diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index 57a834ba1..30e2e5970 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -35,3 +35,9 @@ $(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @echo "(re)installing $(GOBIN)/golangci-lint-v1.61.0" @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.61.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" +MOCKGEN := $(GOBIN)/mockgen-v0.5.0 +$(MOCKGEN): $(BINGO_DIR)/mockgen.mod + @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. + @echo "(re)installing $(GOBIN)/mockgen-v0.5.0" + @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=mockgen.mod -o=$(GOBIN)/mockgen-v0.5.0 "go.uber.org/mock/mockgen" + diff --git a/.bingo/mockgen.mod b/.bingo/mockgen.mod new file mode 100644 index 000000000..14ebb4904 --- /dev/null +++ b/.bingo/mockgen.mod @@ -0,0 +1,5 @@ +module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT + +go 1.23.3 + +require go.uber.org/mock v0.5.0 // mockgen diff --git a/.bingo/mockgen.sum b/.bingo/mockgen.sum new file mode 100644 index 000000000..23f693019 --- /dev/null +++ b/.bingo/mockgen.sum @@ -0,0 +1,8 @@ +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= diff --git a/.bingo/variables.env b/.bingo/variables.env index 149a03e58..cacd5d736 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -14,3 +14,5 @@ GOIMPORTS="${GOBIN}/goimports-v0.26.0" GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.61.0" +MOCKGEN="${GOBIN}/mockgen-v0.5.0" + diff --git a/.github/workflows/aro-hcp-cd.yml b/.github/workflows/aro-hcp-cd.yml index 21eaf0a2c..ac6bf6a4c 100644 --- a/.github/workflows/aro-hcp-cd.yml +++ b/.github/workflows/aro-hcp-cd.yml @@ -41,15 +41,6 @@ cancel-in-progress: false jobs: - is_running_on_fork: - name: 'Ensure PR is submitted from Azure/ARO-HCP' - if: github.event_name != 'workflow_dispatch' - runs-on: ubuntu-latest - steps: - - name: Fail if PR submitted from fork - if: ${{ github.event.pull_request.head.repo.full_name != 'Azure/ARO-HCP' }} - run: core.setFailed('Expected source repository to be Azure/ARO-HCP, re-create PR as a branch of Azure/ARO-HCP') - deploy_global_rg: name: 'Deploy global resources' if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' @@ -79,7 +70,10 @@ cd dev-infrastructure/ # Manage ACR - make acr-svc acr-ocp + make acr acr-svc-cfg acr-ocp-cfg + + # Setup operator roles for platform workload identity + make operator-roles deploy_image_sync_rg: name: 'Deploy Image Sync' diff --git a/.github/workflows/aro-hcp-login-check.yml b/.github/workflows/aro-hcp-login-check.yml new file mode 100644 index 000000000..67a5a03b0 --- /dev/null +++ b/.github/workflows/aro-hcp-login-check.yml @@ -0,0 +1,52 @@ +--- + name: Azure Login Check + on: + workflow_dispatch: + pull_request: + branches: + - main + paths: + - '.github/workflows/aro-hcp-cd.yml' + - '.github/workflows/environment-infra-cd.yml' + - '.github/workflows/services-cd.yml' + - '.github/workflows/services-ci.yml' + - 'config/config.yaml' + - 'dev-infrastructure/**/*.bicep' + - 'dev-infrastructure/**/*.bicepparam' + - 'dev-infrastructure/configurations/*' + - 'frontend/**' + - 'backend/**' + - 'cluster-service/**' + - 'internal/**' + - 'maestro/**' + - 'pko/**' + - 'acm/**' + - 'hypershiftoperator/**' + - 'image-sync/**/' + - 'tooling/image-sync/**' + - 'tooling/templatize/**' + - 'config/*' + types: + - opened + - synchronize + - reopened + - closed + + jobs: + is_running_on_fork: + name: 'Ensure PR is submitted from Azure/ARO-HCP' + if: github.event_name != 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + id-token: 'write' + contents: 'read' + steps: + - name: 'Az CLI login - will fail if PR is submitted from a fork of the repo' + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - name: Fail if PR submitted from fork + if: failure() + run: core.setFailed('Expected source repository to be Azure/ARO-HCP, not ${{ github.event.pull_request.head.repo.full_name }}, re-create PR as a branch of Azure/ARO-HCP') diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 9f0c83469..32e9b82ff 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -12,21 +12,47 @@ on: jobs: test: permissions: + id-token: 'write' contents: 'read' runs-on: 'ubuntu-latest' steps: + - name: "install azure-cli" + uses: "Azure/ARO-HCP@main" + + - uses: azure/use-kubelogin@76597ae0fcbaace21b05e13a2cbf8daee2c6e820 # v1.2 + with: + kubelogin-version: 'v0.1.3' + + - name: 'Az CLI login' + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: 'Set up Go' - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: 'go.work' check-latest: true + - name: 'Regenerate mocks' + run: | + make mocks + if [[ ! -z "$(git status --short)" ]] + then + echo "there are some modified files" + git status + exit 1 + fi + - name: 'Test' - run: make test + run: JOB_ID=${{ github.job }} PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make test + lint: permissions: contents: 'read' @@ -37,7 +63,7 @@ jobs: fetch-depth: 1 - name: 'Set up Go' - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version-file: 'go.work' check-latest: true diff --git a/.github/workflows/environment-infra-cd.yml b/.github/workflows/environment-infra-cd.yml index 925c684b0..a49191d78 100644 --- a/.github/workflows/environment-infra-cd.yml +++ b/.github/workflows/environment-infra-cd.yml @@ -76,6 +76,10 @@ - name: "install azure-cli" uses: "Azure/ARO-HCP@main" + - uses: azure/use-kubelogin@76597ae0fcbaace21b05e13a2cbf8daee2c6e820 # v1.3 + with: + kubelogin-version: 'v0.1.3' + - name: 'Az CLI login' uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 with: @@ -101,7 +105,7 @@ - name: 'Deploy rest' run: | cd dev-infrastructure/ - PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make svc.aks.admin-access svc.enable-aks-metrics + PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make svc.aks.admin-access svc.istio - name: 'CS PR check MSI' if: inputs.deploy_cs_pr_check_deps @@ -134,4 +138,16 @@ - name: 'Deploy or Update' run: | cd dev-infrastructure/ - PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make mgmt mgmt.aks.admin-access mgmt.enable-aks-metrics + PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make mgmt + + - name: 'Az CLI login again' + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: 'Deploy rest' + run: | + cd dev-infrastructure/ + PRINCIPAL_ID=${{ secrets.GHA_PRINCIPAL_ID }} make mgmt.aks.admin-access diff --git a/.github/workflows/services-cd.yml b/.github/workflows/services-cd.yml index d7a7adee1..b3aaa7342 100644 --- a/.github/workflows/services-cd.yml +++ b/.github/workflows/services-cd.yml @@ -33,6 +33,8 @@ jobs: deploy_to_service_cluster: + env: + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' @@ -78,27 +80,31 @@ - name: 'Deploy Istio Configuration' run: | - make isto.deploy + make istio.deploy_pipeline + + - name: 'Deploy ACR Pull Configuration' + run: | + make acrpull.deploy_pipeline - name: 'Deploy Frontend' run: | - make rp.frontend.deploy + make frontend.deploy_pipeline - name: 'Deploy Backend' run: | - make rp.backend.deploy + make backend.deploy_pipeline - name: 'Deploy Cluster Service' run: | - make cs.deploy + make cluster-service.deploy_pipeline - name: 'Deploy Maestro' run: | - make maestro.server.deploy maestro.registration.deploy + make maestro.server.deploy_pipeline maestro.registration.deploy - name: 'Deploy Prometheus Config' run: | - make metrics.deploy + make metrics.deploy_pipeline - name: 'Deploy CS PR check environment dressup' if: inputs.deploy_cs_pr_check_deps @@ -106,6 +112,8 @@ ./svc-deploy.sh ${DEPLOY_ENV} cluster-service svc deploy-pr-env-deps deploy_to_management_cluster: + env: + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} permissions: id-token: 'write' contents: 'read' @@ -141,18 +149,22 @@ cd dev-infrastructure/ make mgmt.aks.kubeconfig - - name: 'Deploy PKO' + - name: 'Deploy ACR Pull Configuration' run: | - make pko.deploy + make acrpull.mgmt.deploy + + # - name: 'Deploy PKO' + # run: | + # make pko.deploy - name: 'Deploy ACM' run: | - make acm.deploy + make acm.deploy_pipeline - name: 'Deploy Maestro Agent' run: | - make maestro.agent.deploy + make maestro.agent.deploy_pipeline - name: 'Deploy Hypershift Operator and External DNS Operator' run: | - make hypershift.deploy + make hypershiftoperator.deploy_pipeline diff --git a/.github/workflows/services-ci.yml b/.github/workflows/services-ci.yml index 1029f627f..6ffece37c 100644 --- a/.github/workflows/services-ci.yml +++ b/.github/workflows/services-ci.yml @@ -157,3 +157,31 @@ run: | cd tooling/image-sync make push + + build_push_package_operator: + permissions: + id-token: 'write' + contents: 'read' + runs-on: 'ubuntu-latest' + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 1 + + - name: "install azure-cli" + if: inputs.push == true + uses: "Azure/ARO-HCP@main" + + - name: 'Az CLI login' + if: inputs.push == true + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Build package operator container image from git@github.com:package-operator/package-operator.git + if: inputs.push == true + run: | + cd pko + make image diff --git a/.github/workflows/services-pr-check.yml b/.github/workflows/services-pr-check.yml new file mode 100644 index 000000000..bd7bb223b --- /dev/null +++ b/.github/workflows/services-pr-check.yml @@ -0,0 +1,165 @@ +--- + name: ARO HCP Service PR Check + env: + DEPLOY_ENV: dev + SKIP_CONFIRM: true + on: + pull_request: + paths: + - '.github/workflows/aro-hcp-cd.yml' + - '.github/workflows/environment-infra-cd.yml' + - '.github/workflows/services-cd.yml' + - '.github/workflows/services-ci.yml' + - 'config/config.yaml' + - 'dev-infrastructure/**/*.bicep' + - 'dev-infrastructure/**/*.bicepparam' + - 'dev-infrastructure/configurations/*' + - 'frontend/**' + - 'backend/**' + - 'cluster-service/**' + - 'internal/**' + - 'maestro/**' + - 'pko/**' + - 'acm/**' + - 'hypershiftoperator/**' + - 'image-sync/**/' + - 'tooling/image-sync/**' + - 'tooling/templatize/**' + - 'config/*' + types: + - opened + - synchronize + - reopened + + jobs: + service_cluster_pr_check: + env: + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} + permissions: + id-token: 'write' + contents: 'read' + runs-on: 'ubuntu-latest' + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 1 + + - name: "install azure-cli" + uses: "Azure/ARO-HCP@main" + + - name: 'Az CLI login' + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 + + # Used to deploy Cluster Service + - name: 'Install oc' + run: | + curl -sfLo - https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.9/openshift-client-linux.tar.gz | tar xzf - + sudo mv oc /usr/local/bin/oc + chmod +x /usr/local/bin/oc + + # Used to deploy Maestro Server, Frontend + - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + with: + version: 'v3.13.3' + + - uses: azure/use-kubelogin@76597ae0fcbaace21b05e13a2cbf8daee2c6e820 # v1.2 + with: + kubelogin-version: 'v0.1.3' + + - name: 'Install helm diff' + run: | + helm plugin install https://github.com/databus23/helm-diff + + - name: 'Dry Run Cluster Service' + run: | + make cluster-service.dry_run + + - name: 'Dry Run Backend' + run: | + make backend.dry_run + + - name: 'Dry Run Frontend' + run: | + make frontend.dry_run + + - name: 'Dry Run Maestro Server' + run: | + make maestro.server.dry_run + + - name: 'Dry Run Istio' + run: | + make istio.dry_run + + - name: 'Dry Run ACR Pull' + run: | + make acrpull.dry_run + + - name: 'Dry Run Metrics' + run: | + make metrics.dry_run + + mgmt_cluster_pr_check: + env: + PRINCIPAL_ID: ${{ secrets.GHA_PRINCIPAL_ID }} + permissions: + id-token: 'write' + contents: 'read' + runs-on: 'ubuntu-latest' + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 1 + + - name: "install azure-cli" + uses: "Azure/ARO-HCP@main" + + - name: 'Az CLI login' + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f # v4.0.0 + + # Used to deploy Cluster Service + - name: 'Install oc' + run: | + curl -sfLo - https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.9/openshift-client-linux.tar.gz | tar xzf - + sudo mv oc /usr/local/bin/oc + chmod +x /usr/local/bin/oc + + # Used to deploy Maestro Server, Frontend + - uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + with: + version: 'v3.13.3' + + - uses: azure/use-kubelogin@76597ae0fcbaace21b05e13a2cbf8daee2c6e820 # v1.2 + with: + kubelogin-version: 'v0.1.3' + + - name: 'Install helm diff' + run: | + helm plugin install https://github.com/databus23/helm-diff + + - name: 'Dry Run ACR Pull on MGMT' + run: | + make acrpull.mgmt.dry_run + + - name: 'Dry Run HypershiftOperator' + run: | + make hypershiftoperator.dry_run + + - name: 'Dry Run Maestro Agent' + run: | + make maestro.agent.dry_run + + - name: 'Dry Run ACM' + run: | + make acm.dry_run diff --git a/.gitignore b/.gitignore index 39b5e0ea2..a3383022b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ env */archive.tar.gz tooling/bin tooling/image-sync/config.yml +**/venv +**/__pycache__ \ No newline at end of file diff --git a/.yamllint.yml b/.yamllint.yml index 22af28228..0fb376210 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -3,6 +3,9 @@ yaml-files: - '*.yaml' - '*.yml' - '.yamllint' +ignore: + - 'acm/deploy/helm/clc-state-metrics/' + - 'acrpull/deploy/helm/acrpull/templates/deployment.yaml' rules: brackets: enable diff --git a/CODEOWNERS b/CODEOWNERS index 421221c53..be29b24bc 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,8 +1,11 @@ -* @bennerv @jharrington22 @mjlshen @SudoBrendan @ulrichschlueter @zgalor -/dev-infrastructure/ @bennerv @geoberle @janboll @jmelis @jonathan34c @mjlshen @niontive @nwnt @SudoBrendan @ulrichschlueter @weinong @whober0521 -/image-sync/ @bennerv @geoberle @janboll @jmelis @jonathan34c @mjlshen @niontive @nwnt @SudoBrendan @ulrichschlueter @weinong @whober0521 -/api/ @bennerv @mbarnes @mjlshen @SudoBrendan -/frontend/ @bennerv @mbarnes @mjlshen @SudoBrendan -/backend/ @bennerv @mbarnes @mjlshen @SudoBrendan -/internal/ @bennerv @mbarnes @mjlshen @SudoBrendan -/tooling/ @bennerv @geoberle @janboll @weinong @whober0521 +* @bennerv @jharrington22 @SudoBrendan @ulrichschlueter @zgalor +go.work* @bennerv @mbarnes @SudoBrendan @mociarain @venkateshsredhat @nanyte25 @kostola +/dev-infrastructure/ @bennerv @geoberle @janboll @jmelis @jonathan34c @SudoBrendan @ulrichschlueter @weinong @whober0521 @tony-schndr @jfchevrette +/image-sync/ @bennerv @geoberle @janboll @jmelis @jonathan34c @SudoBrendan @ulrichschlueter @weinong @whober0521 +/api/ @bennerv @mbarnes @SudoBrendan @mociarain @venkateshsredhat @nanyte25 +/frontend/ @bennerv @mbarnes @SudoBrendan @mociarain @venkateshsredhat @nanyte25 @kostola +/backend/ @bennerv @mbarnes @SudoBrendan @mociarain @venkateshsredhat @nanyte25 @kostola +/internal/ @bennerv @mbarnes @SudoBrendan @mociarain @venkateshsredhat @nanyte25 @kostola +/tooling/ @bennerv @geoberle @janboll @weinong @whober0521 @tony-schndr @jfchevrette +/config/ @bennerv @geoberle @janboll @weinong @whober0521 @tony-schndr @jfchevrette +/metrics/ @bennerv @geoberle @janboll @weinong @whober0521 @tony-schndr @jfchevrette diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27fbd4f52..eafd858f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,15 +11,19 @@ Welcome to the ARO HCP project! We appreciate your interest in contributing. Thi ## Getting Started + To contribute to ARO HCP, follow these steps: -1. Fork the repository to your GitHub account. -2. Clone the forked repository to your local machine. -3. Create a new branch for your changes. -4. Make your changes and commit them. -5. Push your changes to your forked repository. -6. Submit a pull request to the main repository. +1. Clone the ARO-HCP repository to your local machine. +2. Create a new branch for your changes. +3. Make your changes and commit them. +4. Push your changes to ARO-HCP repository. +5. Submit a pull request to the main repository. +If you create a pull request for a branch located in your GitHub fork of +ARO-HCP repository, GitHub `is_running_on_fork` check will raise an error. You +need to create your pull from ARO-HCP repository directly. See +[ARO-8846](https://issues.redhat.com/browse/ARO-8846) for details. ## Contributing Guidelines Please follow these guidelines when contributing to ARO HCP: diff --git a/Makefile b/Makefile index caf2b2dde..575e12c37 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,17 @@ all: test lint # There is currently no convenient way to run tests against a whole Go workspace # https://github.com/golang/go/issues/50745 test: - go list -f '{{.Dir}}/...' -m | xargs go test -tags=$(GOTAGS) -cover + go list -f '{{.Dir}}/...' -m |RUN_TEMPLATIZE_E2E=true xargs go test -timeout 1200s -tags=$(GOTAGS) -cover .PHONY: test +mocks: install-tools + MOCKGEN=${MOCKGEN} go generate ./internal/mocks +.PHONY: mocks + +install-tools: $(BINGO) + $(BINGO) get +.PHONY: install-tools + # There is currently no convenient way to run golangci-lint against a whole Go workspace # https://github.com/golang/go/issues/50745 MODULES := $(shell go list -f '{{.Dir}}/...' -m | xargs) @@ -82,97 +90,76 @@ infra.clean: .PHONY: infra.clean # -# Istio -# - -isto.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) istio svc -.PHONY: isto.deploy - -# -# Metrics -# - -metrics.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) metrics svc -.PHONY: metrics.deploy - -# -# Cluster Service -# - -cs.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) cluster-service svc -.PHONY: cs.deploy - -# -# Maestro -# - -maestro.server.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) maestro/server svc -.PHONY: maestro.server.deploy - -maestro.agent.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) maestro/agent mgmt -.PHONY: maestro.agent.deploy - -maestro.registration.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) maestro/registration svc -.PHONY: maestro.registration.deploy - -maestro: maestro.server.deploy maestro.agent.deploy maestro.registration.deploy -.PHONY: maestro - -# -# Resource Provider -# - -rp.frontend.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) frontend svc -.PHONY: rp.frontend.deploy - -rp.backend.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) backend svc -.PHONY: rp.backend.deploy - -# -# PKO -# - -pko.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) pko mgmt -.PHONY: pko.deploy - -# -# ACM -# - -acm.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) acm mgmt -.PHONY: acm.deploy - -# -# Hypershift -# - -hypershift.deploy: - @./svc-deploy.sh $(DEPLOY_ENV) hypershiftoperator mgmt -.PHONY: hypershift.deploy - -# -# Deploy ALL components -# - -deploy.svc.all: isto.deploy metrics.deploy maestro.server.deploy maestro.registration.deploy cs.deploy rp.frontend.deploy rp.backend.deploy -.PHONY: deploy.svc.all - -deploy.mgmt.all: maestro.agent.deploy acm.deploy hypershift.deploy -.PHONY: deploy.mgmt.all - -deploy.all: deploy.svc.all deploy.mgmt.all -.PHONY: deploy.all +# Services +# + +# Service Deployment Conventions: +# +# - Services are deployed in aks clusters (either svc or mgmt), which are +# provisioned via infra section above +# - Makefile targets to deploy services ends with ".deploy" suffix +# - To deploy all services on svc or mgmt cluster, we have special targets +# `svc.deployall` and `mgmt.deployall`, and `deployall` deploys everithing. +# - Placement of a service is controlled via services_svc and services_mgmt +# variables +# - If the name of the service contains a dot, it's interpreted as directory +# separator "/" (used for maestro only). + +# Services deployed on "svc" aks cluster +services_svc = maestro.registration +# Services deployed on "mgmt" aks cluster(s) +services_mgmt = +# List of all services +services_all = $(join services_svc,services_mgmt) + +.PHONY: $(addsuffix .deploy, $(services_all)) deployall svc.deployall mgmt.deployall listall list clean + +# Service deployment on either svc or mgmt aks cluster, a service name +# needs to be listed either in services_svc or services_mgmt variable (wich +# defines where it will be deployed). +%.deploy: + $(eval export dirname=$(subst .,/,$(basename $@))) + @if [ $(words $(filter $(basename $@), $(services_svc))) = 1 ]; then\ + ./svc-deploy.sh $(DEPLOY_ENV) $(dirname) svc;\ + elif [ $(words $(filter $(basename $@), $(services_mgmt))) = 1 ]; then\ + ./svc-deploy.sh $(DEPLOY_ENV) $(dirname) mgmt;\ + else\ + echo "'$(basename $@)' is not to be deployed on neither svc nor mgmt cluster";\ + exit 1;\ + fi + + +# Pipelines section +# This sections is used to reference pipeline runs and should replace +# the usage of `svc-deploy.sh` script in the future. +services_svc_pipelines = istio acrpull metrics backend frontend cluster-service maestro.server +# Don't apply mgmt cluster fixes to personal clusters +ifeq ($(DEPLOY_ENV), personal-dev) + services_mgmt_pipelines = hypershiftoperator maestro.agent acm +else + services_mgmt_pipelines = mgmt-fixes hypershiftoperator maestro.agent acm +endif +%.deploy_pipeline: + $(eval export dirname=$(subst .,/,$(basename $@))) + ./templatize.sh $(DEPLOY_ENV) -p ./$(dirname)/pipeline.yaml -s deploy -P run -c public + +%.dry_run: + $(eval export dirname=$(subst .,/,$(basename $@))) + ./templatize.sh $(DEPLOY_ENV) -p ./$(dirname)/pipeline.yaml -s deploy -P run -c public -d + +svc.deployall: $(addsuffix .deploy_pipeline, $(services_svc_pipelines)) $(addsuffix .deploy, $(services_svc)) +mgmt.deployall: $(addsuffix .deploy, $(services_mgmt)) $(addsuffix .deploy_pipeline, $(services_mgmt_pipelines)) +deployall: svc.deployall mgmt.deployall + +acrpull.mgmt.deploy: + ./templatize.sh $(DEPLOY_ENV) -p ./acrpull/pipeline.yaml -s deploy-mgmt -P run -c public + +acrpull.mgmt.dry_run: + ./templatize.sh $(DEPLOY_ENV) -p ./acrpull/pipeline.yaml -s deploy-mgmt -P run -c public -d + +listall: + @echo svc: ${services_svc} + @echo mgmt: ${services_mgmt} list: @grep '^[^#[:space:]].*:' Makefile -.PHONY: list diff --git a/README.md b/README.md index 4c02e6a46..5a4c9b8c7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Description The RP for the ARO-HCP project. -The components for HCP are each encpasulated in a top-level directory and each directory contains it's own makefile. +The components for HCP are each encapsulated in a top-level directory and each directory contains it's own makefile. ## Development setup diff --git a/acm/Makefile b/acm/Makefile index 3bd29bd7c..84530b91c 100644 --- a/acm/Makefile +++ b/acm/Makefile @@ -1,29 +1,35 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install --wait --wait-for-jobs -MCE_OPERATOR_BUNDLE_IMAGE ?= quay.io/acm-d/mce-operator-bundle:v2.7.0-110 -REGISTRY ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io/acm-d-mce -# once MCE 2.7 is released, we can find the official bundle image here -# https://catalog.redhat.com/software/containers/multicluster-engine/mce-operator-bundle/6160406290fb938ecf6009c6 +MCE_OPERATOR_BUNDLE_IMAGE ?= registry.redhat.io/multicluster-engine/mce-operator-bundle:v2.7.0-116 +REGISTRY ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io MCE_OPERATOR_BUNDLE_FILE = mce-operator-bundle.tgz HELM_BASE_DIR = deploy/helm MCE_CHART_DIR = ${HELM_BASE_DIR}/multicluster-engine +CLC_CHART_DIR = ${HELM_BASE_DIR}/clc-state-metrics MCE_CONFIG_DIR = ${HELM_BASE_DIR}/multicluster-engine-config MCE_NS = multicluster-engine POLICY_HELM_REPO = https://github.com/stolostron/mce-install-kube.git +POLICY_HELM_REPO_BRANCH = release-2.12 deploy: @kubectl create namespace ${MCE_NS} --dry-run=client -o json | kubectl apply -f - - helm upgrade --install --wait --wait-for-jobs \ + ${HELM_CMD} \ mce ${MCE_CHART_DIR} \ --namespace ${MCE_NS} \ --set imageRegistry=${REGISTRY} - helm upgrade --install --wait --wait-for-jobs \ + ${HELM_CMD} \ mce-config ${MCE_CONFIG_DIR} \ - --namespace ${MCE_NS} + --namespace ${MCE_NS} \ + --set global.registryOverride=${REGISTRY} + ${HELM_CMD} \ + clc-state-metrics ${CLC_CHART_DIR} \ + --namespace ${MCE_NS} \ + --set global.imageOverrides.clusterlifecycle_state_metrics=${REGISTRY}/multicluster-engine/clusterlifecycle-state-metrics-rhel9@sha256:${CLC_STATE_METRICS_IMAGE_DIGEST} \ + --set global.namespace=${MCE_NS} + helm-chart: @podman pull --arch amd64 ${MCE_OPERATOR_BUNDLE_IMAGE} @@ -37,14 +43,11 @@ helm-chart: @echo "Cloning remote mce-install-kube repository..." TMP_DIR=$$(mktemp -d) && \ - git clone ${POLICY_HELM_REPO} $$TMP_DIR && \ + git clone --branch ${POLICY_HELM_REPO_BRANCH} ${POLICY_HELM_REPO} $$TMP_DIR && \ rm -rf ${MCE_CONFIG_DIR}/charts && \ mkdir -p ${MCE_CONFIG_DIR}/charts && \ cp -r $$TMP_DIR/policy ${MCE_CONFIG_DIR}/charts && \ rm -rf $$TMP_DIR @echo "Helm chart imported successfully." -import-chart: - - .PHONY: deploy helm-chart diff --git a/acm/README.md b/acm/README.md index d476ae000..54c19442b 100644 --- a/acm/README.md +++ b/acm/README.md @@ -2,16 +2,26 @@ This folder contains helm charts and automation to managed helm charts for the ACM components `MCE` and `policy`. +## Structure + Installation and configuration are split into two individual helm charts -## multicluster-engine +### multicluster-engine This helm chart installs the MCE operator. The chart is autogenerated from an OLM release-bundle of MCE by running `make helm-chart`. The resulting chart is then commited into the repository. To update MCE, change the `MCE_OPERATOR_BUNDLE_IMAGE` variable in the Makefile. If you are testing pre-releases from the `quay.io/acm-d` organization, make sure the `REGISTRY` env var in the Makefile is set to `${ARO_HCP_IMAGE_ACR}.azurecr.io/acm-d-mce`. For production releases set it to `${ARO_HCP_IMAGE_ACR}.azurecr.io` instead. -## multicluster-engine-config +### multicluster-engine-config This helm chart configures MCE and installs the `policy` component on top of it. The subchart for `policy` is imported into this repo by running `make helm-chart`. It can be found [in the ACM upstream Github org](https://github.com/stolostron/mce-install-kube) and is maintained by the ACM team. Updating `policy` needs to be done with care for now, since the content of the helm chart repo is not tagged. We are working on it. + +## Updating charts + +To update the `multicluster-engine` chart, lookup the desired install MCE OLM bundle on [https://catalog.redhat.com](https://catalog.redhat.com/software/containers/multicluster-engine/mce-operator-bundle/6160406290fb938ecf6009c6) and update the `MCE_OPERATOR_BUNDLE_IMAGE` variable in `Makefile`. + +To update the `multicluster-engine-config/policy` subchart, update the `POLICY_HELM_REPO_BRANCH` variable in the `Makefile` for the desired release. + +Run `make helm-chart` to update all charts. Review and commit all changes to the `deploy/helm` directory. diff --git a/acm/config.tmpl.mk b/acm/config.tmpl.mk deleted file mode 100644 index 200f6bd2a..000000000 --- a/acm/config.tmpl.mk +++ /dev/null @@ -1 +0,0 @@ -ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} diff --git a/acm/deploy/helm/clc-state-metrics/Chart.yaml b/acm/deploy/helm/clc-state-metrics/Chart.yaml new file mode 100644 index 000000000..e6211d222 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/Chart.yaml @@ -0,0 +1,7 @@ +# Original source https://github.com/stolostron/mce-install-kube/tree/main/clc-state-metrics +# TODO: Remove this chart and enable via MCE once MCE 2.8.0 is released (Feb 2025) +apiVersion: v2 +name: clusterlifecycle-state-metrics +description: A Helm chart for clusterlifecycle-state-metrics +version: 2.7.0 +appVersion: 2.7.0 diff --git a/acm/deploy/helm/clc-state-metrics/templates/_helpers.tpl b/acm/deploy/helm/clc-state-metrics/templates/_helpers.tpl new file mode 100644 index 000000000..303f97c33 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/_helpers.tpl @@ -0,0 +1,12 @@ +{{- define "installNamespace" }} +{{- if .Values.global.namespace }} +{{- printf "%s" .Values.global.namespace }} +{{- else }} +{{- printf "multicluster-engine" }} +{{- end }} +{{- end }} + +{{- define "commonCN" }} +{{- printf "clusterlifecycle-state-metrics-v2.%s.svc" .Values.global.namespace }} +{{- end }} + diff --git a/acm/deploy/helm/clc-state-metrics/templates/cert-secret.yaml b/acm/deploy/helm/clc-state-metrics/templates/cert-secret.yaml new file mode 100644 index 000000000..b2189db07 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/cert-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + name: clusterlifecycle-state-metrics-certs + namespace: {{ .Values.global.namespace }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "0" +type: kubernetes.io/tls +{{- if .Release.IsUpgrade }} +data: {{ (lookup "v1" "Secret" (include "installNamespace" .) "clusterlifecycle-state-metrics-certs").data }} +{{ else }} +{{ $ca := genCA (include "commonCN" .) 365 -}} +data: + tls.crt: {{ $ca.Cert | b64enc }} + tls.key: {{ $ca.Key | b64enc }} +{{- end }} diff --git a/acm/deploy/helm/clc-state-metrics/templates/clc-state-metrics.servicemonitor.yaml b/acm/deploy/helm/clc-state-metrics/templates/clc-state-metrics.servicemonitor.yaml new file mode 100644 index 000000000..8e596e211 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/clc-state-metrics.servicemonitor.yaml @@ -0,0 +1,17 @@ +apiVersion: azmonitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: clusterlifecycle-state-metrics-v2 + namespace: {{ .Values.global.namespace }} + labels: + clc-app: clusterlifecycle-state-metrics-v2 +spec: + selector: + matchLabels: + clc-app: clusterlifecycle-state-metrics-v2 + namespaceSelector: + matchNames: + - {{ .Values.global.namespace }} + endpoints: + - port: http + scheme: http diff --git a/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole.yaml b/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole.yaml new file mode 100644 index 000000000..e0e99e797 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole.yaml @@ -0,0 +1,55 @@ +# Copyright Contributors to the Open Cluster Management project + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Values.org }}:cluster-lifecycle:clusterlifecycle-state-metrics-v2 +rules: +# Allow hub to manage configmap for leader selection +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - update + - get + - delete +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +# Allow hub to monitor and update status of csr +- apiGroups: ["hive.openshift.io"] + resources: ["clusterdeployments"] + verbs: ["get"] +- apiGroups: ["internal.open-cluster-management.io"] + resources: ["managedclusterinfos"] + verbs: ["get","list","watch"] +- apiGroups: ["cluster.open-cluster-management.io"] + resources: ["managedclusters"] + verbs: ["get","list","watch"] +# Allow to query the CVO on the Hub Cluster to get the ClusterId +- apiGroups: ["config.openshift.io"] + resources: ["clusterversions"] + verbs: ["get"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: [""] + resources: ["pods","services","endpoints"] + verbs: ["get","list","watch"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +# Allow hub to monitor add-ons & manifestworks +- apiGroups: ["addon.open-cluster-management.io"] + resources: ["managedclusteraddons"] + verbs: ["get","list","watch"] +- apiGroups: ["work.open-cluster-management.io"] + resources: ["manifestworks"] + verbs: ["get","list","watch"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] diff --git a/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole_binding.yaml b/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole_binding.yaml new file mode 100644 index 000000000..e81d979ac --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/metrics-clusterrole_binding.yaml @@ -0,0 +1,14 @@ +# Copyright Contributors to the Open Cluster Management project + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Values.org }}:cluster-lifecycle:clusterlifecycle-state-metrics-v2 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Values.org }}:cluster-lifecycle:clusterlifecycle-state-metrics-v2 +subjects: + - kind: ServiceAccount + name: clusterlifecycle-state-metrics-v2 + namespace: {{ .Values.global.namespace }} diff --git a/acm/deploy/helm/clc-state-metrics/templates/metrics-deployment.yaml b/acm/deploy/helm/clc-state-metrics/templates/metrics-deployment.yaml new file mode 100644 index 000000000..00ee419fa --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/metrics-deployment.yaml @@ -0,0 +1,128 @@ +# Copyright Contributors to the Open Cluster Management project + +kind: Deployment +apiVersion: apps/v1 +metadata: + name: clusterlifecycle-state-metrics-v2 + namespace: {{ .Values.global.namespace }} +spec: + replicas: 2 + selector: + matchLabels: + app: clusterlifecycle-state-metrics-v2 + template: + metadata: + labels: + app: clusterlifecycle-state-metrics-v2 + ocm-antiaffinity-selector: "clusterlifecycle-state-metrics-v2" + spec: + {{- if .Values.global.pullSecret }} + imagePullSecrets: + - name: {{ .Values.global.pullSecret }} + {{- end }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: ocm-antiaffinity-selector + operator: In + values: + - clusterlifecycle-state-metrics-v2 + topologyKey: topology.kubernetes.io/zone + weight: 70 + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: ocm-antiaffinity-selector + operator: In + values: + - clusterlifecycle-state-metrics-v2 + topologyKey: kubernetes.io/hostname + weight: 35 + serviceAccountName: clusterlifecycle-state-metrics-v2 + containers: + - name: clusterlifecycle-state-metrics + image: "{{ .Values.global.imageOverrides.clusterlifecycle_state_metrics }}" + imagePullPolicy: {{ .Values.global.pullPolicy }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + resources: + requests: + memory: "32Mi" + cpu: "25m" + limits: + memory: "2Gi" + cpu: "500m" + args: + - "--http-port=8080" + - "--http-telemetry-port=8081" + - "--https-port=8443" + - "--https-telemetry-port=8444" + - "--tls-crt-file=/var/run/clusterlifecycle-state-metrics/tls.crt" + - "--tls-key-file=/var/run/clusterlifecycle-state-metrics/tls.key" +{{- if .Values.hubconfig.hubType }} + - "--hub-type={{ .Values.hubconfig.hubType }}" +{{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: GOMEMLIMIT + value: "1892MiB" +{{- if .Values.hubconfig.proxyConfigs }} + - name: HTTP_PROXY + value: {{ .Values.hubconfig.proxyConfigs.HTTP_PROXY }} + - name: HTTPS_PROXY + value: {{ .Values.hubconfig.proxyConfigs.HTTPS_PROXY }} + - name: NO_PROXY + value: {{ .Values.hubconfig.proxyConfigs.NO_PROXY }} +{{- end }} + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 5 + volumeMounts: + - mountPath: "/var/run/clusterlifecycle-state-metrics" + name: certs + readOnly: true + securityContext: + {{- if .Values.global.deployOnOCP }} + {{- if semverCompare ">=4.11.0" .Values.hubconfig.ocpVersion }} + seccompProfile: + type: RuntimeDefault + {{- end }} + {{- end }} + volumes: + - name: certs + secret: + secretName: clusterlifecycle-state-metrics-certs +{{- with .Values.hubconfig.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} +{{- end }} +{{- with .Values.hubconfig.tolerations }} + tolerations: + {{- range . }} + - {{ if .Key }} key: {{ .Key }} {{- end }} + {{ if .Operator }} operator: {{ .Operator }} {{- end }} + {{ if .Value }} value: {{ .Value }} {{- end }} + {{ if .Effect }} effect: {{ .Effect }} {{- end }} + {{ if .TolerationSeconds }} tolerationSeconds: {{ .TolerationSeconds }} {{- end }} + {{- end }} +{{- end }} diff --git a/acm/deploy/helm/clc-state-metrics/templates/metrics-service.yaml b/acm/deploy/helm/clc-state-metrics/templates/metrics-service.yaml new file mode 100644 index 000000000..99242b040 --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/metrics-service.yaml @@ -0,0 +1,20 @@ +# Copyright Contributors to the Open Cluster Management project + +apiVersion: v1 +kind: Service +metadata: + name: clusterlifecycle-state-metrics-v2 + namespace: {{ .Values.global.namespace }} + labels: + clc-app: clusterlifecycle-state-metrics-v2 + annotations: + service.beta.openshift.io/serving-cert-secret-name: clusterlifecycle-state-metrics-certs +spec: + type: ClusterIP + ports: + - name: http + port: 8080 + targetPort: 8080 + protocol: TCP + selector: + app: clusterlifecycle-state-metrics-v2 diff --git a/acm/deploy/helm/clc-state-metrics/templates/metrics-service_account.yaml b/acm/deploy/helm/clc-state-metrics/templates/metrics-service_account.yaml new file mode 100644 index 000000000..120e1ebdd --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/templates/metrics-service_account.yaml @@ -0,0 +1,7 @@ +# Copyright Contributors to the Open Cluster Management project + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: clusterlifecycle-state-metrics-v2 + namespace: {{ .Values.global.namespace }} diff --git a/acm/deploy/helm/clc-state-metrics/values.yaml b/acm/deploy/helm/clc-state-metrics/values.yaml new file mode 100644 index 000000000..05c956a2a --- /dev/null +++ b/acm/deploy/helm/clc-state-metrics/values.yaml @@ -0,0 +1,15 @@ +global: + imageOverrides: + clusterlifecycle_state_metrics: "" + templateOverrides: {} + pullSecret: "" + namespace: multicluster-engine + hubSize: Small + deployOnOCP: "false" +hubconfig: + nodeSelector: {} + proxyConfigs: {} + replicaCount: 1 + tolerations: [] + ocpVersion: "4.17.0" +org: open-cluster-management diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/Chart.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/Chart.yaml index 21157ea9c..84dcdbfa0 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/Chart.yaml @@ -1,11 +1,11 @@ apiVersion: v2 -appVersion: 2.12.0 -version: 2.12.0 +appVersion: v2.12.0 +version: v2.12.0 description: A Helm chart for ACM addons name: policy dependencies: - name: grc - version: "2.12.0" + version: "v2.12.0" - name: cluster-lifecycle - version: "2.12.0" + version: "v2.12.0" diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/Chart.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/Chart.yaml index 31da13e4c..d1da32b98 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/Chart.yaml @@ -2,8 +2,8 @@ # Copyright Contributors to the Open Cluster Management project apiVersion: v2 -appVersion: 2.12.0 +appVersion: v2.12.0 description: Helm chart for deploying the cluster lifecycle kubeVersion: ">=1.11.0-0" name: cluster-lifecycle -version: 2.12.0 +version: v2.12.0 diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/templates/klusterlet-addon-deployment.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/templates/klusterlet-addon-deployment.yaml index 125442e7d..1cd430e69 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/templates/klusterlet-addon-deployment.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/cluster-lifecycle/templates/klusterlet-addon-deployment.yaml @@ -79,7 +79,7 @@ spec: {{- end }} containers: - name: klusterlet-addon-controller - image: "{{ .Values.global.imageOverrides.klusterlet_addon_controller }}" + image: "{{ .Values.global.registryOverride}}/{{ .Values.global.imageOverrides.klusterlet_addon_controller }}" imagePullPolicy: {{ .Values.global.pullPolicy }} securityContext: allowPrivilegeEscalation: false diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/Chart.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/Chart.yaml index 3dd9d60bd..ca17401e3 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/Chart.yaml @@ -2,10 +2,10 @@ # Copyright Contributors to the Open Cluster Management project apiVersion: v2 -appVersion: 2.12.0 +appVersion: v2.12.0 description: A Helm chart for multicloud grc keywords: - acm - grc name: grc -version: 2.12.0 +version: v2.12.0 diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-addon-controller.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-addon-controller.yaml index a17d5d85d..3adf2adc5 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-addon-controller.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-addon-controller.yaml @@ -69,10 +69,10 @@ spec: apiVersion: v1 fieldPath: metadata.name - name: CONFIG_POLICY_CONTROLLER_IMAGE - value: {{ .Values.global.imageOverrides.config_policy_controller }} + value: "{{ .Values.global.registryOverride}}/{{ .Values.global.imageOverrides.config_policy_controller }}" - name: GOVERNANCE_POLICY_FRAMEWORK_ADDON_IMAGE - value: {{ .Values.global.imageOverrides.governance_policy_framework_addon }} - image: {{ .Values.global.imageOverrides.governance_policy_addon_controller }} + value: "{{ .Values.global.registryOverride}}/{{ .Values.global.imageOverrides.governance_policy_framework_addon }}" + image: "{{ .Values.global.registryOverride}}/{{ .Values.global.imageOverrides.governance_policy_addon_controller }}" imagePullPolicy: IfNotPresent name: manager resources: diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-propagator.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-propagator.yaml index 32961c6d9..5d9fbe2db 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-propagator.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/templates/grc-policy-propagator.yaml @@ -81,7 +81,7 @@ spec: fieldPath: metadata.name - name: OPERATOR_NAME value: governance-policy-propagator - image: {{ .Values.global.imageOverrides.governance_policy_propagator }} + image: "{{ .Values.global.registryOverride}}/{{ .Values.global.imageOverrides.governance_policy_propagator }}" imagePullPolicy: IfNotPresent livenessProbe: exec: diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/values.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/values.yaml index d727960d3..dd1f1531c 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/values.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/charts/grc/values.yaml @@ -1,6 +1,7 @@ # Copyright (c) 2020 Red Hat, Inc. global: + registryOverride: "" imageOverrides: governance_policy_propagator: "" governance_policy_addon_controller: "" diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/crds/policy.open-cluster-management.io_policyautomations.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/crds/policy.open-cluster-management.io_policyautomations.yaml index 2a5ed4d4b..6386db481 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/crds/policy.open-cluster-management.io_policyautomations.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/crds/policy.open-cluster-management.io_policyautomations.yaml @@ -56,8 +56,8 @@ spec: x-kubernetes-preserve-unknown-fields: true jobTtl: description: >- - JobTTL sets the time to live for the Kubernetes AnsibleJob object after the Ansible job run has - finished. + JobTTL sets the time to live for the Kubernetes Job object after the Ansible job playbook run + has finished. type: integer name: description: Name of the Ansible Template to run in Ansible Automation @@ -91,6 +91,7 @@ spec: minimum: 0 type: integer eventHook: + default: noncompliant description: >- EventHook specifies the compliance state that initiates automation. This must be set to "noncompliant". @@ -116,7 +117,6 @@ spec: type: string required: - automationDef - - eventHook - mode - policyRef type: object diff --git a/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml b/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml index 591cbd7d8..4bc148748 100644 --- a/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml +++ b/acm/deploy/helm/multicluster-engine-config/charts/policy/values.yaml @@ -1,18 +1,12 @@ global: + registryOverride: "registry.redhat.io" imageOverrides: - # upstream images - governance_policy_propagator: "quay.io/stolostron/governance-policy-propagator:2.12.0-SNAPSHOT-2024-09-30-01-46-06" - governance_policy_addon_controller: "quay.io/stolostron/governance-policy-addon-controller:2.12.0-SNAPSHOT-2024-09-30-01-46-06" - config_policy_controller: "quay.io/stolostron/config-policy-controller:2.12.0-SNAPSHOT-2024-09-30-01-46-06" - governance_policy_framework_addon: "quay.io/stolostron/governance-policy-framework-addon:2.12.0-SNAPSHOT-2024-09-30-01-46-06" - klusterlet_addon_controller: "quay.io/stolostron/klusterlet-addon-controller:2.12.0-SNAPSHOT-2024-09-30-01-46-06" + governance_policy_propagator: "rhacm2/governance-policy-propagator-rhel9@sha256:f2fa1a7c7af6379eda44a691de57eb59dc8068aadb98504df7ef4a5e059a0cfa" + governance_policy_addon_controller: "rhacm2/acm-governance-policy-addon-controller-rhel9@sha256:7b2f432d7ea6b9eb9c4df6df88ae3d5bfc261a8d24a5146a04d3465a41d99e10" + config_policy_controller: "rhacm2/config-policy-controller-rhel9@sha256:bad96b2cd7efd604b3ef8092eb72c5a7d33b39732a1a8fe995aa197ead7a5d31" + governance_policy_framework_addon: "rhacm2/acm-governance-policy-framework-addon-rhel9@sha256:a5373e3aed5c8e0ac1427599c3801eccd3b4ff4bdc3f9c0cd7083ff3e34433b3" + klusterlet_addon_controller: "rhacm2/klusterlet-addon-controller-rhel9@sha256:f8188bc955dbc635031e765fb09015926eb350a7484e6c9f2e0af6020e02aa30" - # images in ACM 2.11.2 - # governance_policy_propagator: "registry.redhat.io/rhacm2/governance-policy-propagator-rhel9@sha256:af848e7e31d8ec9b5ad1896a5d5ccc67f320a7740245c190ba8a76757984e65b" - # governance_policy_addon_controller: "registry.redhat.io/rhacm2/acm-governance-policy-addon-controller-rhel9@sha256:fc0708f0a6d5266fb544f41b61d9697d370c8c5e297e4e3f13de8656f9c2b049" - # config_policy_controller: "registry.redhat.io/rhacm2/config-policy-controller-rhel9@sha256:cecf914d7fb7759a4f512c1ec53a077dcb1c7e405c22a5bf6af1bf5878cf3c42" - # governance_policy_framework_addon: "registry.redhat.io/rhacm2/acm-governance-policy-framework-addon-rhel9@sha256:a4880f6e82d2b82606203ea855d0418bb29b3d4535f8bc7a9ef4074258c18674" - # klusterlet_addon_controller: "registry.redhat.io/rhacm2/klusterlet-addon-controller-rhel9@sha256:478e3e6cda0d74f43b0f05911d023344108a5cd79d57d5cc9f268ad064848a00" namespace: multicluster-engine pullSecret: open-cluster-management-image-pull-credentials diff --git a/acm/deploy/helm/multicluster-engine-config/values.yaml b/acm/deploy/helm/multicluster-engine-config/values.yaml index d68a71eca..566c559ca 100644 --- a/acm/deploy/helm/multicluster-engine-config/values.yaml +++ b/acm/deploy/helm/multicluster-engine-config/values.yaml @@ -2,6 +2,9 @@ localCluster: kubeApiUrl: https://kubernetes.default.svc addonConfig: applicationManagerEnabled: false - certPolicyControllerEnabled: true + certPolicyControllerEnabled: false policyControllerEnabled: true searchCollectorEnabled: false + +global: + registryOverride: "" diff --git a/acm/deploy/helm/multicluster-engine/Chart.yaml b/acm/deploy/helm/multicluster-engine/Chart.yaml index 131abac41..63b86082c 100644 --- a/acm/deploy/helm/multicluster-engine/Chart.yaml +++ b/acm/deploy/helm/multicluster-engine/Chart.yaml @@ -7,6 +7,6 @@ keywords: - multiclusterengine name: multicluster-engine sources: -- oci://quay.io/acm-d/mce-operator-bundle:v2.7.0-110 +- oci://registry.redhat.io/multicluster-engine/mce-operator-bundle:v2.7.0-116 type: application version: 2.7.0 diff --git a/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml b/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml index b50db827f..183031900 100644 --- a/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml +++ b/acm/deploy/helm/multicluster-engine/templates/multicluster-engine-operator.deployment.yaml @@ -57,80 +57,80 @@ spec: fieldRef: fieldPath: metadata.namespace - name: OPERAND_IMAGE_ADDON_MANAGER - value: '{{ .Values.imageRegistry }}/multicluster-engine/addon-manager-rhel9@sha256:3a2d6035027382c001eff5ec49c50804818d36fa40defc8b36487a8bb5c74637' + value: '{{ .Values.imageRegistry }}/multicluster-engine/addon-manager-rhel9@sha256:25cdce9461a24748fc6631fa4394b813deabdb27d0c95956508d2a38c504a6a9' - name: OPERAND_IMAGE_ASSISTED_IMAGE_SERVICE - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-image-service-rhel9@sha256:dfec5080d0d7e71834648c29c367aff336371b197fa3301bdcdaed0f148a1440' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-image-service-rhel9@sha256:e1623f5819b3c3a1c79584846eb09c92583a3e88b47fd421d6b72ceccee857d0' - name: OPERAND_IMAGE_ASSISTED_INSTALLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-rhel9@sha256:23c0fc8624a2d0f6257d9e02cc13a15c0b04a3bf514d87c94b1fc47e9fe23b07' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-rhel9@sha256:b030580e10ae9daa3832e1755e80b0638e5de1673b5bca2e34c742e507a900cd' - name: OPERAND_IMAGE_ASSISTED_INSTALLER_AGENT - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-agent-rhel9@sha256:9b05bab596ab41ec0fc734202dd2d170aef57dccc3aed86577f43d0b44b74a72' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-agent-rhel9@sha256:2e71067d7e28e0b9e8463653be16b9bad711f3f05b0007dabd5282b88f32df05' - name: OPERAND_IMAGE_ASSISTED_INSTALLER_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-controller-rhel9@sha256:86bef67d5275612a26f4c738691951eb75c5f591ccafccd26c68dc9f5dbe3c59' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-installer-controller-rhel9@sha256:07eb099581b1c8b65a05e80f876b58ac4fa9e3435634db52de5a22010cb7aeff' - name: OPERAND_IMAGE_ASSISTED_SERVICE_8 - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-service-8-rhel8@sha256:3b21e10c2d71d7587ea863fc99175ac9e5607bc54ee067d0be42769f8de2ef10' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-service-8-rhel8@sha256:e8260d0a6187638cc1a2219d553b8a681a026c80621335c6984675cef308aa57' - name: OPERAND_IMAGE_ASSISTED_SERVICE_9 - value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-service-9-rhel9@sha256:47328c195447b5928aee72c7d4039e46ed955c2df27b22f3dda936220314b81c' + value: '{{ .Values.imageRegistry }}/multicluster-engine/assisted-service-9-rhel9@sha256:0e34d52ac6173678a7a7ebdc0ea9554c47876f2dcb4526a815a541d3762a5a5f' - name: OPERAND_IMAGE_BACKPLANE_MUST_GATHER - value: '{{ .Values.imageRegistry }}/multicluster-engine/must-gather-rhel9@sha256:5bf03dd58dabd95c7243a3b27ecf6a703803dd1904a5714401581ceca84ca7cf' + value: '{{ .Values.imageRegistry }}/multicluster-engine/must-gather-rhel9@sha256:8d7dd9a280551430eb9cb57709c8e0f6dc135bab306ed34b57b13d07d05e9719' - name: OPERAND_IMAGE_CLUSTER_API - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-rhel9@sha256:4f9f2ee158f090d8e958988ceb0cec56271531cbc6be9b128c5d18e9777829da' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-rhel9@sha256:13276174e2955fdee35e2e1fa84de1be25229da2672b37f6c9ad4ed2a3eb5954' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_AGENT - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-provider-agent-rhel9@sha256:75fb058973d276f6dd33cc3b07b484794531c41882e03516fc117e7f9e780eef' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-provider-agent-rhel9@sha256:883427857d3960b365d0d8714b867f5a0c712be5a053b41779bc7feb2b95207d' - name: OPERAND_IMAGE_CLUSTER_API_PROVIDER_KUBEVIRT - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-provider-kubevirt-rhel9@sha256:a0077b2c2a59f9c8fbdd8a3605f0d461060e43f0bd0ad29ac3027995b04ef852' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-api-provider-kubevirt-rhel9@sha256:0abf3c9c3db13749b4399de6ef162a00ec63ae18e6dc6e4c96a4d332f83bea18' - name: OPERAND_IMAGE_CLUSTERCLAIMS_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/clusterclaims-controller-rhel9@sha256:ae228c4d3191b04cbd9c534e17e944d17b9cce5957012b3d672d89134d4e98fc' + value: '{{ .Values.imageRegistry }}/multicluster-engine/clusterclaims-controller-rhel9@sha256:4aeb801c624bffaa44c108bbad030f44cb69699564b06b7c12143d0c5b5db61c' - name: OPERAND_IMAGE_CLUSTER_CURATOR_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-curator-controller-rhel9@sha256:a1b70852434d3c29ebfe8717e529a4e91c65009ccb4b7d05e3b1ff466b252113' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-curator-controller-rhel9@sha256:f2025f357f1b7c3b516a66ece247a50fcceb048dff758944098efe672b020db2' - name: OPERAND_IMAGE_CLUSTER_IMAGE_SET_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-image-set-controller-rhel9@sha256:64f3a1ccfa1c15f8f0cce33a37082919544f97fecccaa389436704043052b579' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-image-set-controller-rhel9@sha256:d082cea8410f0f5f3684cbc1583519f17300d119ef3fb04e7876f03ea7b53da3' - name: OPERAND_IMAGE_CLUSTERLIFECYCLE_STATE_METRICS - value: '{{ .Values.imageRegistry }}/multicluster-engine/clusterlifecycle-state-metrics-rhel9@sha256:cebc895269458c2652de11e7b060f2765491ad9494d432dd6088756042ddc443' + value: '{{ .Values.imageRegistry }}/multicluster-engine/clusterlifecycle-state-metrics-rhel9@sha256:bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7' - name: OPERAND_IMAGE_CLUSTER_PROXY_ADDON - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-proxy-addon-rhel9@sha256:0fe206e859c6ff4000d1a26641890fae10a95f7cddae6bc0472b05d685ca618e' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-proxy-addon-rhel9@sha256:87a3811feac15c463e6410d6d64653cc5b22915a1c9408d41713b54c94ffb6c1' - name: OPERAND_IMAGE_CLUSTER_PROXY - value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-proxy-rhel9@sha256:241ce844db29e2f0af726bcb262bf9214702664121729da8b785c6283919dffe' + value: '{{ .Values.imageRegistry }}/multicluster-engine/cluster-proxy-rhel9@sha256:3b2f833933763026fc0a5e3e86872d32432a50389a9c7d2f71e17d501bd219f1' - name: OPERAND_IMAGE_CONSOLE_MCE - value: '{{ .Values.imageRegistry }}/multicluster-engine/console-mce-rhel9@sha256:967e6d0bb0655bbd2959d052d0049d52aad4e440dae8fa31f17dffa86787d5fa' + value: '{{ .Values.imageRegistry }}/multicluster-engine/console-mce-rhel9@sha256:407f44993e8b14e99990360333e1af3f7097591396f9cf56479b2b8438d47dca' - name: OPERAND_IMAGE_DISCOVERY_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/discovery-rhel9@sha256:07d2c496361b786320657f215edbaa83661e396b391834ad8d5862ae951a3f31' + value: '{{ .Values.imageRegistry }}/multicluster-engine/discovery-rhel9@sha256:2a03d06f5c412a896c491cbcbf00b2883980835fd94737482042c06d6a68022c' - name: OPERAND_IMAGE_HYPERSHIFT_ADDON_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-addon-rhel9-operator@sha256:8ac8df86a5f715c9065ff30602eb6d803f67d7a7550f0a805376c99fa793e8be' + value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-addon-rhel9-operator@sha256:af40c47a901c3c1851104427d3fd9db1f0cb6205e37917dc87af57facc90d75d' - name: OPERAND_IMAGE_HYPERSHIFT_CLI - value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-cli-rhel9@sha256:fc53d8bda8b4c9f05ee48c4ed11ed5682c5f493c996ca98646f99a9e9d7a4875' + value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-cli-rhel9@sha256:f68997b97948891fab2ce7f60c2b9657da147491f8c5bb0e804aab7b0d57c854' - name: OPERAND_IMAGE_HYPERSHIFT_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-rhel9-operator@sha256:23fb3c2671cd382f75288c928ea391fafecda9bffd9442b0d63635e61421075b' + value: '{{ .Values.imageRegistry }}/multicluster-engine/hypershift-rhel9-operator@sha256:161292cbf4b81c928e6dc9162dc63b02b21c93bfa92b3272f437dc4ff5a02c3a' - name: OPERAND_IMAGE_IMAGE_BASED_INSTALL_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/image-based-install-rhel9@sha256:3baea6a1e65f687fa2a0c6b01d2376a20eb2f572b2abfcb516c41f6752fe4be7' + value: '{{ .Values.imageRegistry }}/multicluster-engine/image-based-install-rhel9@sha256:1b145d921805c94dcd9da4387944039c4ea1af782969d35b42f27c30198b8fbe' - name: OPERAND_IMAGE_KUBE_RBAC_PROXY_MCE - value: '{{ .Values.imageRegistry }}/multicluster-engine/kube-rbac-proxy-mce-rhel9@sha256:865c85fbe1f582605923333f8fef963cd78d1e409a52f3d372623eb5546f08cf' + value: '{{ .Values.imageRegistry }}/multicluster-engine/kube-rbac-proxy-mce-rhel9@sha256:b1ada80f881131283a94d84cb37edc4b9725ccea9b66ebf8ccd6956cb515531a' - name: OPERAND_IMAGE_MANAGEDCLUSTER_IMPORT_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/managedcluster-import-controller-rhel9@sha256:229eeb1e86f4e8b5833ba08e9044356addc989c3612db6e0bcc4ad4784eab4f1' + value: '{{ .Values.imageRegistry }}/multicluster-engine/managedcluster-import-controller-rhel9@sha256:09a2f864c76373c9c6af4e8f7c2ffe4dffecc2637cf1647b7d2926419265e3f4' - name: OPERAND_IMAGE_MANAGED_SERVICEACCOUNT - value: '{{ .Values.imageRegistry }}/multicluster-engine/managed-serviceaccount-rhel9@sha256:0cfff5011533e0e1c28621f129a8fc600dd974bbf17aeca59da855887aee6427' + value: '{{ .Values.imageRegistry }}/multicluster-engine/managed-serviceaccount-rhel9@sha256:bc6ddc984411179e3882afbdb66664cec7cfd7cc65077e4866748939622f6687' - name: OPERAND_IMAGE_MULTICLOUD_MANAGER - value: '{{ .Values.imageRegistry }}/multicluster-engine/multicloud-manager-rhel9@sha256:d00b99b2e6041bcc4fd82ae8230348cb59b8daf4abffa4d0309ecab355f486c1' + value: '{{ .Values.imageRegistry }}/multicluster-engine/multicloud-manager-rhel9@sha256:a0873734a8e0d0b5092820d7ded0436c30fd572abdabb01159b53f0bb2e9d4a3' - name: OPERAND_IMAGE_OPENSHIFT_HIVE - value: '{{ .Values.imageRegistry }}/multicluster-engine/hive-rhel9@sha256:168a1f36bef09a89975721c7c182f3ac53334bd94cbe79d044d303f42abc7206' + value: '{{ .Values.imageRegistry }}/multicluster-engine/hive-rhel9@sha256:504c80f8391fe6c5953ff058ef61db0d87880d24605ff872a2112d7003ede848' - name: OPERAND_IMAGE_PROVIDER_CREDENTIAL_CONTROLLER - value: '{{ .Values.imageRegistry }}/multicluster-engine/provider-credential-controller-rhel9@sha256:8ef1a479d6324277cf3dafc3d8f43fe24e138c76a46203b48a04482f1967fb49' + value: '{{ .Values.imageRegistry }}/multicluster-engine/provider-credential-controller-rhel9@sha256:1df5c14a22fffdcf04cc82e26fdd153f26f85dd78bc237f5a8f4379f142ccb22' - name: OPERAND_IMAGE_PLACEMENT - value: '{{ .Values.imageRegistry }}/multicluster-engine/placement-rhel9@sha256:2e683cd960cc469b215255ae5c65fd0185ef4cc708a98e0be0c1417ad6ee8ea7' + value: '{{ .Values.imageRegistry }}/multicluster-engine/placement-rhel9@sha256:737cf1d7dcdf8c32d96894eebd686caf35959232f3fd774b307cf1df8068d26c' - name: OPERAND_IMAGE_REGISTRATION - value: '{{ .Values.imageRegistry }}/multicluster-engine/registration-rhel9@sha256:b101420ec76edb714c364fddfee7ff90a1f13212904688d740d4fc70c0a7175d' + value: '{{ .Values.imageRegistry }}/multicluster-engine/registration-rhel9@sha256:26ef4145f464f1c5cdb6ab42c119766669f7f08e46cbd4185bdbd3f4cd70bb54' - name: OPERAND_IMAGE_REGISTRATION_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/registration-operator-rhel9@sha256:6dcc104b4402010ccb0b27ced1bd0606c49effb27db59f47241b1b72030070ab' + value: '{{ .Values.imageRegistry }}/multicluster-engine/registration-operator-rhel9@sha256:8a37700e9848830dca9a3eebd4c8ca6abd7b04dc28ab5cefd743d00dd58be92a' - name: OPERAND_IMAGE_WORK - value: '{{ .Values.imageRegistry }}/multicluster-engine/work-rhel9@sha256:482c09e19316ee3b90abc0c9531609ec2e962d93154d9892aa219ed98b3e15d7' + value: '{{ .Values.imageRegistry }}/multicluster-engine/work-rhel9@sha256:1fecd5872ad4a0ce5ddab8a156a54315fc51508a4a18a80d901af7f9af294ec6' - name: OPERAND_IMAGE_BACKPLANE_OPERATOR - value: '{{ .Values.imageRegistry }}/multicluster-engine/backplane-rhel9-operator@sha256:3f3ec83d4c8b8f4c877da96b2254fb1f871633ebb6853f29f225189094badd36' + value: '{{ .Values.imageRegistry }}/multicluster-engine/backplane-rhel9-operator@sha256:8c2f526398df56f92bfc62af8e42c3e373c236ab67e58e877cf9690fc480d46a' - name: OPERAND_IMAGE_POSTGRESQL_12 value: '{{ .Values.imageRegistry }}/rhel8/postgresql-12@sha256:82d171ab0ce78a0157408662155b53d4f637947a303bfecb684f6132f5f468be' - name: OPERATOR_VERSION value: 2.7.0 - name: OPERATOR_PACKAGE value: multicluster-engine - image: '{{ .Values.imageRegistry }}/multicluster-engine/backplane-rhel9-operator@sha256:3f3ec83d4c8b8f4c877da96b2254fb1f871633ebb6853f29f225189094badd36' + image: '{{ .Values.imageRegistry }}/multicluster-engine/backplane-rhel9-operator@sha256:8c2f526398df56f92bfc62af8e42c3e373c236ab67e58e877cf9690fc480d46a' livenessProbe: httpGet: path: /healthz diff --git a/acm/pipeline.yaml b/acm/pipeline.yaml new file mode 100644 index 000000000..202c18a71 --- /dev/null +++ b/acm/pipeline.yaml @@ -0,0 +1,20 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.ACM +rolloutName: ACM Rollout +resourceGroups: +- name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ARO_HCP_IMAGE_ACR + configRef: svcAcrName + - name: CLC_STATE_METRICS_IMAGE_DIGEST + configRef: mce.clcStateMetrics.imageDigest diff --git a/acrpull/Makefile b/acrpull/Makefile new file mode 100644 index 000000000..28b8e7e1d --- /dev/null +++ b/acrpull/Makefile @@ -0,0 +1,15 @@ +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install + +deploy: + kubectl create namespace acrpull --dry-run=client -o json | kubectl apply -f - && \ + ${HELM_CMD} acrpull \ + deploy/helm/acrpull/ \ + --set image=mcr.microsoft.com/aks/msi-acrpull@${ACRPULL_DIGEST} \ + --namespace acrpull +.PHONY: deploy + +undeploy: + helm uninstall acrpull --namespace acrpull +.PHONY: undeploy diff --git a/acrpull/deploy/helm/acrpull/Chart.yaml b/acrpull/deploy/helm/acrpull/Chart.yaml new file mode 100644 index 000000000..63420852c --- /dev/null +++ b/acrpull/deploy/helm/acrpull/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: acrpull +description: Controller for injecting pull credentials from managed identities into AKS clusters. +type: application +version: 0.1.0 +appVersion: "v0.1.5" diff --git a/acrpull/deploy/helm/acrpull/templates/acrpull.microsoft.com_acrpullbindings.yaml b/acrpull/deploy/helm/acrpull/templates/acrpull.microsoft.com_acrpullbindings.yaml new file mode 100644 index 000000000..6e444be51 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/acrpull.microsoft.com_acrpullbindings.yaml @@ -0,0 +1,225 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: acrpullbindings.acrpull.microsoft.com +spec: + group: acrpull.microsoft.com + names: + kind: AcrPullBinding + listKind: AcrPullBindingList + plural: acrpullbindings + shortNames: + - apb + - apbs + singular: acrpullbinding + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: FQDN for the ACR. + jsonPath: .spec.acr.server + name: Server + type: string + - description: Scope for the ACR token. + jsonPath: .spec.acr.scope + name: Scope + priority: 1 + type: string + - description: ServiceAccount to which the pull credentials are attached. + jsonPath: .spec.serviceAccountName + name: Target + type: string + - description: Time the token was last refreshed. + jsonPath: .status.lastTokenRefreshTime + name: Last Refresh + priority: 1 + type: date + - description: Time the current token expires. + jsonPath: .status.tokenExpirationTime + name: Expiration + type: date + - description: Errors encountered during token generation, if any. + jsonPath: .status.error + name: Error + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: AcrPullBinding is the Schema for the acrpullbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AcrPullBindingSpec defines the desired state of AcrPullBinding + properties: + acr: + description: ACR holds specifics of the Azure Container Registry for + which credentials are projected. + properties: + cloudConfig: + description: AirgappedCloudConfiguration configures a custom cloud + to interact with when running air-gapped. + properties: + entraAuthorityHost: + description: EntraAuthorityHost configures a custom Entra + host endpoint. + minLength: 1 + type: string + resourceManagerAudience: + description: ResourceManagerAudience configures the audience + for which tokens will be requested from Entra. + minLength: 1 + type: string + required: + - entraAuthorityHost + - resourceManagerAudience + type: object + environment: + default: PublicCloud + description: Environment specifies the Azure Cloud environment + in which the ACR is deployed. + enum: + - PublicCloud + - USGovernmentCloud + - ChinaCloud + - AirgappedCloud + example: PublicCloud + type: string + scope: + description: |- + Scope defines the scope for the access token, e.g. pull/push access for a repository. + Note: you need to pin it down to the repository level, there is no wildcard available, + however a list of space-delimited scopes is acceptable. + See docs for details: https://distribution.github.io/distribution/spec/auth/scope/ + + + Examples: + repository:my-repository:pull,push + repository:my-repository:pull repository:other-repository:push,pull + example: repository:my-repository:pull,push + minLength: 1 + type: string + server: + description: Server is the FQDN for the Azure Container Registry, + e.g. example.azurecr.io + example: example.azurecr.io + type: string + x-kubernetes-validations: + - message: server must be a fully-qualified domain name + rule: isURL('https://' + self) && url('https://' + self).getHostname() + == self + required: + - environment + - scope + - server + type: object + x-kubernetes-validations: + - message: a custom cloud configuration must be present for air-gapped + cloud environments + rule: 'self.environment == ''ArigappedCloud'' ? has(self.cloudConfig) + : !has(self.cloudConfig)' + auth: + description: Auth determines how we will authenticate to the Azure + Container Registry. Only one method may be provided. + properties: + managedIdentity: + description: ManagedIdentity uses Azure Managed Identity to authenticate + with Azure. + properties: + clientID: + description: ClientID is the client identifier for the managed + identity. Either provide the client ID or the resource ID. + example: 1b461305-28be-5271-beda-bd9fd2e24251 + type: string + resourceID: + description: ResourceID is the resource identifier for the + managed identity. Either provide the client ID or the resource + ID. + example: /subscriptions/sub-name/resourceGroups/rg-name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/1b461305-28be-5271-beda-bd9fd2e24251 + type: string + type: object + x-kubernetes-validations: + - message: only client or resource ID can be set + rule: '[has(self.clientID), has(self.resourceID)].exists_one(x, + x)' + workloadIdentity: + description: WorkloadIdentity uses Azure Workload Identity to + authenticate with Azure. + properties: + clientID: + description: |- + ClientID holds an optional client identifier of a federated identity. + Specify this identifier if multiple identities are federated with the + service account and the identity to use for image pulling is not the + default identity stored in the service account's annotations. The + client and tenant ID must be specified together. + example: 1b461305-28be-5271-beda-bd9fd2e24251 + type: string + serviceAccountRef: + description: |- + ServiceAccountName specifies the name of the service account + that should be used when authenticating with WorkloadIdentity. + type: string + tenantID: + description: |- + TenantID holds an optional tenant identifier of a federated identity. + Specify this identifier if multiple identities are federated with the + service account and the identity to use for image pulling is not the + default identity stored in the service account's annotations. The + client and tenant ID must be specified together. + example: 72f988bf-86f1-41af-91ab-2d7cd011db47 + type: string + type: object + x-kubernetes-validations: + - message: custom client and tenant identifiers must be provided + together, if at all + rule: (has(self.clientID) && has(self.tenantID)) || (!has(self.clientID) + && !has(self.tenantID)) + type: object + x-kubernetes-validations: + - message: only one authentication type can be set + rule: '[has(self.managedIdentity), has(self.workloadIdentity)].exists_one(x, + x)' + serviceAccountName: + description: The name of the service account to associate the image + pull secret with. + type: string + type: object + status: + description: AcrPullBindingStatus defines the observed state of AcrPullBinding + properties: + error: + description: Error message if there was an error updating the token. + type: string + lastTokenRefreshTime: + description: Information when was the last time the ACR token was + refreshed. + format: date-time + type: string + tokenExpirationTime: + description: The expiration date of the current ACR token. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/acrpull/deploy/helm/acrpull/templates/controller_role.yaml b/acrpull/deploy/helm/acrpull/templates/controller_role.yaml new file mode 100644 index 000000000..c7919f064 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/controller_role.yaml @@ -0,0 +1,79 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: acrpull-controller +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - '*' +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - serviceaccounts/token + verbs: + - create +- apiGroups: + - acrpull.microsoft.com + resources: + - acrpullbindings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - acrpull.microsoft.com + resources: + - acrpullbindings/finalizers + verbs: + - update +- apiGroups: + - acrpull.microsoft.com + resources: + - acrpullbindings/status + verbs: + - get + - patch + - update +- apiGroups: + - msi-acrpull.microsoft.com + resources: + - acrpullbindings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - msi-acrpull.microsoft.com + resources: + - acrpullbindings/finalizers + verbs: + - update +- apiGroups: + - msi-acrpull.microsoft.com + resources: + - acrpullbindings/status + verbs: + - get + - patch + - update diff --git a/acrpull/deploy/helm/acrpull/templates/controller_role_binding.yaml b/acrpull/deploy/helm/acrpull/templates/controller_role_binding.yaml new file mode 100644 index 000000000..82800ad35 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/controller_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm + name: acrpull-controller-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: acrpull-controller +subjects: +- kind: ServiceAccount + name: acrpull + namespace: {{ .Values.namespace }} diff --git a/acrpull/deploy/helm/acrpull/templates/deployment.yaml b/acrpull/deploy/helm/acrpull/templates/deployment.yaml new file mode 100644 index 000000000..24abdc3d8 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/deployment.yaml @@ -0,0 +1,77 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: acrpull + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app.kubernetes.io/name: acrpull + replicas: 2 + template: + metadata: + labels: + app.kubernetes.io/name: acrpull + spec: + securityContext: + runAsNonRoot: true + containers: + - command: + - /manager + args: + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" + image: "{{ .Values.image }}" + name: acrpull-controller + ports: + - containerPort: 8080 + protocol: TCP + name: metrics + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + readOnlyRootFilesystem: true + runAsUser: 1000 + runAsGroup: 3000 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 100m + memory: 100Mi + requests: + cpu: 100m + memory: 20Mi + serviceAccountName: acrpull + terminationGracePeriodSeconds: 10 + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/acrpull/deploy/helm/acrpull/templates/leader_election_role.yaml b/acrpull/deploy/helm/acrpull/templates/leader_election_role.yaml new file mode 100644 index 000000000..fd0dae166 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/leader_election_role.yaml @@ -0,0 +1,40 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm + name: acrpull-controller-leader-election + namespace: {{ .Values.namespace }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/acrpull/deploy/helm/acrpull/templates/leader_election_role_binding.yaml b/acrpull/deploy/helm/acrpull/templates/leader_election_role_binding.yaml new file mode 100644 index 000000000..a534e194f --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/leader_election_role_binding.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm + name: acrpull-controller-leader-election-binding + namespace: {{ .Values.namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: acrpull-controller-leader-election +subjects: +- kind: ServiceAccount + name: acrpull + namespace: {{ .Values.namespace }} diff --git a/acrpull/deploy/helm/acrpull/templates/msi-acrpull.microsoft.com_acrpullbindings.yaml b/acrpull/deploy/helm/acrpull/templates/msi-acrpull.microsoft.com_acrpullbindings.yaml new file mode 100644 index 000000000..938ecc25e --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/msi-acrpull.microsoft.com_acrpullbindings.yaml @@ -0,0 +1,87 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: acrpullbindings.msi-acrpull.microsoft.com +spec: + group: msi-acrpull.microsoft.com + names: + kind: AcrPullBinding + listKind: AcrPullBindingList + plural: acrpullbindings + singular: acrpullbinding + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: AcrPullBinding is the Schema for the acrpullbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AcrPullBindingSpec defines the desired state of AcrPullBinding + properties: + acrServer: + description: The full server name for the ACR. For example, test.azurecr.io + minLength: 0 + type: string + managedIdentityClientID: + description: The Managed Identity client ID that is used to authenticate + with ACR (specify one of ClientID or ResourceID) + type: string + managedIdentityResourceID: + description: The Managed Identity resource ID that is used to authenticate + with ACR (if ClientID is specified, this is ignored) + type: string + scope: + description: |- + The registry scope which the pull token should have. For example, repository:my-repository:pull,push + See docs for details: https://distribution.github.io/distribution/spec/auth/scope/ + type: string + serviceAccountName: + description: |- + The Service Account to associate the image pull secret with. If this is not specified, the default Service Account + of the namespace will be used. + type: string + required: + - acrServer + type: object + status: + description: AcrPullBindingStatus defines the observed state of AcrPullBinding + properties: + error: + description: Error message if there was an error updating the token. + type: string + lastTokenRefreshTime: + description: Information when was the last time the ACR token was + refreshed. + format: date-time + type: string + tokenExpirationTime: + description: The expiration date of the current ACR token. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/acrpull/deploy/helm/acrpull/templates/podmonitor.yaml b/acrpull/deploy/helm/acrpull/templates/podmonitor.yaml new file mode 100644 index 000000000..3dec16cb3 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/podmonitor.yaml @@ -0,0 +1,14 @@ +apiVersion: azmonitoring.coreos.com/v1 +kind: PodMonitor +metadata: + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm + name: acrpull-monitor + namespace: {{ .Values.namespace }} +spec: + podMetricsEndpoints: + - port: metrics + selector: + matchLabels: + app.kubernetes.io/name: acrpull diff --git a/acrpull/deploy/helm/acrpull/templates/serviceaccount.yaml b/acrpull/deploy/helm/acrpull/templates/serviceaccount.yaml new file mode 100644 index 000000000..40929d970 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/serviceaccount.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm + name: acrpull + namespace: {{ .Values.namespace }} diff --git a/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicies.yaml b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicies.yaml new file mode 100644 index 000000000..d85324c5f --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicies.yaml @@ -0,0 +1,131 @@ +# This policy validates the configuration of the tokens that are created by the msi-acrpull controller. +# It requires the parameters controllerServiceAccountName, controllerNamespace, token expiration, and token audiences +# to be set in the ConfigMap admission-policies-controller-config. +# The user must configure: +# the token audiences +# the controllerServiceAccountName and controllerNamespace parameters +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "controller-token-request-policy" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + failurePolicy: Fail + paramKind: + apiVersion: v1 + kind: ConfigMap + matchConditions: + - name: 'userIsController' + expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName" + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE"] + resources: ["serviceaccounts/token"] + variables: + - name: requestHasOnlyOneAudience + expression: "object.spec.audiences.size() == 1" + - name: hasCorrectAudience + expression: "object.spec.audiences.exists(w, w == params.data.tokenAudience)" + validations: + - expression: "variables.hasCorrectAudience == true && variables.requestHasOnlyOneAudience == true" # if the expression evaluates to false, the validation check is enforced according to the failurePolicy + messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' ' + string(request.name) + ' token in the ' + string(request.namespace) + ' namespace. Check the configuration.'" + reason: "Forbidden" +--- +# This policy is used to restrict the types of secrets that the controller can create or update. We only allow the controller +# to create dockerconfigjson secret types, as allowing other types would allow privilege escalations and unwanted behavior. +# (For example, service account token secret types get auto-populated with tokens.) +# We furthermore restrict the controller to creating and updating secrets with the label we use for limiting our informers. +# It requires the parameter controllerName, controllerNamespace and the list of secret types to allow to be set in the +# ConfigMap admission-policies-controller-config. +# The user must configure: +# the controllerServiceAccountName and controllerNamespace parameters +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "controller-secret-mutation-policy" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + failurePolicy: Fail + paramKind: + apiVersion: v1 + kind: ConfigMap + matchConditions: + - name: 'userIsController' + expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName" + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["secrets"] + variables: + - name: hasOwner + expression: "has(object.metadata.ownerReferences) && (size(object.metadata.ownerReferences) == 1 && object.metadata.ownerReferences.all(o, o.kind == 'AcrPullBinding' && (o.apiVersion.startsWith('msi-acrpull.microsoft.com/') || o.apiVersion.startsWith('acrpull.microsoft.com/'))))" + - name: matchesPreviousOwner + expression: "has(oldObject.metadata) ? oldObject.metadata.ownerReferences == object.metadata.ownerReferences : true" + - name: hasSecretType + expression: "object.type == 'kubernetes.io/dockerconfigjson'" + - name: matchesPreviousSecretType + expression: "has(oldObject.metadata) ? oldObject.type == object.type : true" + - name: hasLabel + expression: "has(object.metadata.labels) && ('acr.microsoft.com/binding' in object.metadata.labels)" + - name: matchesPreviousLabel + expression: "has(oldObject.metadata) ? oldObject.metadata.labels == object.metadata.labels : true" + validations: + - expression: "variables.hasOwner == true && variables.matchesPreviousOwner == true && variables.hasSecretType == true && variables.matchesPreviousSecretType == true && variables.hasLabel == true && variables.matchesPreviousLabel == true" + messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' secret with ' + string(object.type) + ' type ' + 'in the ' + string(request.namespace) + ' namespace. The controller can only create or update secrets that it owns, with the correct type and having the correct label.'" + reason: "Forbidden" +--- +# This policy will deny updates to serviceAccounts that do something other than changing the list of managed pull secrets. +# It requires the parameter controllerServiceAccountName and controllerNamespace to be set in the +# ConfigMap admission-policies-controller-config. +# The user must configure: +# the controllerServiceAccountName and controllerNamespace parameters +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "controller-service-account-mutation-policy" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + failurePolicy: Fail + paramKind: + apiVersion: v1 + kind: ConfigMap + matchConditions: + - name: 'userIsController' + expression: "request.userInfo.username == 'system:serviceaccount:'+params.data.controllerNamespace+':'+params.data.controllerServiceAccountName" + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["UPDATE"] + resources: ["serviceaccounts"] + variables: + - name: secretsUnchanged + expression: "oldObject.?secrets == object.?secrets" + - name: automountUnchanged + expression: "oldObject.?automountServiceAccountToken == object.?automountServiceAccountToken" + - name: previousPullSecretNames + expression: "oldObject.?imagePullSecrets.orValue([]).map(s, s.name)" + - name: pullSecretNames + expression: "object.?imagePullSecrets.orValue([]).map(s, s.name)" + - name: addedPullSecrets + expression: "variables.pullSecretNames.filter(s, !(s in variables.previousPullSecretNames))" + - name: removedPullSecrets + expression: "variables.previousPullSecretNames.filter(s, !(s in variables.pullSecretNames))" + - name: onlyCorrectPullSecretsAdded + expression: "variables.addedPullSecrets.all(s, s.matches('^acr-pull-.{1,44}-[a-zA-Z0-9]{10}$'))" + - name: onlyCorrectPullSecretsRemoved + expression: "variables.removedPullSecrets.all(s, s.matches('^acr-pull-.{1,44}-[a-zA-Z0-9]{10}$'))" + validations: + - expression: "variables.secretsUnchanged == true && variables.automountUnchanged == true && variables.onlyCorrectPullSecretsAdded == true && variables.onlyCorrectPullSecretsRemoved == true" + messageExpression: "string(params.data.controllerServiceAccountName) + ' has failed to ' + string(request.operation) + ' service account ' + string(request.name) + ' in the ' + string(request.namespace) + ' namespace. The controller may only update service accounts to add or remove pull secrets that the controller manages.' + string(variables.automountUnchanged == true) + string(variables.automountUnchanged == true) + string(variables.onlyCorrectPullSecretsAdded == true) + string(variables.onlyCorrectPullSecretsRemoved == true)" + reason: "Forbidden" diff --git a/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicybindings.yaml b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicybindings.yaml new file mode 100644 index 000000000..21d281b81 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicybindings.yaml @@ -0,0 +1,44 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "controller-token-request-policy-binding" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + policyName: "controller-token-request-policy" + validationActions: [Deny] + paramRef: + name: "admission-policies-controller-config" + namespace: {{ .Values.namespace }} + parameterNotFoundAction: "Allow" +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "controller-secret-mutation-policy-binding" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + policyName: "controller-secret-mutation-policy" + validationActions: [Deny] + paramRef: + name: "admission-policies-controller-config" + namespace: {{ .Values.namespace }} + parameterNotFoundAction: "Allow" +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "controller-service-account-mutation-policy-binding" + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +spec: + policyName: "controller-service-account-mutation-policy" + validationActions: [Deny] + paramRef: + name: "admission-policies-controller-config" + namespace: {{ .Values.namespace }} + parameterNotFoundAction: "Allow" diff --git a/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicyparameters.yaml b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicyparameters.yaml new file mode 100644 index 000000000..0152ce02a --- /dev/null +++ b/acrpull/deploy/helm/acrpull/templates/validatingadmissionpolicyparameters.yaml @@ -0,0 +1,17 @@ +# This is the configuration file for the MSI-ACRPull Controller. These values will be passed to the helm chart. +# The config map is an easy way to provide an example of the configuration. +# The user must configure: +# the controllerName and controllerNamespace parameters +# the token audience: any opaque string, which the reconciler will be restricted to use +apiVersion: v1 +kind: ConfigMap +metadata: + name: "admission-policies-controller-config" + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/name: acrpull + app.kubernetes.io/managed-by: Helm +data: + controllerServiceAccountName: 'acrpull' + controllerNamespace: '{{ .Values.namespace }}' + tokenAudience: 'api://AzureCRTokenExchange' diff --git a/acrpull/deploy/helm/acrpull/values.yaml b/acrpull/deploy/helm/acrpull/values.yaml new file mode 100644 index 000000000..e921d8fb2 --- /dev/null +++ b/acrpull/deploy/helm/acrpull/values.yaml @@ -0,0 +1,5 @@ +namespace: acrpull +image: registry/image:tag +nodeSelector: {} +tolerations: [] +affinity: {} diff --git a/acrpull/pipeline.yaml b/acrpull/pipeline.yaml new file mode 100644 index 000000000..522b75175 --- /dev/null +++ b/acrpull/pipeline.yaml @@ -0,0 +1,32 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.ACRPull +rolloutName: ACRPull Controller Rollout +resourceGroups: + - name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ACRPULL_DIGEST + configRef: acrPullImageDigest + - name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy-mgmt + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ACRPULL_DIGEST + configRef: acrPullImageDigest diff --git a/action.yml b/action.yml index 07a5e4d1f..f849a45f9 100644 --- a/action.yml +++ b/action.yml @@ -11,7 +11,7 @@ inputs: version: description: 'Azure CLI Version to install' required: false - default: "2.63.0" # pin to 2.63.0 because of https://github.com/Azure/azure-cli/issues/29828 + default: "latest" runs: using: "composite" steps: diff --git a/api/redhatopenshift/HcpCluster.Management/hcpCluster-models.tsp b/api/redhatopenshift/HcpCluster.Management/hcpCluster-models.tsp index 1997bdefe..de2cfbe22 100644 --- a/api/redhatopenshift/HcpCluster.Management/hcpCluster-models.tsp +++ b/api/redhatopenshift/HcpCluster.Management/hcpCluster-models.tsp @@ -148,7 +148,7 @@ model ClusterSpec { * to authenticate against user Azure cloud account */ @visibility("read") - issuerUrl: string; + issuerUrl: url; /** Configuration to override the openshift-oauth-apiserver inside cluster * This changes user login into the cluster to external provider @@ -264,14 +264,14 @@ union NetworkType { model ConsoleProfile { /** The cluster web console URL endpoint */ @visibility("read") - url: string; + url: url; } /** Information about the API of a cluster. */ model ApiProfile { /** URL endpoint for the API server */ @visibility("read") - url: string; + url: url; /** should the API server be accessible from the internet */ @visibility("create", "read") @@ -292,10 +292,10 @@ union Visibility { /** OpenShift cluster proxy configuration */ model ProxyProfile { /** http proxy config */ - httpProxy?: string; + httpProxy?: url; /** https proxy config */ - httpsProxy?: string; + httpsProxy?: url; /** no proxy config */ noProxy?: string; @@ -316,13 +316,16 @@ model PlatformProfile { outboundType?: OutboundType = OutboundType.loadBalancer; /** ResourceId for the network security group attached to the cluster subnet */ - networkSecurityGroupId: NetworkSecurityGroupResourceId; + networkSecurityGroupId?: NetworkSecurityGroupResourceId; /** The id of the disk encryption set to be used for etcd. * Configure this when `etcdEncryption` is set to true * Is used the https://learn.microsoft.com/en-us/azure/storage/common/customer-managed-keys-overview */ etcdEncryptionSetId?: string; + + /** The configuration that the operators of the cluster have to authenticate to Azure */ + operatorsAuthentication: OperatorsAuthenticationProfile; } scalar SubnetResourceId @@ -338,6 +341,7 @@ scalar NetworkSecurityGroupResourceId type: "Microsoft.Network/networkSecurityGroups", } ]>; + /** The outbound routing strategy used to provide your cluster egress to the internet. */ union OutboundType { string, @@ -346,6 +350,41 @@ union OutboundType { loadBalancer: "loadBalancer", } +/** The configuration that the operators of the cluster have to authenticate to Azure. */ +model OperatorsAuthenticationProfile { + /** Represents the information related to Azure User-Assigned managed identities needed + * to perform Operators authentication based on Azure User-Assigned Managed Identities */ + userAssignedIdentities: UserAssignedIdentitiesProfile; +} + +/** Represents the information related to Azure User-Assigned managed identities needed + * to perform Operators authentication based on Azure User-Assigned Managed Identities */ +model UserAssignedIdentitiesProfile { + /** The set of Azure User-Assigned Managed Identities leveraged for the Control Plane + * operators of the cluster. The set of required managed identities is dependent on the + * Cluster's OpenShift version. */ + #suppress "@azure-tools/typespec-azure-resource-manager/arm-no-record" "operator name to user assigned identity pairings" + controlPlaneOperators: Record; + + /** The set of Azure User-Assigned Managed Identities leveraged for the Data Plane + * operators of the cluster. The set of required managed identities is dependent on the + * Cluster's OpenShift version. */ + #suppress "@azure-tools/typespec-azure-resource-manager/arm-no-record" "operator name to user assigned identity pairings" + dataPlaneOperators: Record; + + /** Represents the information associated to an Azure User-Assigned Managed Identity whose + * purpose is to perform service level actions. */ + @visibility("create", "read") + serviceManagedIdentity: UserAssignedIdentityResourceId; +} + +scalar UserAssignedIdentityResourceId + extends Azure.Core.armResourceIdentifier<[ + { + type: "Microsoft.ManagedIdentity/userAssignedIdentities", + } + ]>; + /* * ======================================= * End HCP cluster core resources @@ -385,7 +424,7 @@ model ExternalAuthProfile { /** Token issuer profile */ model TokenIssuerProfile { /** The URL of the token issuer */ - url: string; + url: url; /** The audience of the token issuer */ audiences: string[]; diff --git a/api/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/hcpclusters/preview/2024-06-10-preview/openapi.json b/api/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/hcpclusters/preview/2024-06-10-preview/openapi.json index f02e82be3..c94fa9b6a 100644 --- a/api/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/hcpclusters/preview/2024-06-10-preview/openapi.json +++ b/api/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/hcpclusters/preview/2024-06-10-preview/openapi.json @@ -927,6 +927,7 @@ "properties": { "url": { "type": "string", + "format": "uri", "description": "URL endpoint for the API server", "readOnly": true }, @@ -1097,6 +1098,7 @@ }, "issuerUrl": { "type": "string", + "format": "uri", "description": "URL for the OIDC provider to be used for authentication\nto authenticate against user Azure cloud account", "readOnly": true }, @@ -1122,6 +1124,7 @@ "properties": { "url": { "type": "string", + "format": "uri", "description": "The cluster web console URL endpoint", "readOnly": true } @@ -1911,6 +1914,19 @@ "platform" ] }, + "OperatorsAuthenticationProfile": { + "type": "object", + "description": "The configuration that the operators of the cluster have to authenticate to Azure.", + "properties": { + "userAssignedIdentities": { + "$ref": "#/definitions/UserAssignedIdentitiesProfile", + "description": "Represents the information related to Azure User-Assigned managed identities needed\nto perform Operators authentication based on Azure User-Assigned Managed Identities" + } + }, + "required": [ + "userAssignedIdentities" + ] + }, "PlatformProfile": { "type": "object", "description": "Azure specific configuration", @@ -1949,11 +1965,15 @@ "etcdEncryptionSetId": { "type": "string", "description": "The id of the disk encryption set to be used for etcd.\nConfigure this when `etcdEncryption` is set to true\nIs used the https://learn.microsoft.com/en-us/azure/storage/common/customer-managed-keys-overview" + }, + "operatorsAuthentication": { + "$ref": "#/definitions/OperatorsAuthenticationProfile", + "description": "The configuration that the operators of the cluster have to authenticate to Azure" } }, "required": [ "subnetId", - "networkSecurityGroupId" + "operatorsAuthentication" ] }, "ProvisioningState": { @@ -2017,10 +2037,12 @@ "properties": { "httpProxy": { "type": "string", + "format": "uri", "description": "http proxy config" }, "httpsProxy": { "type": "string", + "format": "uri", "description": "https proxy config" }, "noProxy": { @@ -2105,6 +2127,7 @@ "properties": { "url": { "type": "string", + "format": "uri", "description": "The URL of the token issuer" }, "audiences": { @@ -2125,6 +2148,51 @@ "ca" ] }, + "UserAssignedIdentitiesProfile": { + "type": "object", + "description": "Represents the information related to Azure User-Assigned managed identities needed\nto perform Operators authentication based on Azure User-Assigned Managed Identities", + "properties": { + "controlPlaneOperators": { + "type": "object", + "description": "The set of Azure User-Assigned Managed Identities leveraged for the Control Plane\noperators of the cluster. The set of required managed identities is dependent on the\nCluster's OpenShift version.", + "additionalProperties": { + "$ref": "#/definitions/UserAssignedIdentityResourceId" + } + }, + "dataPlaneOperators": { + "type": "object", + "description": "The set of Azure User-Assigned Managed Identities leveraged for the Data Plane\noperators of the cluster. The set of required managed identities is dependent on the\nCluster's OpenShift version.", + "additionalProperties": { + "$ref": "#/definitions/UserAssignedIdentityResourceId" + } + }, + "serviceManagedIdentity": { + "$ref": "#/definitions/UserAssignedIdentityResourceId", + "description": "Represents the information associated to an Azure User-Assigned Managed Identity whose\npurpose is to perform service level actions.", + "x-ms-mutability": [ + "read", + "create" + ] + } + }, + "required": [ + "controlPlaneOperators", + "dataPlaneOperators", + "serviceManagedIdentity" + ] + }, + "UserAssignedIdentityResourceId": { + "type": "string", + "format": "arm-id", + "description": "A type definition that refers the id to an Azure Resource Manager resource.", + "x-ms-arm-id-details": { + "allowedResources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities" + } + ] + } + }, "VersionProfile": { "type": "object", "description": "Versions represents an OpenShift version.", diff --git a/backend/.gitignore b/backend/.gitignore index aee2e4ce1..e69de29bb 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1 +0,0 @@ -config.mk diff --git a/backend/Dockerfile b/backend/Dockerfile index 355413d65..cd51d1c07 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,5 +1,5 @@ # Builder image installs tools needed to build aro-hcp-backend -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:6c1b07df15c152fb6a7f4eeece5f50824d83b8bf672709cc951aaa0d5c29887f as builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:97d76864911dfbaf6b3387b6e0583abe5af74d7b744773c4facbaf02389e654f as builder WORKDIR /app ADD archive.tar.gz . # https://github.com/microsoft/go/tree/microsoft/main/eng/doc/fips#build-option-to-require-fips-mode @@ -8,7 +8,7 @@ RUN cd backend && make backend # Deployment image copies aro-hcp-backend from builder image -FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:acb1ab4d2162ecebbe67888bf679f26dcaef29c153954a09396e020e9639862d +FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:ce44fc29db88c9aba8041a50c1abcd19a54f997c2b99a8c513e8ec113261374a WORKDIR / COPY --from=builder /app/backend/aro-hcp-backend . ENTRYPOINT ["/aro-hcp-backend"] diff --git a/backend/Makefile b/backend/Makefile index f580f76b6..f4e9bcb51 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,41 +1,51 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install -COMMIT = $(shell git rev-parse --short=7 HEAD) +ifndef COMMIT +COMMIT := $(shell git rev-parse --short=7 HEAD) +endif ARO_HCP_BASE_IMAGE ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io ARO_HCP_BACKEND_IMAGE ?= $(ARO_HCP_BASE_IMAGE)/arohcpbackend:$(COMMIT) +.DEFAULT_GOAL := backend + backend: go build -o aro-hcp-backend . +.PHONY: backend run: + DB_URL=$$(az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ ./aro-hcp-backend --location ${LOCATION} \ - --clusters-service-url http://localhost:8000 + --clusters-service-url http://localhost:8000 \ + --cosmos-name ${DB_NAME} \ + --cosmos-url $${DB_URL} +.PHONY: run clean: rm -f aro-hcp-backend +.PHONY: clean image: pushd .. && git archive --output backend/archive.tar.gz HEAD && popd docker build -f "./Dockerfile" -t ${ARO_HCP_BACKEND_IMAGE} . rm -f archive.tar.gz +.PHONY: image push: image az acr login --name ${ARO_HCP_IMAGE_ACR} docker push ${ARO_HCP_BACKEND_IMAGE} +.PHONY: push deploy: - BACKEND_MI_CLIENT_ID=$(shell az identity show \ + BACKEND_MI_CLIENT_ID=$$(az identity show \ -g ${RESOURCEGROUP} \ -n backend \ - --query clientId);\ - ISTO_VERSION=$(shell az aks show -n ${AKS_NAME} -g ${RESOURCEGROUP} --query serviceMeshProfile.istio.revisions[-1] -o tsv) && \ - DB_URL=$(shell az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ + --query clientId -o tsv) && \ + DB_URL=$$(az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ kubectl create namespace aro-hcp --dry-run=client -o json | kubectl apply -f - && \ - kubectl label namespace aro-hcp "istio.io/rev=$${ISTO_VERSION}" --overwrite=true && \ - helm upgrade --install aro-hcp-backend-dev \ + kubectl label namespace aro-hcp "istio.io/rev=${ISTO_TAG}" --overwrite=true && \ + ${HELM_CMD} aro-hcp-backend-dev \ deploy/helm/backend/ \ --set configMap.databaseName=${DB_NAME} \ --set configMap.databaseUrl="$${DB_URL}" \ @@ -45,8 +55,8 @@ deploy: --set configMap.location=${LOCATION} \ --set deployment.imageName=${ARO_HCP_BACKEND_IMAGE} \ --namespace aro-hcp +.PHONY: deploy undeploy: helm uninstall aro-hcp-backend-dev --namespace aro-hcp - -.PHONY: backend run clean image push deploy undeploy +.PHONY: undeploy diff --git a/backend/config.tmpl.mk b/backend/config.tmpl.mk deleted file mode 100644 index 5488940ea..000000000 --- a/backend/config.tmpl.mk +++ /dev/null @@ -1,5 +0,0 @@ -ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} -LOCATION ?= {{ .region }} -RESOURCEGROUP ?= {{ .serviceClusterRG }} -AKS_NAME ?= {{ .aksName }} -DB_NAME ?= {{ .frontendCosmosDBName }} diff --git a/backend/go.mod b/backend/go.mod index 3155d8acc..2e8c43c56 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -4,22 +4,23 @@ go 1.23.0 require ( github.com/Azure/ARO-HCP/internal v0.0.0-00010101000000-000000000000 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 - github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 - github.com/openshift-online/ocm-sdk-go v0.1.445 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 + github.com/openshift-online/ocm-sdk-go v0.1.456 github.com/spf13/cobra v1.8.1 + go.uber.org/mock v0.5.0 ) require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect @@ -38,11 +39,11 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index cdb6a1cb5..f2a943be1 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,19 +1,19 @@ github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 h1:c726lgbwpwFBuj+Fyrwuh/vUilqFo+hUAOUNjsKj5DI= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0/go.mod h1:WzFGxuepAtZIZtQbz8/WviJycLMKJHpaEAqcXONxlag= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 h1:1y5G4XTBTEt0nKNFtM7j6CxqkY5fxSuJb/mD8Zf0gPc= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0/go.mod h1:1Dp+C8Sly0hnhX8k5zDuw72Z2ehd9Lv+pkLFn8dgXMA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -31,8 +31,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= @@ -93,8 +93,8 @@ github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/openshift-online/ocm-sdk-go v0.1.445 h1:NfaY+biXaREPnGYxa8G2zS2OZpN06yNnDR95sZoqKUQ= -github.com/openshift-online/ocm-sdk-go v0.1.445/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= +github.com/openshift-online/ocm-sdk-go v0.1.456 h1:N9AmVv8H+FSlld88iCsafy+8Lhykz/1XUrmVhww/BYM= +github.com/openshift-online/ocm-sdk-go v0.1.456/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -110,8 +110,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -123,19 +123,21 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/backend/main.go b/backend/main.go index 88b455aa9..7588537d6 100644 --- a/backend/main.go +++ b/backend/main.go @@ -13,13 +13,12 @@ import ( "runtime/debug" "syscall" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ocmsdk "github.com/openshift-online/ocm-sdk-go" "github.com/spf13/cobra" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + "github.com/Azure/ARO-HCP/internal/database" ) @@ -72,44 +71,26 @@ func init() { } } -func newCosmosDBClient() (database.DBClient, error) { - azcoreClientOptions := azcore.ClientOptions{ - // FIXME Cloud should be determined by other means. - Cloud: cloud.AzurePublic, - } - - credential, err := azidentity.NewDefaultAzureCredential( - &azidentity.DefaultAzureCredentialOptions{ - ClientOptions: azcoreClientOptions, - }) - if err != nil { - return nil, err - } - - client, err := azcosmos.NewClient(argCosmosURL, credential, - &azcosmos.ClientOptions{ - ClientOptions: azcoreClientOptions, - }) - if err != nil { - return nil, err - } - - databaseClient, err := client.NewDatabase(argCosmosName) - if err != nil { - return nil, err - } - - return database.NewCosmosDBClient(context.Background(), databaseClient) -} - func Run(cmd *cobra.Command, args []string) error { handler := slog.NewJSONHandler(os.Stdout, nil) logger := slog.New(handler) - // Create database client - dbClient, err := newCosmosDBClient() + // Create the database client. + cosmosDatabaseClient, err := database.NewCosmosDatabaseClient( + argCosmosURL, + argCosmosName, + azcore.ClientOptions{ + // FIXME Cloud should be determined by other means. + Cloud: cloud.AzurePublic, + }, + ) + if err != nil { + return fmt.Errorf("failed to create the CosmosDB client: %w", err) + } + + dbClient, err := database.NewDBClient(context.Background(), cosmosDatabaseClient) if err != nil { - return fmt.Errorf("Failed to create database client: %w", err) + return fmt.Errorf("failed to create the database client: %w", err) } // Create OCM connection diff --git a/backend/operations_scanner.go b/backend/operations_scanner.go index 00e50076b..111bd394b 100644 --- a/backend/operations_scanner.go +++ b/backend/operations_scanner.go @@ -96,7 +96,7 @@ func (s *OperationsScanner) Join() { func (s *OperationsScanner) pollDBOperations(ctx context.Context, logger *slog.Logger) { var activeOperations []*database.OperationDocument - iterator := s.dbClient.ListAllOperationDocs(ctx) + iterator := s.dbClient.ListAllOperationDocs() for item := range iterator.Items(ctx) { var doc *database.OperationDocument @@ -165,7 +165,7 @@ func (s *OperationsScanner) pollClusterOperation(ctx context.Context, logger *sl if err != nil { var ocmError *ocmerrors.Error if errors.As(err, &ocmError) && ocmError.Status() == http.StatusNotFound && doc.Request == database.OperationRequestDelete { - err = s.withSubscriptionLock(ctx, logger, doc.OperationID.SubscriptionID, func(ctx context.Context) error { + err = s.withSubscriptionLock(ctx, logger, doc.ExternalID.SubscriptionID, func(ctx context.Context) error { return s.deleteOperationCompleted(ctx, logger, doc) }) if err == nil { @@ -180,7 +180,7 @@ func (s *OperationsScanner) pollClusterOperation(ctx context.Context, logger *sl logger.Warn(err.Error()) err = nil } else { - err = s.withSubscriptionLock(ctx, logger, doc.OperationID.SubscriptionID, func(ctx context.Context) error { + err = s.withSubscriptionLock(ctx, logger, doc.ExternalID.SubscriptionID, func(ctx context.Context) error { return s.updateOperationStatus(ctx, logger, doc, opStatus, opError) }) } diff --git a/backend/operations_scanner_test.go b/backend/operations_scanner_test.go index a84c5118f..05d3ff443 100644 --- a/backend/operations_scanner_test.go +++ b/backend/operations_scanner_test.go @@ -5,16 +5,19 @@ package main import ( "context" - "errors" "log/slog" "net/http" "net/http/httptest" "testing" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" + "go.uber.org/mock/gomock" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/mocks" + "github.com/Azure/ARO-HCP/internal/ocm" ) func TestDeleteOperationCompleted(t *testing.T) { @@ -48,13 +51,21 @@ func TestDeleteOperationCompleted(t *testing.T) { }, } + // Placeholder InternalID for NewOperationDocument + internalID, err := ocm.NewInternalID("/api/clusters_mgmt/v1/clusters/placeholder") + if err != nil { + t.Fatal(err) + } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var request *http.Request ctx := context.Background() + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) - resourceID, err := arm.ParseResourceID("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/testCluster") + resourceID, err := azcorearm.ParseResourceID("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/testCluster") if err != nil { t.Fatal(err) } @@ -67,21 +78,26 @@ func TestDeleteOperationCompleted(t *testing.T) { defer server.Close() scanner := &OperationsScanner{ - dbClient: database.NewCache(), + dbClient: mockDBClient, notificationClient: server.Client(), } - operationDoc := database.NewOperationDocument(database.OperationRequestDelete) - operationDoc.ExternalID = resourceID + operationDoc := database.NewOperationDocument(database.OperationRequestDelete, resourceID, internalID) operationDoc.NotificationURI = server.URL operationDoc.Status = tt.operationStatus - _ = scanner.dbClient.CreateOperationDoc(ctx, operationDoc) + var resourceDocDeleted bool - if tt.resourceDocPresent { - resourceDoc := database.NewResourceDocument(resourceID) - _ = scanner.dbClient.CreateResourceDoc(ctx, resourceDoc) - } + mockDBClient.EXPECT(). + DeleteResourceDoc(gomock.Any(), resourceID). + Do(func(ctx context.Context, resourceID *azcorearm.ResourceID) { + resourceDocDeleted = tt.resourceDocPresent + }) + mockDBClient.EXPECT(). + UpdateOperationDoc(gomock.Any(), operationDoc.ID, gomock.Any()). + DoAndReturn(func(ctx context.Context, operationID string, callback func(*database.OperationDocument) bool) (bool, error) { + return callback(operationDoc), nil + }) err = scanner.deleteOperationCompleted(ctx, slog.Default(), operationDoc) @@ -97,18 +113,11 @@ func TestDeleteOperationCompleted(t *testing.T) { t.Errorf("Got unexpected error: %v", err) } - if err == nil && tt.resourceDocPresent { - _, getErr := scanner.dbClient.GetResourceDoc(ctx, resourceID) - if !errors.Is(getErr, database.ErrNotFound) { - t.Error("Expected resource document to be deleted") - } + if err == nil && tt.resourceDocPresent && !resourceDocDeleted { + t.Error("Expected resource document to be deleted") } if err == nil && tt.expectAsyncNotification { - operationDoc, getErr := scanner.dbClient.GetOperationDoc(ctx, operationDoc.ID) - if getErr != nil { - t.Fatal(getErr) - } if operationDoc.Status != arm.ProvisioningStateSucceeded { t.Errorf("Expected updated operation status to be %s but got %s", arm.ProvisioningStateSucceeded, @@ -190,13 +199,21 @@ func TestUpdateOperationStatus(t *testing.T) { }, } + // Placeholder InternalID for NewOperationDocument + internalID, err := ocm.NewInternalID("/api/clusters_mgmt/v1/clusters/placeholder") + if err != nil { + t.Fatal(err) + } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var request *http.Request ctx := context.Background() + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) - resourceID, err := arm.ParseResourceID("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/testCluster") + resourceID, err := azcorearm.ParseResourceID("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/testGroup/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/testCluster") if err != nil { t.Fatal(err) } @@ -209,28 +226,41 @@ func TestUpdateOperationStatus(t *testing.T) { defer server.Close() scanner := &OperationsScanner{ - dbClient: database.NewCache(), + dbClient: mockDBClient, notificationClient: server.Client(), } - operationDoc := database.NewOperationDocument(database.OperationRequestCreate) - operationDoc.ExternalID = resourceID + operationDoc := database.NewOperationDocument(database.OperationRequestCreate, resourceID, internalID) operationDoc.NotificationURI = server.URL operationDoc.Status = tt.currentOperationStatus - _ = scanner.dbClient.CreateOperationDoc(ctx, operationDoc) + var resourceDoc *database.ResourceDocument if tt.resourceDocPresent { - resourceDoc := database.NewResourceDocument(resourceID) + resourceDoc = database.NewResourceDocument(resourceID) if tt.resourceMatchOperationID { resourceDoc.ActiveOperationID = operationDoc.ID } else { resourceDoc.ActiveOperationID = "another operation" } resourceDoc.ProvisioningState = tt.resourceProvisioningState - _ = scanner.dbClient.CreateResourceDoc(ctx, resourceDoc) } + mockDBClient.EXPECT(). + UpdateOperationDoc(gomock.Any(), operationDoc.ID, gomock.Any()). + DoAndReturn(func(ctx context.Context, operationID string, callback func(*database.OperationDocument) bool) (bool, error) { + return callback(operationDoc), nil + }) + mockDBClient.EXPECT(). + UpdateResourceDoc(gomock.Any(), resourceID, gomock.Any()). + DoAndReturn(func(ctx context.Context, resourceID *azcorearm.ResourceID, callback func(*database.ResourceDocument) bool) (bool, error) { + if resourceDoc != nil { + return callback(resourceDoc), nil + } else { + return false, database.ErrNotFound + } + }) + err = scanner.updateOperationStatus(ctx, slog.Default(), operationDoc, tt.updatedOperationStatus, nil) if request == nil && tt.expectAsyncNotification { @@ -246,10 +276,6 @@ func TestUpdateOperationStatus(t *testing.T) { } if err == nil && tt.expectAsyncNotification { - operationDoc, getErr := scanner.dbClient.GetOperationDoc(ctx, operationDoc.ID) - if getErr != nil { - t.Fatal(getErr) - } if operationDoc.Status != tt.updatedOperationStatus { t.Errorf("Expected updated operation status to be %s but got %s", tt.updatedOperationStatus, @@ -258,10 +284,6 @@ func TestUpdateOperationStatus(t *testing.T) { } if err == nil && tt.resourceDocPresent { - resourceDoc, getErr := scanner.dbClient.GetResourceDoc(ctx, resourceID) - if getErr != nil { - t.Fatal(getErr) - } if resourceDoc.ActiveOperationID == "" && !tt.expectResourceOperationIDCleared { t.Error("Resource's active operation ID is unexpectedly empty") } else if resourceDoc.ActiveOperationID != "" && tt.expectResourceOperationIDCleared { diff --git a/backend/pipeline.yaml b/backend/pipeline.yaml new file mode 100644 index 000000000..2a2149f32 --- /dev/null +++ b/backend/pipeline.yaml @@ -0,0 +1,30 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.Backend +rolloutName: RP Backend Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ARO_HCP_IMAGE_ACR + configRef: svcAcrName + - name: LOCATION + configRef: region + - name: RESOURCEGROUP + configRef: svc.rg + - name: AKS_NAME + configRef: aksName + - name: DB_NAME + configRef: frontend.cosmosDB.name + - name: COMMIT + configRef: backend.imageTag + - name: ISTO_TAG + configRef: svc.istio.tag diff --git a/cluster-service/.gitignore b/cluster-service/.gitignore index b714207f2..ccd2192a8 100644 --- a/cluster-service/.gitignore +++ b/cluster-service/.gitignore @@ -1,5 +1,6 @@ deploy/tmp-provisioning-shard.yml deploy/provisioning-shards.yml -deploy/dev-provisioning-shards.yml +deploy/local-provisioning-shards.yml deploy/azure-runtime-config.yaml config.mk +azure-operators-managed-identities-config.yaml diff --git a/cluster-service/Makefile b/cluster-service/Makefile index ac2f3c6b5..75be0c9ed 100644 --- a/cluster-service/Makefile +++ b/cluster-service/Makefile @@ -1,68 +1,99 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install -deploy: deploy-namespace-template deploy-istio-configurations-template ${DB_SECRET_TARGET} - AZURE_CS_MI_CLIENT_ID=$(shell az identity show -g ${RESOURCEGROUP} -n clusters-service --query clientId -o tsv) && \ +ZONE_NAME ?= "${REGIONAL_DNS_SUBDOMAIN}.${CX_PARENT_DNS_ZONE_NAME}" + + +deploy: + @kubectl create namespace ${NAMESPACE} --dry-run=client -o json | kubectl apply -f - && \ + kubectl label namespace ${NAMESPACE} "istio.io/rev=${ISTO_TAG}" --overwrite=true && \ + AZURE_CS_MI_CLIENT_ID=$(shell az identity show -g ${RESOURCEGROUP} -n ${MI_NAME} --query clientId -o tsv) && \ CS_SERVICE_PRINCIPAL_CREDS_BASE64='$(shell az keyvault secret show --vault-name "${SERVICE_KV}" --name "aro-hcp-dev-sp-cs" | jq .value -r | base64 | tr -d '\n')' && \ TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ OIDC_BLOB_SERVICE_ENDPOINT=$(shell az storage account show -n ${OIDC_STORAGE_ACCOUNT} -g ${RESOURCEGROUP} --query primaryEndpoints.blob -o tsv) && \ OIDC_ISSUER_BASE_ENDPOINT=$(shell az storage account show -n ${OIDC_STORAGE_ACCOUNT} -g ${RESOURCEGROUP} --query primaryEndpoints.web -o tsv) && \ - OIDC_CONTAINER="$$web" && \ OCP_ACR_URL=$(shell az acr show -n ${OCP_ACR_NAME} --query loginServer -o tsv) && \ OCP_ACR_RESOURCE_ID=$(shell az acr show -n ${OCP_ACR_NAME} --query id -o tsv) && \ - oc process --local -f deploy/openshift-templates/arohcp-service-template.yml \ - -p AZURE_CS_MI_CLIENT_ID=$${AZURE_CS_MI_CLIENT_ID} \ - -p TENANT_ID=$${TENANT_ID} \ - -p REGION=${REGION} \ - -p SERVICE_KEYVAULT_NAME=${SERVICE_KV} \ - -p CS_SERVICE_PRINCIPAL_CREDS_BASE64=$${CS_SERVICE_PRINCIPAL_CREDS_BASE64} \ - -p IMAGE_REGISTRY=${ACR_NAME}.azurecr.io \ - -p IMAGE_REPOSITORY=${IMAGE_REPO} \ - -p AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID=${AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID} \ - -p FPA_CERT_NAME=${FPA_CERT_NAME} \ - -p IMAGE_TAG=${IMAGE_TAG} \ - -p OCP_ACR_RESOURCE_ID=$${OCP_ACR_RESOURCE_ID} \ - -p OCP_ACR_URL=$${OCP_ACR_URL} \ - -p DATABASE_DISABLE_TLS=${DATABASE_DISABLE_TLS} \ - -p DATABASE_AUTH_METHOD=${DATABASE_AUTH_METHOD} | oc apply -f - - -deploy-namespace-template: - ISTO_VERSION=$(shell az aks show -n ${AKS_NAME} -g ${RESOURCEGROUP} --query serviceMeshProfile.istio.revisions[-1] -o tsv) && \ - oc process --local -f deploy/openshift-templates/arohcp-namespace-template.yml \ - -p ISTIO_VERSION=$${ISTO_VERSION} | oc apply -f - - -deploy-istio-configurations-template: - kubectl apply -f deploy/istio.yml - -deploy-local-db-secret: configure-tmp-provision-shard - oc process --local -f deploy/openshift-templates/arohcp-secrets-template.yml \ - -p PROVISION_SHARDS_CONFIG="$$( base64 -i deploy/provisioning-shards.yml)" | oc apply -f - - oc process --local -f deploy/openshift-templates/arohcp-db-template.yml | oc apply -f - - -deploy-azure-db-secret: configure-tmp-provision-shard - oc process --local -f deploy/openshift-templates/arohcp-secrets-template.yml \ - -p DATABASE_USER=clusters-service \ - -p DATABASE_NAME=clusters-service \ - -p DATABASE_PASSWORD="" \ - -p DATABASE_HOST=$(shell az postgres flexible-server show --resource-group ${RESOURCEGROUP} -n ${DATABASE_SERVER_NAME} --query fullyQualifiedDomainName -o tsv) \ - -p PROVISION_SHARDS_CONFIG="$$( base64 -i deploy/provisioning-shards.yml)" | oc apply -f - - -configure-tmp-provision-shard: + DB_HOST=$$(if [ "${USE_AZURE_DB}" = "true" ]; then az postgres flexible-server show -g ${RESOURCEGROUP} -n ${DATABASE_SERVER_NAME} --query fullyQualifiedDomainName -o tsv; else echo "ocm-cs-db"; fi) && \ + OVERRIDES=$$(if [ "${USE_AZURE_DB}" = "true" ]; then echo "azuredb.values.yaml"; else echo "containerdb.values.yaml"; fi) && \ + OP_CLUSTER_API_AZURE_ROLE_ID=$(shell az role definition list --name "${OP_CLUSTER_API_AZURE_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_CONTROL_PLANE_ROLE_ID=$(shell az role definition list --name "${OP_CONTROL_PLANE_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_CLOUD_CONTROLLER_MANAGER_ROLE_ID=$(shell az role definition list --name "${OP_CLOUD_CONTROLLER_MANAGER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_INGRESS_ROLE_ID=$(shell az role definition list --name "${OP_INGRESS_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_DISK_CSI_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_DISK_CSI_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_FILE_CSI_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_FILE_CSI_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_IMAGE_REGISTRY_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_IMAGE_REGISTRY_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_CLOUD_NETWORK_CONFIG_ROLE_ID=$(shell az role definition list --name "${OP_CLOUD_NETWORK_CONFIG_ROLE_NAME}" --query "[].name" -o tsv) && \ ZONE_RESOURCE_ID=$(shell az network dns zone show -n ${ZONE_NAME} -g ${REGIONAL_RESOURCEGROUP} --query id -o tsv) && \ - ../templatize.sh $(DEPLOY_ENV) deploy/provisioning-shards.tmpl.yml deploy/provisioning-shards.yml -e zoneResourceId=$${ZONE_RESOURCE_ID} + CX_SECRETS_KV_URL=$(shell az keyvault show -n ${CX_SECRETS_KV_NAME} -g ${MGMT_RESOURCEGROUP} --query properties.vaultUri -o tsv) && \ + CX_MI_KV_URL=$(shell az keyvault show -n ${CX_MI_KV_NAME} -g ${MGMT_RESOURCEGROUP} --query properties.vaultUri -o tsv) && \ + ${HELM_CMD} cluster-service deploy/helm \ + --namespace ${NAMESPACE} \ + -f deploy/helm/$${OVERRIDES} \ + --set serviceAccountName=${SERVICE_ACCOUNT_NAME} \ + --set azureCsMiClientId=$${AZURE_CS_MI_CLIENT_ID} \ + --set oidcIssuerBlobServiceUrl=$${OIDC_BLOB_SERVICE_ENDPOINT} \ + --set oidcIssuerBaseUrl=$${OIDC_ISSUER_BASE_ENDPOINT} \ + --set tenantId=$${TENANT_ID} \ + --set region=${REGION} \ + --set serviceKeyvaultName=${SERVICE_KV} \ + --set csServicePrincipalCredsBase64=$${CS_SERVICE_PRINCIPAL_CREDS_BASE64} \ + --set imageRegistry=${ACR_NAME}.azurecr.io \ + --set imageRepository=${IMAGE_REPO} \ + --set imageTag=${IMAGE_TAG} \ + --set azureFirstPartyApplicationClientId=${AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID} \ + --set fpaCertName=${FPA_CERT_NAME} \ + --set ocpAcrResourceId=$${OCP_ACR_RESOURCE_ID} \ + --set ocpAcrUrl=$${OCP_ACR_URL} \ + --set shard.consumerName="${CONSUMER_NAME}" \ + --set shard.zoneResourceId="$${ZONE_RESOURCE_ID}" \ + --set shard.cxSecretsKeyVaultUrl="$${CX_SECRETS_KV_URL}" \ + --set shard.cxMiKeyVaultUrl="$${CX_MI_KV_URL}" \ + --set shard.maestroRestUrl="http://maestro.maestro.svc.cluster.local:8000" \ + --set shard.maestroGrpUrl="maestro-grpc.maestro.svc.cluster.local:8090" \ + --set databaseHost=$${DB_HOST} \ + --set azureMiMockServicePrincipalPrincipalId=${AZURE_MI_MOCK_SERVICE_PRINCIPAL_PRINCIPAL_ID} \ + --set azureMiMockServicePrincipalClientId=${AZURE_MI_MOCK_SERVICE_PRINCIPAL_CLIENT_ID} \ + --set azureMiMockServicePrincipalCertName=${MI_MOCK_SERVICE_PRINCIPAL_CERT_NAME} \ + --set azureArmHelperIdentityCertName=${ARM_HELPER_CERT_NAME} \ + --set azureArmHelperIdentityClientId=${AZURE_ARM_HELPER_IDENTITY_CLIENT_ID} \ + --set azureArmHelperMockFpaPrincipalId=${AZURE_ARM_HELPER_MOCK_FPA_PRINCIPAL_ID} \ + --set azureOperatorsMI.clusterApiAzure.roleName="${OP_CLUSTER_API_AZURE_ROLE_NAME}" \ + --set azureOperatorsMI.clusterApiAzure.roleId="$${OP_CLUSTER_API_AZURE_ROLE_ID}" \ + --set azureOperatorsMI.controlPlane.roleName="${OP_CONTROL_PLANE_ROLE_NAME}" \ + --set azureOperatorsMI.controlPlane.roleId="$${OP_CONTROL_PLANE_ROLE_ID}" \ + --set azureOperatorsMI.cloudControllerManager.roleName="${OP_CLOUD_CONTROLLER_MANAGER_ROLE_NAME}" \ + --set azureOperatorsMI.cloudControllerManager.roleId="$${OP_CLOUD_CONTROLLER_MANAGER_ROLE_ID}" \ + --set azureOperatorsMI.ingress.roleName="${OP_INGRESS_ROLE_NAME}" \ + --set azureOperatorsMI.ingress.roleId="$${OP_INGRESS_ROLE_ID}" \ + --set azureOperatorsMI.diskCsiDriver.roleName="${OP_DISK_CSI_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.diskCsiDriver.roleId="$${OP_DISK_CSI_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.fileCsiDriver.roleName="${OP_FILE_CSI_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.fileCsiDriver.roleId="$${OP_FILE_CSI_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.imageRegistry.roleName="${OP_IMAGE_REGISTRY_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.imageRegistry.roleId="$${OP_IMAGE_REGISTRY_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.cloudNetworkConfig.roleName="${OP_CLOUD_NETWORK_CONFIG_ROLE_NAME}" \ + --set azureOperatorsMI.cloudNetworkConfig.roleId="$${OP_CLOUD_NETWORK_CONFIG_ROLE_ID}" deploy-pr-env-deps: AZURE_CS_MI_CLIENT_ID=$(shell az identity show -g ${RESOURCEGROUP} -n clusters-service --query clientId -o tsv) && \ oc process --local -f deploy/integration/cluster-service-namespace.yaml \ -p CLIENT_ID=$${AZURE_CS_MI_CLIENT_ID} | oc apply -f - -# for local development -provision-shard: - ZONE_RESOURCE_ID=$(shell az network dns zone show -n ${ZONE_NAME} -g ${REGIONAL_RESOURCEGROUP} --query id -o tsv) && \ - ../templatize.sh $(DEPLOY_ENV) deploy/provisioning-shards.tmpl.yml deploy/provisioning-shards.yml -e zoneResourceId=$${ZONE_RESOURCE_ID} - @cat deploy/provisioning-shards.yml +create-pr-env-sp: + CLUSTER_ID=$(shell az aks show -g ${RESOURCEGROUP} -n aro-hcp-aks --query id -o tsv) && \ + az ad sp create-for-rbac \ + --display-name "cs-pr-authentication" \ + --role 'Azure Kubernetes Service RBAC Admin' \ + --scopes "$${CLUSTER_ID}" + +local-deploy-provision-shard: + @ZONE_RESOURCE_ID=$(shell az network dns zone show -n ${ZONE_NAME} -g ${REGIONAL_RESOURCEGROUP} --query id -o tsv) && \ + CX_SECRETS_KV_URL=$(shell az keyvault show -n ${CX_SECRETS_KV_NAME} -g ${MGMT_RESOURCEGROUP} --query properties.vaultUri -o tsv) && \ + CX_MI_KV_URL=$(shell az keyvault show -n ${CX_MI_KV_NAME} -g ${MGMT_RESOURCEGROUP} --query properties.vaultUri -o tsv) && \ + ../templatize.sh $(DEPLOY_ENV) deploy/provisioning-shards.tmpl.yml deploy/local-provisioning-shards.yml -e zoneResourceId=$${ZONE_RESOURCE_ID},cxSecretsKeyVaultUrl=$${CX_SECRETS_KV_URL},cxMiKeyVaultUrl=$${CX_MI_KV_URL},maestroRestUrl=http://localhost:8001,maestroGrpUrl=localhost:8090 + @cat deploy/local-provisioning-shards.yml personal-runtime-config: @TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ @@ -75,6 +106,29 @@ personal-runtime-config: @cat deploy/azure-runtime-config.yaml .PHONY: personal-runtime-config +local-azure-operators-managed-identities-config: + @OP_CLOUD_CONTROLLER_MANAGER_ROLE_ID=$(shell az role definition list --name "${OP_CLOUD_CONTROLLER_MANAGER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_INGRESS_ROLE_ID=$(shell az role definition list --name "${OP_INGRESS_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_DISK_CSI_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_DISK_CSI_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_FILE_CSI_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_FILE_CSI_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_IMAGE_REGISTRY_DRIVER_ROLE_ID=$(shell az role definition list --name "${OP_IMAGE_REGISTRY_DRIVER_ROLE_NAME}" --query "[].name" -o tsv) && \ + OP_CLOUD_NETWORK_CONFIG_ROLE_ID=$(shell az role definition list --name "${OP_CLOUD_NETWORK_CONFIG_ROLE_NAME}" --query "[].name" -o tsv) && \ + helm template deploy/helm -s templates/azure-operators-managed-identities-config.configmap.yaml \ + --set azureOperatorsMI.cloudControllerManager.roleName="${OP_CLOUD_CONTROLLER_MANAGER_ROLE_NAME}" \ + --set azureOperatorsMI.cloudControllerManager.roleId="$${OP_CLOUD_CONTROLLER_MANAGER_ROLE_ID}" \ + --set azureOperatorsMI.ingress.roleName="${OP_INGRESS_ROLE_NAME}" \ + --set azureOperatorsMI.ingress.roleId="$${OP_INGRESS_ROLE_ID}" \ + --set azureOperatorsMI.diskCsiDriver.roleName="${OP_DISK_CSI_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.diskCsiDriver.roleId="$${OP_DISK_CSI_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.fileCsiDriver.roleName="${OP_FILE_CSI_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.fileCsiDriver.roleId="$${OP_FILE_CSI_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.imageRegistry.roleName="${OP_IMAGE_REGISTRY_DRIVER_ROLE_NAME}" \ + --set azureOperatorsMI.imageRegistry.roleId="$${OP_IMAGE_REGISTRY_DRIVER_ROLE_ID}" \ + --set azureOperatorsMI.cloudNetworkConfig.roleName="${OP_CLOUD_NETWORK_CONFIG_ROLE_NAME}" \ + --set azureOperatorsMI.cloudNetworkConfig.roleId="$${OP_CLOUD_NETWORK_CONFIG_ROLE_ID}" \ + | yq '.data."azure-operators-managed-identities-config.yaml"' > ./azure-operators-managed-identities-config.yaml +.PHONY: local-azure-operators-managed-identities-config + # # Shared OIDC Storage # @@ -87,6 +141,7 @@ shared-oidc-storage: az group create \ --name $(SHARED_OIDC_RG_NAME) \ --location westus3 \ + --tags persist=true \ --output none; \ fi az deployment group create \ @@ -113,4 +168,4 @@ shared-storage-runtime-config: @cat deploy/azure-runtime-config.yaml .PHONY: shared-storage-runtime-config -.PHONY: deploy deploy-using-azure-db deploy-integ provision-shard configure-tmp-provision-shard deploy-secrets-template deploy-secrets-template-using-azure-db deploy-istio-configurations-template deploy-namespace-template runtime-config +.PHONY: create-pr-env-sp deploy deploy-using-azure-db deploy-integ configure-tmp-provision-shard deploy-secrets-template deploy-secrets-template-using-azure-db deploy-istio-configurations-template deploy-namespace-template runtime-config diff --git a/cluster-service/deploy/openshift-templates/arohcp.devenv.md b/cluster-service/arohcp.devenv.md similarity index 100% rename from cluster-service/deploy/openshift-templates/arohcp.devenv.md rename to cluster-service/arohcp.devenv.md diff --git a/cluster-service/config.tmpl.mk b/cluster-service/config.tmpl.mk deleted file mode 100644 index d1e888716..000000000 --- a/cluster-service/config.tmpl.mk +++ /dev/null @@ -1,21 +0,0 @@ -REGION ?= {{ .region }} -CONSUMER_NAME ?= {{ .maestroConsumerName }} -RESOURCEGROUP ?= {{ .serviceClusterRG }} -REGIONAL_RESOURCEGROUP ?= {{ .regionRG }} -AKS_NAME ?= {{ .aksName }} -SERVICE_KV ?= {{ .serviceKeyVaultName }} -OIDC_STORAGE_ACCOUNT ?= {{ .oidcStorageAccountName }} -IMAGE_REPO ?= {{ .clusterServiceImageRepo }} -IMAGE_TAG ?= {{ .clusterServiceImageTag }} -ACR_NAME ?= {{ .svcAcrName }} -OCP_ACR_NAME ?= {{ .ocpAcrName }} -AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID ?= {{ .firstPartyAppClientId }} -FPA_CERT_NAME ?= firstPartyCert -ZONE_NAME ?= {{ .regionalDNSSubdomain }}.{{ .baseDnsZoneName }} - -DATABASE_DISABLE_TLS ?= {{ not .clusterServicePostgresDeploy }} -DATABASE_AUTH_METHOD ?= {{ ternary "az-entra" "postgres" .clusterServicePostgresDeploy }} -DATABASE_SERVER_NAME ?= {{ .clusterServicePostgresName }} -DB_SECRET_TARGET = {{ ternary "deploy-azure-db-secret" "deploy-local-db-secret" .clusterServicePostgresDeploy }} - -DEVOPS_MSI_ID ?= {{ .aroDevopsMsiId }} diff --git a/cluster-service/deploy/azure-runtime-config.tmpl.yaml b/cluster-service/deploy/azure-runtime-config.tmpl.yaml index e5ecd67d9..54f6f6ee2 100644 --- a/cluster-service/deploy/azure-runtime-config.tmpl.yaml +++ b/cluster-service/deploy/azure-runtime-config.tmpl.yaml @@ -1,12 +1,13 @@ { - "cloudEnvironment": "AzurePublicCloud", - "tenantId": "{{ .extraVars.tenantId }}", - "ocpImagesAcr": { - "resourceId": "{{ .extraVars.ocpAcrResourceId }}", + "cloud_environment": "AzurePublicCloud", + "tenant_id": "{{ .extraVars.tenantId }}", + "managed_identities_data_plane_audience_resource": "https://dummy.org", + "ocp_images_acr": { + "resource_id": "{{ .extraVars.ocpAcrResourceId }}", "url": "{{ .extraVars.ocpAcrResourceUrl }}", - "scopeMapName": "_repositories_pull" + "scope_map_name": "_repositories_pull" }, - "dataplane_identities_oidc_configuration": { + "data_plane_identities_oidc_configuration": { "storage_account_blob_container_name": "{{ .extraVars.oidc_container }}", "storage_account_blob_service_url": "{{ .extraVars.oidc_service_url }}", "oidc_issuer_base_url": "{{ .extraVars.oidc_issuer_base_url }}" diff --git a/cluster-service/deploy/dev-provisioning-shards.tmpl.yml b/cluster-service/deploy/dev-provisioning-shards.tmpl.yml deleted file mode 100644 index 0f99e08eb..000000000 --- a/cluster-service/deploy/dev-provisioning-shards.tmpl.yml +++ /dev/null @@ -1,18 +0,0 @@ -provision_shards: -- id: 1 - maestro_config: | - { - "rest_api_config": { - "url": "http://localhost:8001" - }, - "grpc_api_config": { - "url": "localhost:8090" - }, - "consumer_name": "{{ .maestroConsumerName }}" - } - status: active - azure_base_domain: {{ .extraVars.zoneResourceId }} - management_cluster_id: {{ .regionRG }} - region: {{ .regionRG }} - cloud_provider: azure - topology: dedicated diff --git a/cluster-service/deploy/helm/.helmignore b/cluster-service/deploy/helm/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/cluster-service/deploy/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/cluster-service/deploy/helm/Chart.yaml b/cluster-service/deploy/helm/Chart.yaml new file mode 100644 index 000000000..8b43a7921 --- /dev/null +++ b/cluster-service/deploy/helm/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +name: cluster-service +description: A Helm chart for Cluster Service +type: application +version: 0.1.0 + +appVersion: "1.16.0" + +dependencies: + - name: database + version: 0.1.0 + repository: "file://charts/database" + condition: deployLocalDatabase diff --git a/cluster-service/deploy/helm/azuredb.values.yaml b/cluster-service/deploy/helm/azuredb.values.yaml new file mode 100644 index 000000000..6278ef61e --- /dev/null +++ b/cluster-service/deploy/helm/azuredb.values.yaml @@ -0,0 +1,6 @@ +databaseDisableTls: false +databaseAuthMethod: az-entra +deployLocalDatabase: false +databaseName: clusters-service +databaseUser: clusters-service +databasePassword: '' diff --git a/cluster-service/deploy/helm/charts/database/Chart.yaml b/cluster-service/deploy/helm/charts/database/Chart.yaml new file mode 100644 index 000000000..0bed3783c --- /dev/null +++ b/cluster-service/deploy/helm/charts/database/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: database +description: A Helm chart for a Local Cluster Service Database +type: application +version: 0.1.0 diff --git a/cluster-service/deploy/helm/charts/database/templates/database.deployment.yaml b/cluster-service/deploy/helm/charts/database/templates/database.deployment.yaml new file mode 100644 index 000000000..8916157d0 --- /dev/null +++ b/cluster-service/deploy/helm/charts/database/templates/database.deployment.yaml @@ -0,0 +1,69 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.databaseServiceName }} + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + name: {{ .Values.databaseServiceName }} + strategy: + type: Recreate + template: + metadata: + labels: + name: {{ .Values.databaseServiceName }} + spec: + containers: + - env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + key: db.user + name: {{ .Values.databaseK8sSecretName }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: db.password + name: {{ .Values.databaseK8sSecretName }} + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + key: db.name + name: {{ .Values.databaseK8sSecretName }} + - name: PGDATA + value: /var/lib/pgsql/data/pgdata + image: docker.io/library/postgres:16.2 + imagePullPolicy: IfNotPresent + livenessProbe: + tcpSocket: + port: 5432 + initialDelaySeconds: 120 + timeoutSeconds: 10 + name: postgresql + ports: + - containerPort: 5432 + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - exec /usr/bin/pg_isready -U $POSTGRES_USER -d $POSTGRES_DB -h localhost -p 5432 + initialDelaySeconds: 5 + timeoutSeconds: 1 + securityContext: + capabilities: {} + privileged: false + terminationMessagePath: /dev/termination-log + volumeMounts: + - mountPath: /var/lib/pgsql/data + name: '{{ .Values.databaseServiceName }}-data' + dnsPolicy: ClusterFirst + restartPolicy: Always + volumes: + - name: '{{ .Values.databaseServiceName }}-data' + persistentVolumeClaim: + claimName: {{ .Values.databaseServiceName }} diff --git a/cluster-service/deploy/helm/charts/database/templates/database.pvc.yaml b/cluster-service/deploy/helm/charts/database/templates/database.pvc.yaml new file mode 100644 index 000000000..2af978c02 --- /dev/null +++ b/cluster-service/deploy/helm/charts/database/templates/database.pvc.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.databaseServiceName }} + namespace: {{ .Release.Namespace }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.databaseVolumeCapacity }} diff --git a/cluster-service/deploy/helm/charts/database/templates/database.service.yaml b/cluster-service/deploy/helm/charts/database/templates/database.service.yaml new file mode 100644 index 000000000..cb7e390c6 --- /dev/null +++ b/cluster-service/deploy/helm/charts/database/templates/database.service.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.databaseServiceName }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - name: postgresql + nodePort: 0 + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + name: {{ .Values.databaseServiceName }} + sessionAffinity: None + type: ClusterIP diff --git a/cluster-service/deploy/helm/charts/database/values.yaml b/cluster-service/deploy/helm/charts/database/values.yaml new file mode 100644 index 000000000..5faefc0cf --- /dev/null +++ b/cluster-service/deploy/helm/charts/database/values.yaml @@ -0,0 +1,26 @@ +# The name of the OpenShift Service exposed for the database. +databaseServiceName: ocm-cs-db + +# The name of the K8s secret where CS DB connection information is placed +databaseK8sSecretName: ocm-cs-db + +# Volume space available for data, e.g. 512Mi, 2Gi. +databaseVolumeCapacity: 512Mi + +# Version of PostgreSQL image to be used (10 or latest). +postgresqlVersion: "12" + +# The hostname of the postgres server/service. It can be a K8s service name +databaseHost: "ocm-cs-db" + +# Username for PostgreSQL user that will be used for accessing the database. +databaseUser: "ocm" + +# Password for the PostgreSQL connection user. +databasePassword: "TheBlurstOfTimes" + +# Name of the PostgreSQL database accessed. +databaseName: "ocm-cs-db" + +# Host port +databasePort: "5432" diff --git a/cluster-service/deploy/helm/containerdb.values.yaml b/cluster-service/deploy/helm/containerdb.values.yaml new file mode 100644 index 000000000..0b814b1b2 --- /dev/null +++ b/cluster-service/deploy/helm/containerdb.values.yaml @@ -0,0 +1,6 @@ +databaseDisableTls: true +databaseAuthMethod: postgres +deployLocalDatabase: true +databaseName: ocm-cs-db +databaseUser: ocm +databasePassword: TheBlurstOfTimes diff --git a/cluster-service/deploy/helm/templates/authentication.configmap.yaml b/cluster-service/deploy/helm/templates/authentication.configmap.yaml new file mode 100644 index 000000000..adc4ada49 --- /dev/null +++ b/cluster-service/deploy/helm/templates/authentication.configmap.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: authentication + namespace: {{ .Release.Namespace }} +data: + jwks.json: "" + acl.yml: "" diff --git a/cluster-service/deploy/helm/templates/azure-credentials.secret.yaml b/cluster-service/deploy/helm/templates/azure-credentials.secret.yaml new file mode 100644 index 000000000..7827f9c13 --- /dev/null +++ b/cluster-service/deploy/helm/templates/azure-credentials.secret.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: azure-credentials + namespace: {{ .Release.Namespace }} +type: Opaque +data: + azure-auth-config: {{ .Values.csServicePrincipalCredsBase64 }} diff --git a/cluster-service/deploy/helm/templates/azure-operators-managed-identities-config.configmap.yaml b/cluster-service/deploy/helm/templates/azure-operators-managed-identities-config.configmap.yaml new file mode 100644 index 000000000..fe1aa1e91 --- /dev/null +++ b/cluster-service/deploy/helm/templates/azure-operators-managed-identities-config.configmap.yaml @@ -0,0 +1,82 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: azure-operators-managed-identities-config + namespace: {{ .Release.Namespace }} +data: + azure-operators-managed-identities-config.yaml: | + controlPlaneOperatorsIdentities: + cluster-api-azure: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.clusterApiAzure.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.clusterApiAzure.roleName }}' + optional: false + control-plane: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.controlPlane.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.controlPlane.roleName }}' + optional: false + cloud-controller-manager: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.cloudControllerManager.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.cloudControllerManager.roleName }}' + optional: false + ingress: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.ingress.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.ingress.roleName }}' + optional: false + disk-csi-driver: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.diskCsiDriver.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.diskCsiDriver.roleName }}' + optional: false + file-csi-driver: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.fileCsiDriver.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.fileCsiDriver.roleName }}' + optional: false + image-registry: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.imageRegistry.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.imageRegistry.roleName }}' + optional: false + cloud-network-config: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.cloudNetworkConfig.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.cloudNetworkConfig.roleName }}' + optional: false + dataPlaneOperatorsIdentities: + disk-csi-driver: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.diskCsiDriver.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.diskCsiDriver.roleName }}' + k8sServiceAccounts: + - name: 'azure-disk-csi-driver-operator' + namespace: 'openshift-cluster-csi-drivers' + - name: 'azure-disk-csi-driver-controller-sa' + namespace: 'openshift-cluster-csi-drivers' + optional: false + image-registry: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.imageRegistry.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.imageRegistry.roleName }}' + k8sServiceAccounts: + - name: 'cluster-image-registry-operator' + namespace: 'openshift-image-registry' + - name: 'registry' + namespace: 'openshift-image-registry' + optional: false + file-csi-driver: + minOpenShiftVersion: 4.17 + azureRoleDefinitionResourceId: '/providers/Microsoft.Authorization/roleDefinitions/{{ .Values.azureOperatorsMI.fileCsiDriver.roleId }}' + azureRoleDefinitionName: '{{ .Values.azureOperatorsMI.fileCsiDriver.roleName }}' + k8sServiceAccounts: + - name: 'azure-file-csi-driver-operator' + namespace: 'openshift-cluster-csi-drivers' + - name: 'azure-file-csi-driver-controller-sa' + namespace: 'openshift-cluster-csi-drivers' + - name: 'azure-file-csi-driver-node-sa' + namespace: 'openshift-cluster-csi-drivers' + optional: false diff --git a/cluster-service/deploy/helm/templates/azure-runtime-config.configmap.yaml b/cluster-service/deploy/helm/templates/azure-runtime-config.configmap.yaml new file mode 100644 index 000000000..07c0603e5 --- /dev/null +++ b/cluster-service/deploy/helm/templates/azure-runtime-config.configmap.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: azure-runtime-config + namespace: {{ .Release.Namespace }} +data: + config.json: | + { + "cloud_environment": "AzurePublicCloud", + "managed_identities_data_plane_audience_resource": "{{ .Values.managedIdentitiesDataPlaneAudienceResource }}", + "tenant_id": "{{ .Values.tenantId }}", + "ocp_images_acr": { + "resource_id": "{{ .Values.ocpAcrResourceId }}", + "url": "{{ .Values.ocpAcrUrl }}", + "scope_map_name": "_repositories_pull" + }, + "data_plane_identities_oidc_configuration": { + "storage_account_blob_container_name": "$web", + "storage_account_blob_service_url": "{{ .Values.oidcIssuerBlobServiceUrl }}", + "oidc_issuer_base_url": "{{ .Values.oidcIssuerBaseUrl }}" + } + } diff --git a/cluster-service/deploy/helm/templates/cloud-resource-constraints-config.configmap.yaml b/cluster-service/deploy/helm/templates/cloud-resource-constraints-config.configmap.yaml new file mode 100644 index 000000000..fb854609f --- /dev/null +++ b/cluster-service/deploy/helm/templates/cloud-resource-constraints-config.configmap.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloud-resource-constraints-config + namespace: {{ .Release.Namespace }} +data: + instance-type-constraints.yaml: | + instance_types: + - id: Standard_D8s_v3 + ccs_only: true + enabled: true + cloud-region-constraints.yaml: | + cloud_regions: + - id: {{ .Values.region }} + enabled: true + govcloud: false + ccs_only: false diff --git a/cluster-service/deploy/helm/templates/cloud-resources-config.configmap.yaml b/cluster-service/deploy/helm/templates/cloud-resources-config.configmap.yaml new file mode 100644 index 000000000..b4f2969b7 --- /dev/null +++ b/cluster-service/deploy/helm/templates/cloud-resources-config.configmap.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cloud-resources-config + namespace: {{ .Release.Namespace }} +data: + instance-types.yaml: | + instance_types: + - id: Standard_D8s_v3 + name: Standard_D8s_v3 - General purpose + cloud_provider_id: azure + cpu_cores: 8 + memory: 34359738368 + category: general_purpose + size: d8s_v3 + generic_name: standard-d8s_v3 + cloud-regions.yaml: | + cloud_regions: + - id: {{ .Values.region }} + cloud_provider_id: azure + display_name: Azure East US + supports_multi_az: true diff --git a/cluster-service/deploy/helm/templates/cluster-proxy-service-config.configmap.yaml b/cluster-service/deploy/helm/templates/cluster-proxy-service-config.configmap.yaml new file mode 100644 index 000000000..2a9303fa8 --- /dev/null +++ b/cluster-service/deploy/helm/templates/cluster-proxy-service-config.configmap.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-proxy-service-config + namespace: {{ .Release.Namespace }} +data: + config.yaml: | + # Hosts that should be added to noProxy for all clusters + noProxy: [] + # Hosts that should be added to noProxy for AWS clusters + noProxy_aws: [] + # Hosts that should be added to noProxy for GCP clusters + noProxy_gcp: [] + # Readiness endpoints that verify proxy connectivity + readinessEndpoints: + - "https://api.openshift.com" diff --git a/cluster-service/deploy/helm/templates/clusters-service.secret.yaml b/cluster-service/deploy/helm/templates/clusters-service.secret.yaml new file mode 100644 index 000000000..227752f09 --- /dev/null +++ b/cluster-service/deploy/helm/templates/clusters-service.secret.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: clusters-service + namespace: {{ .Release.Namespace }} +stringData: + client.id: '{{ .Values.clientId }}' + client.secret: '{{ .Values.clientSecret }}' diff --git a/cluster-service/deploy/helm/templates/cs-keyvault.secret.yaml b/cluster-service/deploy/helm/templates/cs-keyvault.secret.yaml new file mode 100644 index 000000000..8e454f2f8 --- /dev/null +++ b/cluster-service/deploy/helm/templates/cs-keyvault.secret.yaml @@ -0,0 +1,27 @@ +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: cs-keyvault + namespace: {{ .Release.Namespace }} +spec: + parameters: + clientID: {{ .Values.azureCsMiClientId }} + cloudName: AzurePublicCloud + keyvaultName: {{ .Values.serviceKeyvaultName }} + objects: |- + array: + - | + objectName: {{ .Values.fpaCertName }} + objectType: secret + objectAlias: firstPartyApplicationCertificateBundle + - | + objectName: {{ .Values.azureMiMockServicePrincipalCertName }} + objectType: secret + objectAlias: mockMiServicePrincipalCertificateBundle + - | + objectName: {{ .Values.azureArmHelperIdentityCertName }} + objectType: secret + objectAlias: armHelperIndentityCertificateBundle + tenantId: {{ .Values.tenantId }} + usePodIdentity: "false" + provider: azure diff --git a/cluster-service/deploy/helm/templates/database.secret.yaml b/cluster-service/deploy/helm/templates/database.secret.yaml new file mode 100644 index 000000000..a8f15debc --- /dev/null +++ b/cluster-service/deploy/helm/templates/database.secret.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.databaseK8sSecretName }} + namespace: {{ .Release.Namespace }} +stringData: + db.host: '{{ .Values.databaseHost }}' + db.name: '{{ .Values.databaseName }}' + db.password: '{{ .Values.databasePassword }}' + db.user: '{{ .Values.databaseUser }}' + db.port: '{{ .Values.databasePort }}' diff --git a/cluster-service/deploy/helm/templates/deployment.yaml b/cluster-service/deploy/helm/templates/deployment.yaml new file mode 100644 index 000000000..e1a2496b7 --- /dev/null +++ b/cluster-service/deploy/helm/templates/deployment.yaml @@ -0,0 +1,223 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: clusters-service + namespace: {{ .Release.Namespace }} + labels: + app: clusters-service +spec: + selector: + matchLabels: + app: clusters-service + replicas: {{ .Values.replicas }} + template: + metadata: + labels: + app: clusters-service + azure.workload.identity/use: "true" + annotations: + checksum/db: {{ include (print $.Template.BasePath "/database.secret.yaml") . | sha256sum }} + checksum/azurecreds: {{ include (print $.Template.BasePath "/azure-credentials.secret.yaml") . | sha256sum }} + checksum/operatorcfg: {{ include (print $.Template.BasePath "/azure-operators-managed-identities-config.configmap.yaml") . | sha256sum }} + checksum/cskv: {{ include (print $.Template.BasePath "/cs-keyvault.secret.yaml") . | sha256sum }} + checksum/provisionshard: {{ include (print $.Template.BasePath "/provisioning-shards.secret.yaml") . | sha256sum }} + checksum/cs: {{ include (print $.Template.BasePath "/clusters-service.secret.yaml") . | sha256sum }} + checksum/runtime: {{ include (print $.Template.BasePath "/azure-runtime-config.configmap.yaml") . | sha256sum }} + spec: + serviceAccount: {{ .Values.serviceAccountName }} + serviceAccountName: {{ .Values.serviceAccountName }} + volumes: + - name: service + secret: + secretName: clusters-service + - name: shards + secret: + secretName: provision-shards + - name: rds + secret: + secretName: ocm-cs-db + - name: oidc + secret: + secretName: rh-oidc-s3-secret + - name: authentication + configMap: + name: authentication + - name: region-constraints + configMap: + name: region-constraints-config + - name: instance-types + configMap: + name: cloud-resources-config + - name: instance-type-constraints + configMap: + name: cloud-resource-constraints-config + - name: cloud-regions + configMap: + name: cloud-resources-config + - name: cloud-region-constraints + configMap: + name: cloud-resource-constraints-config + - name: proxy + configMap: + name: cluster-proxy-service-config + - name: azure-runtime-config + configMap: + name: azure-runtime-config + - name: azure-operators-managed-identities-config + configMap: + name: azure-operators-managed-identities-config + - name: mixin-pull-secret + secret: + secretName: hive-ci-global-pull-secret + optional: true + - name: azure-credentials + secret: + secretName: azure-credentials + - name: keyvault + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: cs-keyvault + initContainers: + - name: init + image: '{{ .Values.imageRegistry }}/{{ .Values.imageRepository }}:{{ .Values.imageTag }}' + imagePullPolicy: IfNotPresent + volumeMounts: + - name: rds + mountPath: /secrets/rds + - name: service + mountPath: /secrets/service + command: + - /usr/local/bin/clusters-service + - init + - --db-host=@/secrets/rds/db.host + - --db-port=@/secrets/rds/db.port + - --db-name=@/secrets/rds/db.name + - --db-user=@/secrets/rds/db.user + - --db-password=@/secrets/rds/db.password + - --db-disable-tls={{ .Values.databaseDisableTls }} + - --db-auth-method={{ .Values.databaseAuthMethod }} + - --force-migration={{ .Values.forceMigration }} + - --batch-processes-dry-run={{ .Values.batchProcessesDryRun }} + - --batch-processes={{ .Values.batchProcesses }} + containers: + - name: service + image: '{{ .Values.imageRegistry }}/{{ .Values.imageRepository }}:{{ .Values.imageTag }}' + imagePullPolicy: IfNotPresent + volumeMounts: + - name: service + mountPath: /secrets/service + - name: shards + mountPath: /secrets/shards + - name: rds + mountPath: /secrets/rds + - name: authentication + mountPath: /configs/authentication + - name: region-constraints + mountPath: /configs/region-constraints + - name: proxy + mountPath: /configs/proxy + - name: mixin-pull-secret + mountPath: /secrets/mixin-pull-secret + - name: instance-types + mountPath: /configs/cloud-resources/instance-types.yaml + subPath: instance-types.yaml + - name: instance-type-constraints + mountPath: /configs/cloud-resource-constraints/instance-type-constraints.yaml + subPath: instance-type-constraints.yaml + - name: cloud-regions + mountPath: /configs/cloud-resources/cloud-regions.yaml + subPath: cloud-regions.yaml + - name: cloud-region-constraints + mountPath: /configs/cloud-resource-constraints/cloud-region-constraints.yaml + subPath: cloud-region-constraints.yaml + - name: azure-credentials + mountPath: /secrets/azure-credentials + - name: keyvault + mountPath: "/secrets/keyvault" + readOnly: true + - name: azure-runtime-config + mountPath: /configs/azure-runtime-config + - name: azure-operators-managed-identities-config + mountPath: /configs/azure-operators-managed-identities-config.yaml + subPath: azure-operators-managed-identities-config.yaml + command: + - /usr/local/bin/clusters-service + - serve + - --log-level={{ .Values.logLevel }} + - --namespace={{ .Release.Namespace }} + - --runtime-mode={{ .Values.runtimeMode }} + - --default-expiration={{ .Values.defaultExpiration }} + - --maximum-expiration={{ .Values.maximumExpiration }} + - --db-host=@/secrets/rds/db.host + - --db-port=@/secrets/rds/db.port + - --db-name=@/secrets/rds/db.name + - --db-user=@/secrets/rds/db.user + - --db-password=@/secrets/rds/db.password + - --db-disable-tls={{ .Values.databaseDisableTls }} + - --db-auth-method={{ .Values.databaseAuthMethod }} + - --gateway-url={{ .Values.gatewayURL }} + - --client-id=@/secrets/service/client.id + - --client-secret=@/secrets/service/client.secret + - --client-scopes={{ .Values.clientScopes }} + - --user-defined-dns-base-domain={{ .Values.userDefinedDnsBaseDomain }} + - --jwks-url={{ .Values.jwksUrl }} + - --jwks-file=/configs/authentication/jwks.json + - --acl-file=/configs/authentication/acl.yml + - --token-url={{ .Values.tokenUrl }} + - --insecure={{ .Values.insecure }} + - --api-listener-network=tcp + - --api-listener-address=:8000 + - --metrics-listener-network=tcp + - --metrics-listener-address=:8080 + - --healthcheck-listener-network=tcp + - --healthcheck-listener-address=:8083 + - --environment={{ .Values.environment }} + - --backplane-url={{ .Values.backplaneURL }} + - --provision-shards-config=/secrets/shards/config + - --proxy-config-file=/configs/proxy/config.yaml + - --aws-sts-policy-directory=/configs/policies + - --mixin-pull-secret-path=/secrets/mixin-pull-secret + - --region-constraints-config=/configs/region-constraints/config.yaml + - --instance-type-config=/configs/cloud-resources/instance-types.yaml + - --instance-type-constraints-config=/configs/cloud-resource-constraints/instance-type-constraints.yaml + - --cloud-region-config=/configs/cloud-resources/cloud-regions.yaml + - --cloud-region-constraints-config=/configs/cloud-resource-constraints/cloud-region-constraints.yaml + - --azure-auth-config-path=/secrets/azure-credentials/azure-auth-config + - --azure-first-party-application-client-id={{ .Values.azureFirstPartyApplicationClientId }} + - --azure-first-party-application-certificate-bundle-path=/secrets/keyvault/firstPartyApplicationCertificateBundle + - --azure-runtime-config-path=/configs/azure-runtime-config/config.json + - --azure-operators-managed-identities-config-path=/configs/azure-operators-managed-identities-config.yaml + - --azure-mi-mock-service-principal-certificate-bundle-path=/secrets/keyvault/mockMiServicePrincipalCertificateBundle + - --azure-mi-mock-service-principal-client-id={{ .Values.azureMiMockServicePrincipalClientId }} + - --azure-mi-mock-service-principal-principal-id={{ .Values.azureMiMockServicePrincipalPrincipalId }} + - --azure-arm-helper-identity-certificate-bundle-path=/secrets/keyvault/armHelperIndentityCertificateBundle + - --azure-arm-helper-identity-client-id={{ .Values.azureArmHelperIdentityClientId }} + - --azure-arm-helper-mock-fpa-principal-id={{ .Values.azureArmHelperMockFpaPrincipalId }} + livenessProbe: + httpGet: + path: /api/clusters_mgmt/v1 + port: 8000 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /healthcheck + port: 8083 + scheme: HTTP + httpHeaders: + - name: User-Agent + value: Probe + initialDelaySeconds: 20 + periodSeconds: 10 + resources: + requests: + memory: {{ .Values.memoryRequest }} + cpu: {{ .Values.cpuRequest }} + limits: + memory: {{ .Values.memoryLimit }} + cpu: {{ .Values.cpuLimit }} diff --git a/cluster-service/deploy/istio.yml b/cluster-service/deploy/helm/templates/istio.yml similarity index 82% rename from cluster-service/deploy/istio.yml rename to cluster-service/deploy/helm/templates/istio.yml index 0c3eede83..f0b95a81e 100644 --- a/cluster-service/deploy/istio.yml +++ b/cluster-service/deploy/helm/templates/istio.yml @@ -2,7 +2,7 @@ apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default - namespace: cluster-service + namespace: {{ .Release.Namespace }} spec: selector: matchLabels: @@ -15,7 +15,7 @@ apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: allow-metrics - namespace: cluster-service + namespace: {{ .Release.Namespace }} spec: action: "ALLOW" rules: @@ -32,14 +32,14 @@ apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: allow-nothing - namespace: cluster-service + namespace: {{ .Release.Namespace }} spec: {} --- apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: allow-frontend - namespace: cluster-service + namespace: {{ .Release.Namespace }} spec: action: "ALLOW" rules: @@ -61,13 +61,13 @@ apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: allow-intra-namespace - namespace: cluster-service + namespace: {{ .Release.Namespace }} spec: action: "ALLOW" rules: - from: - source: - principals: ["cluster.local/ns/cluster-service/sa/clusters-service"] + principals: ["cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.serviceAccountName }}"] to: - operation: ports: diff --git a/cluster-service/deploy/helm/templates/provisioning-shards.secret.yaml b/cluster-service/deploy/helm/templates/provisioning-shards.secret.yaml new file mode 100644 index 000000000..78dcd4e1c --- /dev/null +++ b/cluster-service/deploy/helm/templates/provisioning-shards.secret.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: provision-shards + namespace: {{ .Release.Namespace }} +stringData: + config: | + provision_shards: + - id: 1 + maestro_config: | + { + "rest_api_config": { + "url": "{{ .Values.shard.maestroRestUrl }}" + }, + "grpc_api_config": { + "url": "{{ .Values.shard.maestroGrpUrl }}" + }, + "consumer_name": "{{ .Values.shard.consumerName }}" + } + status: active + management_cluster_id: local-cluster + region: {{ .Values.region }} + cloud_provider: azure + topology: dedicated + azure_shard: + public_dns_zone_resource_id: "{{ .Values.shard.zoneResourceId }}" + cx_secrets_key_vault_url: "{{ .Values.shard.cxSecretsKeyVaultUrl }}" + cx_managed_identities_key_vault_url: "{{ .Values.shard.cxMiKeyVaultUrl }}" diff --git a/cluster-service/deploy/helm/templates/region-constraints-config.configmap.yaml b/cluster-service/deploy/helm/templates/region-constraints-config.configmap.yaml new file mode 100644 index 000000000..1aad1bc2f --- /dev/null +++ b/cluster-service/deploy/helm/templates/region-constraints-config.configmap.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: region-constraints-config + namespace: {{ .Release.Namespace }} +data: + config.yaml: | + cloud_providers: + - name: azure + regions: + - name: {{ .Values.region }} + version_constraints: + min_version: 4.11.0 diff --git a/cluster-service/deploy/helm/templates/service.yaml b/cluster-service/deploy/helm/templates/service.yaml new file mode 100644 index 000000000..884374c93 --- /dev/null +++ b/cluster-service/deploy/helm/templates/service.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: clusters-service + namespace: {{ .Release.Namespace }} + labels: + app: clusters-service + port: api +spec: + selector: + app: clusters-service + ports: + - port: 8000 + targetPort: 8000 + protocol: TCP + +--- +# Services for diagnostic ports (not part of main service because we +# don't want exposing them externally through same route). +apiVersion: v1 +kind: Service +metadata: + name: clusters-service-metrics + namespace: {{ .Release.Namespace }} + labels: + # {app, port} labels together identify this service for monitoring + app: clusters-service + port: metrics +spec: + selector: + app: clusters-service + ports: + - port: 8080 + targetPort: 8080 + name: metrics + protocol: TCP +--- +apiVersion: v1 +kind: Service +metadata: + name: clusters-service-healthcheck + namespace: {{ .Release.Namespace }} + labels: + app: clusters-service + port: healthcheck +spec: + selector: + app: clusters-service + ports: + - port: 8083 + targetPort: 8083 + name: healthcheck + protocol: TCP diff --git a/cluster-service/deploy/helm/templates/serviceaccount.yaml b/cluster-service/deploy/helm/templates/serviceaccount.yaml new file mode 100644 index 000000000..68acd7dfe --- /dev/null +++ b/cluster-service/deploy/helm/templates/serviceaccount.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.serviceAccountName }} + namespace: {{ .Release.Namespace }} + labels: + app: clusters-service + annotations: + azure.workload.identity/client-id: '{{ .Values.azureCsMiClientId }}' diff --git a/cluster-service/deploy/helm/templates/servicemonitor.yaml b/cluster-service/deploy/helm/templates/servicemonitor.yaml new file mode 100644 index 000000000..05136d44e --- /dev/null +++ b/cluster-service/deploy/helm/templates/servicemonitor.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: azmonitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: clusters-service-service-monitor + namespace: {{ .Release.Namespace }} +spec: + endpoints: + - interval: 30s + path: /metrics + port: metrics + scheme: http + namespaceSelector: + matchNames: + - cluster-service + selector: + matchLabels: + app: clusters-service + port: metrics diff --git a/cluster-service/deploy/helm/values.yaml b/cluster-service/deploy/helm/values.yaml new file mode 100644 index 000000000..d7c1c5435 --- /dev/null +++ b/cluster-service/deploy/helm/values.yaml @@ -0,0 +1,299 @@ +# service account name +serviceAccountName: clusters-service + + +# TODO: This parameter isn't currently used, but kept to avoid failures in the +# execution of saasherder. It will be removed once the version of the service +# that doesn't use it is deployed to all environments. +debugPort: "" + +# Maximum allowed duration for /debug/pprof/ profiling requests, e.g. "30s" or "5m". "0" means no limit. +debugMaxDuration: "5m" + +# Sets the runtime configuration mode for CS. +runtimeMode: "aro-hcp" + +# Default expiration time assigned to any newly created cluster (e.g. 45m or 72h). 0 means no expiration. +defaultExpiration: "0" + +# Maximum expiration duration possible for any newly created cluster (e.g. 72h means the expiration date cannot be greater than 72h). 0 means no maximum expiration value possible. +maximumExpiration: "0" + +# Duration since cluster creation after which the first notification for stale cluster should be sent. +firstStaleClusterNotification: "24h" # 1 day + +# Duration since cluster creation after which the second notification for stale cluster should be sent. +secondStaleClusterNotification: "600h" # 25 days + +# Duration after which a stale cluster can be cleaned up. +staleClusterAutocleanupWindow: "720h" # 30 days + +# Image Registry +imageRegistry: "" + +# Image Repository +imageRepository: "" + +# Image Tag +imageTag: "" + +# log verbosity level +logLevel: "debug" + +# Number of replicas of the service to run. +replicas: 1 + +# Location of the JSON web key set used to verify tokens. +jwksUrl: "http://localhost" + +# Location of the service that issues JSON web tokens. +tokenUrl: "http://localhost" + +# Disable TLS certificate verification on authentication. +insecure: "false" + +# The URL of the gateway. +gatewayUrl: "http://127.0.0.1:9090" + +# Level of access that an app can request to a resource. +clientScopes: "openid" + +# Environment associated with this instance. +environment: "aro-hcp-dev" + +# The URL of the Backplane API which is exposed via an endpoint and is dynamically consumed by the Backplane CLI. +# Backplane CLI expects a URL with the following format https://api..backplane. +# The part is specific to each deployment environment. The part is optional. +# Note: this is defaulted to empty string and should be overriden in fedramp app-interface. +# This being an empty string, CS will send an empty string back via the /environment endpoint +# thus making the Backplane CLI failover to check if the backplane user has an environment variable BACKPLANE_URL set and use it instead. +backplaneURL: "" + +# Provision shard limit of managed clusters. +provisionShardClusterLimit: "500" + +# If not empty clears the dirty flag and forces the given migration version. +forceMigration: "" + +# If set to true, a cluster error will trigger a report. +clusterErrorReport: "false" + +# Period between executions of day-1 machine pool migration worker. Useful time units are "m" or "h". +machinePoolMigrationWorkerPeriod: "1h" + +# The name of the DNS base domain for creating a user defined domains. +# Note: this is defaulted to a commercial value. This should be overriden in fedramp app-interface +userDefinedDnsBaseDomain: "i1.devshift.org" + +# Signals batch processes step to run in dry run. +batchProcessesDryRun: "true" + +# Date identification of each batch process expected to be run. Comma separated sequence. +batchProcesses: "" + +# The URL of the Azure Container Registry where the OpenShift images are stored. +ocpAcrURL: "" + +# The resource ID of the Azure Container Registry where the OpenShift images are stored. +ocpAcrResourceId: "" + +# These limits are based on the metrics collected in the production environment +# over the last year. In particular the following Prometheus queries were used +# to obtain the values: +# +# - For the memory request: +# +# max( +# quantile_over_time( +# 0.5, +# container_memory_usage_bytes{ +# cluster="app-sre", +# namespace="uhc-production", +# pod_name=~"^clusters-service-.*$", +# container_name="service" +# } +# [1w] +# ) +# ) +# +# The result was exactly 88322048. Added a margin of 25% and rounded up to a +# multiple of 50 MiB which results in 150 MiB. +# +# - For the memory limit: +# +# max( +# max_over_time( +# container_memory_usage_bytes{ +# cluster="app-sre", +# namespace="uhc-production", +# pod_name=~"^clusters-service-.*$", +# container_name="service" +# } +# [1w] +# ) +# ) +# +# The result was exactly 131502080. Added a margin of 25% and rounded up to a +# multiple of 50 MiB which results in 200 MiB. +# +# - For the CPU request: +# +# max( +# quantile_over_time( +# 0.5, +# pod_name:container_cpu_usage:sum{ +# cluster="app-sre", +# namespace="uhc-production", +# pod_name=~"^clusters-service-.*$" +# } +# [1w] +# ) +# ) +# +# The result was exactly 0.03117216095926307. Added a margin of 25% and rounded +# up to a multiple of 0.05 cores, which results in 0.05 cores. +# +# - For the CPU limit: +# +# max( +# max_over_time( +# pod_name:container_cpu_usage:sum{ +# cluster="app-sre", +# namespace="uhc-production", +# pod_name=~"^clusters-service-.*$" +# } +# [1w] +# ) +# ) +# +# The result was exactly 0.2380057350296368. Added a margin of 25% and rounded +# up to a multiple of 0.05 cores, which results in 0.3 cores. + +# Memory request. +memoryRequest: "150Mi" + +# Memory limit. +memoryLimit: "1Gi" + +# CPU request. +cpuRequest: "50m" + +# CPU limit. +cpuLimit: "1" + +# Client ID for the clusters-service manage identity. +azureCsMiClientId: "" + +# Azure region the cluster-service instance is running in. +region: "westus3" + +# Base64 encoded service principal credentials for CS. This is temporary for P1. +csServicePrincipalCredsBase64: "" + +# The client id of the first party application identity. +azureFirstPartyApplicationClientId: "" + +# The name of the Key Vault containing keys, secrets and certificates used to support services running on the service cluster. +serviceKeyVaultName: "" + +# The Tenant ID of service cluster. +tenantId: "" + +# The name of the secret that contains the first party application certificate bundle. +fpaCertName: "" + +# If set to true the connection to the database is performed without TLS. +databaseDisableTLS: "false" + +# Authentication method to use when connecting to the database. Accepted values are 'az-entra', 'postgres' +databaseAuthMethod: "az-entra" + +# URL of the storage account blob service, e.g. https://.blob.core.windows.net/ +oidcIssuerBlobServiceUrl: "" + +# OIDC base issuer URL, e.g. https://.z1.web.core.windows.net/ +oidcIssuerBaseUrl: "" + +# The client id of the service principal that represents the ARM Helper Identity. +azureArmHelperIdentityClientId: "" + +# The name of the secret that contains the ARM Helper Indentity certificate bundle. +azureArmHelperIdentityCertName: "" + +# The principal id of the service principal that represents the mock first party application identity. +azureArmHelperMockFpaPrincipalId: "" + +# The name of the secret that contains the mock managed identities certificate bundle. +azureMiMockServicePrincipalCertName: "" + +# The client id of the mock managed identities service principal. +azureMiMockServicePrincipalClientId: "" + +# The principal id of the mock managed identities service principal. +azureMiMockServicePrincipalPrincipalId: "" + +# Details for a provisioning shard +shard: + consumerName: "" + zoneResourceId: "" + cxSecretsKeyVaultUrl: "" + cxMiKeyVaultUrl: "" + maestroRestUrl: "" + maestroGrpUrl: "" + +# ocm client id +clientId: "foo" + +# ocm secret +clientSecret: "bar" + +# If true an in cluster database will be deployed. +deployLocalDatabase: true + +# The name of the K8s secret where CS DB connection information is placed +databaseK8sSecretName: "ocm-cs-db" + +# The hostname of the postgres server/service. It can be a K8s service name +databaseHost: "ocm-cs-db" + +# Username for PostgreSQL user that will be used for accessing the database. +databaseUser: "ocm" + +# Password for the PostgreSQL connection user. +databasePassword: "TheBlurstOfTimes" + +# Name of the PostgreSQL database accessed. +databaseName: "ocm-cs-db" + +# Host port +databasePort: "5432" + +# The name of the managed identities data plane audience resource. +managedIdentitiesDataPlaneAudienceResource: "https://dummy.org" + +# The Azure Operator Managed Identities. +azureOperatorsMI: + clusterApiAzure: + roleName: '' + roleId: '' + controlPlane: + roleName: '' + roleId: '' + cloudControllerManager: + roleName: '' + roleId: '' + ingress: + roleName: '' + roleId: '' + diskCsiDriver: + roleName: '' + roleId: '' + fileCsiDriver: + roleName: '' + roleId: '' + imageRegistry: + roleName: '' + roleId: '' + cloudNetworkConfig: + roleName: '' + roleId: '' diff --git a/cluster-service/deploy/integration/cluster-service-namespace.yaml b/cluster-service/deploy/integration/cluster-service-namespace.yaml index fc17783e8..30aaac143 100644 --- a/cluster-service/deploy/integration/cluster-service-namespace.yaml +++ b/cluster-service/deploy/integration/cluster-service-namespace.yaml @@ -1,5 +1,5 @@ --- -apiVersion: v1 +apiVersion: template.openshift.io/v1 kind: Template metadata: name: cluster-service-admin diff --git a/cluster-service/deploy/openshift-templates/arohcp-db-template.yml b/cluster-service/deploy/openshift-templates/arohcp-db-template.yml deleted file mode 100644 index d8389f1c9..000000000 --- a/cluster-service/deploy/openshift-templates/arohcp-db-template.yml +++ /dev/null @@ -1,147 +0,0 @@ ---- -apiVersion: v1 -kind: Template -metadata: - annotations: - description: PostgreSQL database service for use with the OCM Account Magement Service - iconClass: icon-postgresql - openshift.io/display-name: Account Management PostgreSQL Database - tags: database,postgresql - name: ocm-cs-db -parameters: - - - name: DATABASE_SERVICE_NAME - description: The name of the OpenShift Service exposed for the database. - displayName: Database Service Name - required: true - value: ocm-cs-db - - - name: DATABASE_K8S_SECRET_NAME - description: The name of the K8s secret where CS DB connection information is placed - required: true - value: ocm-cs-db - - - name: DATABASE_VOLUME_CAPACITY - description: Volume space available for data, e.g. 512Mi, 2Gi. - displayName: Volume Capacity - required: true - value: 512Mi - - - name: POSTGRESQL_VERSION - description: Version of PostgreSQL image to be used (10 or latest). - displayName: Version of PostgreSQL Image - required: true - value: "12" - - - name: NAMESPACE - description: The OpenShift Namespace where the resources will be created. - displayName: Namespace - required: true - value: cluster-service - -objects: - - - apiVersion: v1 - kind: Service - metadata: - annotations: - template.openshift.io/expose-uri: postgres://{.spec.clusterIP}:{.spec.ports[?(.name==\postgresql\)].port} - name: ${DATABASE_SERVICE_NAME} - namespace: ${NAMESPACE} - spec: - ports: - - name: postgresql - nodePort: 0 - port: 5432 - protocol: TCP - targetPort: 5432 - selector: - name: ${DATABASE_SERVICE_NAME} - sessionAffinity: None - type: ClusterIP - status: - loadBalancer: {} - - - apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - name: ${DATABASE_SERVICE_NAME} - namespace: ${NAMESPACE} - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: ${DATABASE_VOLUME_CAPACITY} - - apiVersion: apps/v1 - kind: Deployment - metadata: - annotations: - template.alpha.openshift.io/wait-for-ready: true - name: ${DATABASE_SERVICE_NAME} - namespace: ${NAMESPACE} - spec: - replicas: 1 - selector: - matchLabels: - name: ${DATABASE_SERVICE_NAME} - strategy: - type: Recreate - template: - metadata: - labels: - name: ${DATABASE_SERVICE_NAME} - spec: - containers: - - capabilities: {} - env: - - name: POSTGRES_USER - valueFrom: - secretKeyRef: - key: db.user - name: ${DATABASE_K8S_SECRET_NAME} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - key: db.password - name: ${DATABASE_K8S_SECRET_NAME} - - name: POSTGRES_DB - valueFrom: - secretKeyRef: - key: db.name - name: ${DATABASE_K8S_SECRET_NAME} - - name: PGDATA - value: /var/lib/pgsql/data/pgdata - image: docker.io/library/postgres:16.2 - imagePullPolicy: IfNotPresent - livenessProbe: - tcpSocket: - port: 5432 - initialDelaySeconds: 120 - timeoutSeconds: 10 - name: postgresql - ports: - - containerPort: 5432 - protocol: TCP - readinessProbe: - exec: - command: - - /bin/sh - - -c - - exec /usr/bin/pg_isready -U $POSTGRES_USER -d $POSTGRES_DB -h localhost -p 5432 - initialDelaySeconds: 5 - timeoutSeconds: 1 - securityContext: - capabilities: {} - privileged: false - terminationMessagePath: /dev/termination-log - volumeMounts: - - mountPath: /var/lib/pgsql/data - name: ${DATABASE_SERVICE_NAME}-data - dnsPolicy: ClusterFirst - restartPolicy: Always - volumes: - - name: ${DATABASE_SERVICE_NAME}-data - persistentVolumeClaim: - claimName: ${DATABASE_SERVICE_NAME} - status: {} diff --git a/cluster-service/deploy/openshift-templates/arohcp-namespace-template.yml b/cluster-service/deploy/openshift-templates/arohcp-namespace-template.yml deleted file mode 100644 index d5f9150c6..000000000 --- a/cluster-service/deploy/openshift-templates/arohcp-namespace-template.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -apiVersion: v1 -kind: Template -metadata: - name: ocm-cs-ns -parameters: - - - name: NAMESPACE - description: The OpenShift Namespace where the resources will be created. - displayName: Namespace - required: true - value: cluster-service - - - name: ISTIO_VERSION - description: The version of Istio to use for this namespace - displayName: Istio Version - required: true - -objects: - - - apiVersion: v1 - kind: Namespace - metadata: - name: ${NAMESPACE} - labels: - istio.io/rev: ${ISTIO_VERSION} diff --git a/cluster-service/deploy/openshift-templates/arohcp-secrets-template.yml b/cluster-service/deploy/openshift-templates/arohcp-secrets-template.yml deleted file mode 100644 index 49bc7baaa..000000000 --- a/cluster-service/deploy/openshift-templates/arohcp-secrets-template.yml +++ /dev/null @@ -1,101 +0,0 @@ -# This file contains an OpenShift template that creates all the objects needed -# for a working development installation of the clusters service. - -# Staging and production don't use this template, don't forget to update -# mappings from Vault secrets to Secret objects in: -# https://gitlab.cee.redhat.com/service/app-interface/blob/master/resources/app-sre-stage/uhc-stage/clusters-service.secret.yaml -# https://gitlab.cee.redhat.com/service/app-interface/blob/master/resources/app-sre/uhc-production/clusters-service.secret.yaml - ---- - -apiVersion: v1 -kind: Template -metadata: - name: clusters-service-secrets - annotations: - description: "Clusters Service Secrets" -parameters: - - - name: PROVISION_SHARDS_CONFIG - description: Base64 encoded provision shards config. - default: "" - - - name: CLIENT_ID - description: ocm client id - value: foo - - - name: CLIENT_SECRET - description: ocm secret - value: bar - - - name: NAMESPACE - description: The OpenShift Namespace where the resources will be created. - displayName: Namespace - required: true - value: cluster-service - - - name: DATABASE_K8S_SECRET_NAME - description: The name of the K8s secret where CS DB connection information is placed - required: true - value: ocm-cs-db - - - name: DATABASE_HOST - description: The hostname of the postgres server/service. It can be a K8s service name - displayName: Database Service Name - required: true - value: ocm-cs-db - - - name: DATABASE_USER - description: Username for PostgreSQL user that will be used for accessing the database. - displayName: PostgreSQLUsername - required: true - value: ocm - - - name: DATABASE_PASSWORD - description: Password for the PostgreSQL connection user. - displayName: PostgreSQL Password - required: false - value: "TheBlurstOfTimes" - - - name: DATABASE_NAME - description: Name of the PostgreSQL database accessed. - displayName: PostgreSQL Database Name - required: true - value: ocm-cs-db - - - name: DATABASE_PORT - description: Host port - displayName: PostgreSQL Database Host Port - required: true - value: "5432" - -objects: - - - apiVersion: v1 - kind: Secret - metadata: - name: provision-shards - namespace: ${NAMESPACE} - data: - config: ${PROVISION_SHARDS_CONFIG} - - - apiVersion: v1 - kind: Secret - metadata: - name: clusters-service - namespace: ${NAMESPACE} - stringData: - client.id: ${CLIENT_ID} - client.secret: ${CLIENT_SECRET} - - - apiVersion: v1 - kind: Secret - metadata: - name: ${DATABASE_K8S_SECRET_NAME} - namespace: ${NAMESPACE} - stringData: - db.host: ${DATABASE_HOST} - db.name: ${DATABASE_NAME} - db.password: ${DATABASE_PASSWORD} - db.user: ${DATABASE_USER} - db.port: ${DATABASE_PORT} diff --git a/cluster-service/deploy/openshift-templates/arohcp-service-template.yml b/cluster-service/deploy/openshift-templates/arohcp-service-template.yml deleted file mode 100644 index 552d4f8c7..000000000 --- a/cluster-service/deploy/openshift-templates/arohcp-service-template.yml +++ /dev/null @@ -1,668 +0,0 @@ -# This file contains an OpenShift template that creates all the objects needed -# for a working installation of the clusters service. - ---- - -apiVersion: v1 -kind: Template -metadata: - name: clusters-service - annotations: - description: "Clusters Service" -parameters: - -- name: NAMESPACE - description: The OpenShift Namespace where the resources will be created. - displayName: Namespace - required: true - value: cluster-service - -# TODO: This parameter isn't currently used, but kept to avoid failures in the -# execution of saasherder. It will be removed once the version of the service -# that doesn't use it is deployed to all environments. -- name: DEBUG_PORT - value: "" - -- name: DEBUG_MAX_DURATION - description: Maximum allowed duration for /debug/pprof/ profiling requests, e.g. "30s" or "5m". "0" means no limit. - value: "5m" - -- name: RUNTIME_MODE - description: Sets the runtime configuration mode for CS. - value: "aro-hcp" - -- name: DEFAULT_EXPIRATION - description: Default expiration time assigned to any newly created cluster (e.g. 45m or 72h). 0 means no expiration. - value: "0" - -- name: MAXIMUM_EXPIRATION - description: Maximum expiration duration possible for any newly created cluster (e.g. 72h means the expiration date cannot be greater than 72h). 0 means no maximum expiration value possible. - value: "0" - -- name: FIRST_STALE_CLUSTER_NOTIFICATION - description: Duration since cluster creation after which the first notification for stale cluster should be sent. - value: "24h" # 1 day - -- name: SECOND_STALE_CLUSTER_NOTIFICATION - description: Duration since cluster creation after which the second notification for stale cluster should be sent. - value: "600h" # 25 days - -- name: STALE_CLUSTER_AUTOCLEANUP_WINDOW - description: Duration after which a stale cluster can be cleaned up. - value: "720h" # 30days - -- name: IMAGE_REGISTRY - description: Image registry. - -- name: IMAGE_REPOSITORY - description: Image repository. - -- name: IMAGE_TAG - description: Image tag. - -- name: LOG_LEVEL - description: Log verbosity level. - value: "debug" - -- name: REPLICAS - description: Number of replicas of the service to run. - value: "1" - -- name: JWKS_URL - description: Location of the JSON web key set used to verify tokens. - value: "http://localhost" - -- name: TOKEN_URL - description: Location of the service that issues JSON web tokens. - value: "http://localhost" - -- name: INSECURE - description: Disables TLS cert verification on authentication. - value: "false" - -- name: GATEWAY_URL - description: URL of the gateway. - value: "http://127.0.0.1:9090" - -- name: CLIENT_SCOPES - description: Level of access that an app can request to a resource. - value: "openid" - -- name: ENVIRONMENT - description: Environment associated with this instance. - value: "aro-hcp-dev" - -- name: BACKPLANE_URL - description: |- - The URL of the Backplane API which is exposed via an endpoint and is dynamically consumed by the Backplane CLI. - Backplane CLI expects a URL with the following format https://api..backplane. - The part is specific to each deployment environment. The part is optional. - # Note: this is defaulted to empty string and should be overriden in fedramp app-interface. - # This being an empty string, CS will send an empty string back via the /environment endpoint - # thus making the Backplane CLI failover to check if the backplane user has an environment variable BACKPLANE_URL set and use it instead. - value: "" - -- name: PROVISION_SHARD_CLUSTER_LIMIT - description: Provision shard limit of managed clusters. - value: "500" - -- name: FORCE_MIGRATION - description: If not empty clears the dirty flag and forces the given migration version. - value: "" - -- name: CLUSTER_ERROR_REPORT - description: If set to true, a cluster error will trigger a report. - value: "false" - -- name: MACHINE_POOL_MIGRATION_WORKER_PERIOD - description: Period between executions of day-1 machine pool migration worker. Useful time units are "m" or "h". - value: 1h - -- name: USER_DEFINED_DNS_BASE_DOMAIN - description: The name of the DNS base domain for creating a user defined domains. - value: "i1.devshift.org" # Note: this is defaulted to a commercial value. This should be overriden in fedramp app-interface - -- name: BATCH_PROCESSES_DRY_RUN - description: Signals batch processes step to run in dry run. - value: "true" - -- name: BATCH_PROCESSES - description: Date identification of each batch process expected to be run. Comma separated sequence. - value: "" - -- name: OCP_ACR_URL - description: The URL of the Azure Container Registry where the OpenShift images are stored. - required: true - -- name: OCP_ACR_RESOURCE_ID - description: The resource ID of the Azure Container Registry where the OpenShift images are stored. - required: true - - -# These limits are based on the metrics collected in the production environment -# over the last year. In particular the following Prometheus queries were used -# to obtain the values: -# -# - For the memory request: -# -# max( -# quantile_over_time( -# 0.5, -# container_memory_usage_bytes{ -# cluster="app-sre", -# namespace="uhc-production", -# pod_name=~"^clusters-service-.*$", -# container_name="service" -# } -# [1w] -# ) -# ) -# -# The result was exactly 88322048. Added a margin of 25% and rounded up to a -# multiple of 50 MiB which results in 150 MiB. -# -# - For the memory limit: -# -# max( -# max_over_time( -# container_memory_usage_bytes{ -# cluster="app-sre", -# namespace="uhc-production", -# pod_name=~"^clusters-service-.*$", -# container_name="service" -# } -# [1w] -# ) -# ) -# -# The result was exactly 131502080. Added a margin of 25% and rounded up to a -# multiple of 50 MiB which results in 200 MiB. -# -# - For the CPU request: -# -# max( -# quantile_over_time( -# 0.5, -# pod_name:container_cpu_usage:sum{ -# cluster="app-sre", -# namespace="uhc-production", -# pod_name=~"^clusters-service-.*$" -# } -# [1w] -# ) -# ) -# -# The result was exactly 0.03117216095926307. Added a margin of 25% and rounded -# up to a multiple of 0.05 cores, which results in 0.05 cores. -# -# - For the CPU limit: -# -# max( -# max_over_time( -# pod_name:container_cpu_usage:sum{ -# cluster="app-sre", -# namespace="uhc-production", -# pod_name=~"^clusters-service-.*$" -# } -# [1w] -# ) -# ) -# -# The result was exactly 0.2380057350296368. Added a margin of 25% and rounded -# up to a multiple of 0.05 cores, which results in 0.3 cores. -- name: MEMORY_REQUEST - description: Memory request. - value: "150Mi" -- name: MEMORY_LIMIT - description: Memory limit. - value: "1Gi" -- name: CPU_REQUEST - description: CPU request. - value: "50m" -- name: CPU_LIMIT - description: CPU limit. - value: "1" -- name: AZURE_CS_MI_CLIENT_ID - description: Client ID for the clusters-service manage identity. - required: true -- name: REGION - value: "westus3" -- name: CS_SERVICE_PRINCIPAL_CREDS_BASE64 - description: Base64 encoded service principal credentials for CS. This is temporary for P1. - required: true -- name: AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID - description: The client id of the first party application identity. - value: "" -- name: SERVICE_KEYVAULT_NAME - description: The name of the Key Vault containing keys, secrets and certificates used to support services running on the service cluster. - value: "" -- name: TENANT_ID - description: The Tenant ID of service cluster. - value: "" -- name: FPA_CERT_NAME - description: The name of the secret that contains the first party application certificate bundle. -- name: DATABASE_DISABLE_TLS - description: "If set to true the connection to the database is performed without TLS" - value: "false" -- name: DATABASE_AUTH_METHOD - description: "Authentication method to use when connecting to the database. Accepted values are 'az-entra', 'postgres'" - value: "az-entra" - -objects: - -- apiVersion: secrets-store.csi.x-k8s.io/v1 - kind: SecretProviderClass - metadata: - name: cs-keyvault - namespace: ${NAMESPACE} - spec: - parameters: - clientID: ${AZURE_CS_MI_CLIENT_ID} - cloudName: AzurePublicCloud - keyvaultName: ${SERVICE_KEYVAULT_NAME} - objects: |- - array: - - | - objectName: ${FPA_CERT_NAME} - objectType: secret - objectAlias: firstPartyApplicationCertificateBundle - tenantId: ${TENANT_ID} - usePodIdentity: "false" - provider: azure - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: cloud-resources-config - namespace: ${NAMESPACE} - data: - instance-types.yaml: | - instance_types: - - id: Standard_D8s_v3 - name: Standard_D8s_v3 - General purpose - cloud_provider_id: azure - cpu_cores: 8 - memory: 34359738368 - category: general_purpose - size: d8s_v3 - generic_name: standard-d8s_v3 - cloud-regions.yaml: | - cloud_regions: - - id: ${REGION} - cloud_provider_id: azure - display_name: Azure East US - supports_multi_az: true - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: cloud-resource-constraints-config - namespace: ${NAMESPACE} - data: - instance-type-constraints.yaml: | - instance_types: - - id: Standard_D8s_v3 - ccs_only: true - enabled: true - cloud-region-constraints.yaml: | - cloud_regions: - - id: ${REGION} - enabled: true - govcloud: false - ccs_only: false - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: cluster-proxy-service-config - namespace: ${NAMESPACE} - data: - config.yaml: | - # Hosts that should be added to noProxy for all clusters - noProxy: [] - # Hosts that should be added to noProxy for AWS clusters - noProxy_aws: [] - # Hosts that should be added to noProxy for GCP clusters - noProxy_gcp: [] - # Readiness endpoints that verify proxy connectivity - readinessEndpoints: - - "https://api.openshift.com" - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: authentication - namespace: ${NAMESPACE} - data: - jwks.json: "" - acl.yml: "" - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: region-constraints-config - namespace: ${NAMESPACE} - data: - config.yaml: | - cloud_providers: - - name: azure - regions: - - name: ${REGION} - version_constraints: - min_version: 4.11.0 - -- apiVersion: v1 - kind: ConfigMap - metadata: - name: azure-runtime-config - namespace: ${NAMESPACE} - data: - config.json: | - { - "cloudEnvironment": "AzurePublicCloud", - "tenantId": "${TENANT_ID}", - "ocpImagesAcr": { - "resourceId": "${OCP_ACR_RESOURCE_ID}", - "url": "${OCP_ACR_URL}", - "scopeMapName": "_repositories_pull" - } - } - -- apiVersion: v1 - kind: ServiceAccount - metadata: - name: clusters-service - namespace: ${NAMESPACE} - labels: - app: clusters-service - annotations: - azure.workload.identity/client-id: ${AZURE_CS_MI_CLIENT_ID} - -- apiVersion: v1 - kind: Secret - metadata: - name: azure-credentials - namespace: ${NAMESPACE} - type: Opaque - data: - azure-auth-config: "${CS_SERVICE_PRINCIPAL_CREDS_BASE64}" - -- apiVersion: apps/v1 - kind: Deployment - metadata: - name: clusters-service - namespace: ${NAMESPACE} - labels: - app: clusters-service - spec: - selector: - matchLabels: - app: clusters-service - replicas: ${{REPLICAS}} - template: - metadata: - labels: - app: clusters-service - azure.workload.identity/use: "true" - spec: - serviceAccount: clusters-service - serviceAccountName: clusters-service - volumes: - - name: service - secret: - secretName: clusters-service - - name: shards - secret: - secretName: provision-shards - - name: rds - secret: - secretName: ocm-cs-db - - name: oidc - secret: - secretName: rh-oidc-s3-secret - - name: authentication - configMap: - name: authentication - - name: region-constraints - configMap: - name: region-constraints-config - - name: instance-types - configMap: - name: cloud-resources-config - - name: instance-type-constraints - configMap: - name: cloud-resource-constraints-config - - name: cloud-regions - configMap: - name: cloud-resources-config - - name: cloud-region-constraints - configMap: - name: cloud-resource-constraints-config - - name: proxy - configMap: - name: cluster-proxy-service-config - - name: azure-runtime-config - configMap: - name: azure-runtime-config - - name: mixin-pull-secret - secret: - secretName: hive-ci-global-pull-secret - optional: true - - name: azure-credentials - secret: - secretName: azure-credentials - - name: keyvault - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: cs-keyvault - initContainers: - - name: init - image: ${IMAGE_REGISTRY}/${IMAGE_REPOSITORY}:${IMAGE_TAG} - imagePullPolicy: IfNotPresent - volumeMounts: - - name: rds - mountPath: /secrets/rds - - name: service - mountPath: /secrets/service - command: - - /usr/local/bin/clusters-service - - init - - --db-host=@/secrets/rds/db.host - - --db-port=@/secrets/rds/db.port - - --db-name=@/secrets/rds/db.name - - --db-user=@/secrets/rds/db.user - - --db-password=@/secrets/rds/db.password - - --db-disable-tls=${DATABASE_DISABLE_TLS} - - --db-auth-method=${DATABASE_AUTH_METHOD} - - --force-migration=${FORCE_MIGRATION} - - --batch-processes-dry-run=${BATCH_PROCESSES_DRY_RUN} - - --batch-processes=${BATCH_PROCESSES} - containers: - - name: service - image: ${IMAGE_REGISTRY}/${IMAGE_REPOSITORY}:${IMAGE_TAG} - imagePullPolicy: IfNotPresent - volumeMounts: - - name: service - mountPath: /secrets/service - - name: shards - mountPath: /secrets/shards - - name: rds - mountPath: /secrets/rds - - name: authentication - mountPath: /configs/authentication - - name: region-constraints - mountPath: /configs/region-constraints - - name: proxy - mountPath: /configs/proxy - - name: mixin-pull-secret - mountPath: /secrets/mixin-pull-secret - - name: instance-types - mountPath: /configs/cloud-resources/instance-types.yaml - subPath: instance-types.yaml - - name: instance-type-constraints - mountPath: /configs/cloud-resource-constraints/instance-type-constraints.yaml - subPath: instance-type-constraints.yaml - - name: cloud-regions - mountPath: /configs/cloud-resources/cloud-regions.yaml - subPath: cloud-regions.yaml - - name: cloud-region-constraints - mountPath: /configs/cloud-resource-constraints/cloud-region-constraints.yaml - subPath: cloud-region-constraints.yaml - - name: azure-credentials - mountPath: /secrets/azure-credentials - - name: keyvault - mountPath: "/secrets/keyvault" - readOnly: true - - name: azure-runtime-config - mountPath: /configs/azure-runtime-config - env: - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - command: - - /usr/local/bin/clusters-service - - serve - - --log-level=${LOG_LEVEL} - - --namespace=$(NAMESPACE) - - --runtime-mode=${RUNTIME_MODE} - - --default-expiration=${DEFAULT_EXPIRATION} - - --maximum-expiration=${MAXIMUM_EXPIRATION} - - --db-host=@/secrets/rds/db.host - - --db-port=@/secrets/rds/db.port - - --db-name=@/secrets/rds/db.name - - --db-user=@/secrets/rds/db.user - - --db-password=@/secrets/rds/db.password - - --db-disable-tls=${DATABASE_DISABLE_TLS} - - --db-auth-method=${DATABASE_AUTH_METHOD} - - --gateway-url=${GATEWAY_URL} - - --client-id=@/secrets/service/client.id - - --client-secret=@/secrets/service/client.secret - - --client-scopes=${CLIENT_SCOPES} - - --user-defined-dns-base-domain=${USER_DEFINED_DNS_BASE_DOMAIN} - - --jwks-url=${JWKS_URL} - - --jwks-file=/configs/authentication/jwks.json - - --acl-file=/configs/authentication/acl.yml - - --token-url=${TOKEN_URL} - - --insecure=${INSECURE} - - --api-listener-network=tcp - - --api-listener-address=:8000 - - --metrics-listener-network=tcp - - --metrics-listener-address=:8080 - - --healthcheck-listener-network=tcp - - --healthcheck-listener-address=:8083 - - --environment=${ENVIRONMENT} - - --backplane-url=${BACKPLANE_URL} - - --provision-shards-config=/secrets/shards/config - - --proxy-config-file=/configs/proxy/config.yaml - - --aws-sts-policy-directory=/configs/policies - - --mixin-pull-secret-path=/secrets/mixin-pull-secret - - --region-constraints-config=/configs/region-constraints/config.yaml - - --instance-type-config=/configs/cloud-resources/instance-types.yaml - - --instance-type-constraints-config=/configs/cloud-resource-constraints/instance-type-constraints.yaml - - --cloud-region-config=/configs/cloud-resources/cloud-regions.yaml - - --cloud-region-constraints-config=/configs/cloud-resource-constraints/cloud-region-constraints.yaml - - --azure-auth-config-path=/secrets/azure-credentials/azure-auth-config - - --azure-first-party-application-client-id=${AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID} - - --azure-first-party-application-certificate-bundle-path=/secrets/keyvault/firstPartyApplicationCertificateBundle - - --azure-runtime-config-path=/configs/azure-runtime-config/config.json - livenessProbe: - httpGet: - path: /api/clusters_mgmt/v1 - port: 8000 - scheme: HTTP - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /healthcheck - port: 8083 - scheme: HTTP - httpHeaders: - - name: User-Agent - value: Probe - initialDelaySeconds: 20 - periodSeconds: 10 - resources: - requests: - memory: ${MEMORY_REQUEST} - cpu: ${CPU_REQUEST} - limits: - memory: ${MEMORY_LIMIT} - cpu: ${CPU_LIMIT} - -- apiVersion: v1 - kind: Service - metadata: - name: clusters-service - namespace: ${NAMESPACE} - labels: - app: clusters-service - port: api - spec: - selector: - app: clusters-service - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - -# Services for diagnostic ports (not part of main service because we -# don't want exposing them externally through same route). - -- apiVersion: v1 - kind: Service - metadata: - name: clusters-service-metrics - namespace: ${NAMESPACE} - labels: - # {app, port} labels together identify this service for monitoring - app: clusters-service - port: metrics - spec: - selector: - app: clusters-service - ports: - - port: 8080 - targetPort: 8080 - name: metrics - protocol: TCP - -- apiVersion: v1 - kind: Service - metadata: - name: clusters-service-healthcheck - namespace: ${NAMESPACE} - labels: - app: clusters-service - port: healthcheck - spec: - selector: - app: clusters-service - ports: - - port: 8083 - targetPort: 8083 - name: healthcheck - protocol: TCP - -- apiVersion: azmonitoring.coreos.com/v1 - kind: ServiceMonitor - metadata: - name: clusters-service-service-monitor - namespace: ${NAMESPACE} - spec: - endpoints: - - interval: 30s - path: /metrics - port: metrics - scheme: http - namespaceSelector: - matchNames: - - cluster-service - selector: - matchLabels: - app: clusters-service - port: metrics diff --git a/cluster-service/deploy/provisioning-shards.tmpl.yml b/cluster-service/deploy/provisioning-shards.tmpl.yml index 95fd14e27..63a737a34 100644 --- a/cluster-service/deploy/provisioning-shards.tmpl.yml +++ b/cluster-service/deploy/provisioning-shards.tmpl.yml @@ -3,16 +3,19 @@ provision_shards: maestro_config: | { "rest_api_config": { - "url": "http://maestro.maestro.svc.cluster.local:8000" + "url": "{{ .extraVars.maestroRestUrl }}" }, "grpc_api_config": { - "url": "maestro-grpc.maestro.svc.cluster.local:8090" + "url": "{{ .extraVars.maestroGrpUrl }}" }, - "consumer_name": "{{ .maestroConsumerName }}" + "consumer_name": "{{ .maestro.consumerName }}" } status: active - azure_base_domain: "{{ .extraVars.zoneResourceId }}" management_cluster_id: local-cluster region: {{ .region }} cloud_provider: azure topology: dedicated + azure_shard: + public_dns_zone_resource_id: "{{ .extraVars.zoneResourceId }}" + cx_secrets_key_vault_url: "{{ .extraVars.cxSecretsKeyVaultUrl }}" + cx_managed_identities_key_vault_url: "{{ .extraVars.cxMiKeyVaultUrl }}" diff --git a/cluster-service/pipeline.yaml b/cluster-service/pipeline.yaml new file mode 100644 index 000000000..5f58e85b3 --- /dev/null +++ b/cluster-service/pipeline.yaml @@ -0,0 +1,98 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.ClusterService +rolloutName: Cluster Service Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: REGION + configRef: region + - name: RESOURCEGROUP + configRef: svc.rg + - name: AKS_NAME + configRef: aksName + - name: SERVICE_KV + configRef: serviceKeyVault.name + - name: OIDC_STORAGE_ACCOUNT + configRef: oidcStorageAccountName + - name: IMAGE_REPO + configRef: clusterService.imageRepo + - name: IMAGE_TAG + configRef: clusterService.imageTag + - name: ACR_NAME + configRef: svcAcrName + - name: OCP_ACR_NAME + configRef: ocpAcrName + - name: AZURE_FIRST_PARTY_APPLICATION_CLIENT_ID + configRef: firstPartyAppClientId + - name: FPA_CERT_NAME + value: firstPartyCert + - name: AZURE_MI_MOCK_SERVICE_PRINCIPAL_PRINCIPAL_ID + configRef: miMockPrincipalId + - name: AZURE_MI_MOCK_SERVICE_PRINCIPAL_CLIENT_ID + configRef: miMockClientId + - name: AZURE_ARM_HELPER_IDENTITY_CLIENT_ID + configRef: armHelperClientId + - name: AZURE_ARM_HELPER_MOCK_FPA_PRINCIPAL_ID + configRef: armHelperFPAPrincipalId + - name: MI_MOCK_SERVICE_PRINCIPAL_CERT_NAME + value: msiMockCert + - name: ARM_HELPER_CERT_NAME + value: armHelperCert + - name: CX_PARENT_DNS_ZONE_NAME + configRef: dns.cxParentZoneName + - name: REGIONAL_DNS_SUBDOMAIN + configRef: dns.regionalSubdomain + - name: USE_AZURE_DB + configRef: clusterService.postgres.deploy + - name: DATABASE_SERVER_NAME + configRef: clusterService.postgres.name + - name: DEVOPS_MSI_ID + configRef: aroDevopsMsiId + - name: OP_CLUSTER_API_AZURE_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.clusterApiAzure.roleName + - name: OP_CONTROL_PLANE_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.controlPlane.roleName + - name: OP_CLOUD_CONTROLLER_MANAGER_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.cloudControllerManager.roleName + - name: OP_INGRESS_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.ingress.roleName + - name: OP_DISK_CSI_DRIVER_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.diskCsiDriver.roleName + - name: OP_FILE_CSI_DRIVER_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.fileCsiDriver.roleName + - name: OP_IMAGE_REGISTRY_DRIVER_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.imageRegistry.roleName + - name: OP_CLOUD_NETWORK_CONFIG_ROLE_NAME + configRef: clusterService.azureOperatorsManagedIdentities.cloudNetworkConfig.roleName + - name: ISTO_TAG + configRef: svc.istio.tag + - name: MI_NAME + configRef: clusterService.managedIdentityName + - name: NAMESPACE + configRef: clusterService.k8s.namespace + - name: SERVICE_ACCOUNT_NAME + configRef: clusterService.k8s.serviceAccountName + + + # this is maestro consumer registration stuff + # this goes away when we have a real registration process + - name: CONSUMER_NAME + configRef: maestro.consumerName + - name: REGIONAL_RESOURCEGROUP + configRef: regionRG + - name: MGMT_RESOURCEGROUP + configRef: mgmt.rg + - name: CX_SECRETS_KV_NAME + configRef: cxKeyVault.name + - name: CX_MI_KV_NAME + configRef: msiKeyVault.name diff --git a/config/Makefile b/config/Makefile index 84ece6e8e..deb33c1fb 100644 --- a/config/Makefile +++ b/config/Makefile @@ -1,7 +1,12 @@ materialize: + @echo "Materializing public cloud int env of config/config.yaml" @../templatize.sh dev > public-cloud-dev.json + @echo "Materializing public cloud cs-pr env of config/config.yaml" @../templatize.sh cs-pr > public-cloud-cs-pr.json + @echo "Materializing public cloud personal dev env of config/config.yaml" @USER=tst ../templatize.sh personal-dev > public-cloud-personal-dev.json + @echo "Materializing public cloud int env of config/config.msft.yaml" + @CONFIG_FILE=../config/config.msft.yaml ../templatize.sh int > public-cloud-msft-int.json .PHONY: materialize detect-change: materialize @@ -10,7 +15,7 @@ detect-change: materialize echo "Please review the diffs below:\n\n"; \ echo "$$diff_output"; \ echo "\n\n===================================================="; \ - echo "\n\nOnce you reviewed the changes and consider them meaningful, commit them."; \ + echo "\n\nOnce you reviewed the changes and consider them meaningful, update them by running "make -C config/ materialize" and commit your changes."; \ echo "\n\n===================================================="; \ exit 1; \ else \ diff --git a/config/config.msft.yaml b/config/config.msft.yaml new file mode 100644 index 000000000..315f38b73 --- /dev/null +++ b/config/config.msft.yaml @@ -0,0 +1,291 @@ +$schema: config.schema.json +defaults: + region: {{ .ctx.region }} + + # Resourcegroups + regionRG: '{{ .ctx.region }}-shared-resources' + + global: + rg: global-shared-resources + subscription: hcp-{{ .ctx.region }} + region: uksouth + globalMSIName: "global-ev2-identity" + + # General AKS config + aksName: aro-hcp-aks + + # ACR Pull + acrPullImageDigest: sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca #v0.1.7 + + # Hypershift + hypershift: + namespace: hypershift + additionalInstallArg: '--tech-preview-no-upgrade' + + svc: + subscription: hcp-{{ .ctx.region }} + rg: hcp-underlay-{{ .ctx.region }}-svc + aks: + vnetAddressPrefix: "10.128.0.0/14" + subnetPrefix: "10.128.8.0/21" + podSubnetPrefix: "10.128.64.0/18" + kubernetesVersion: 1.31.2 + etcd: + kvName: arohcp-etcd-{{ .ctx.regionShort }} + kvSoftDelete: true + clusterOutboundIPAddressIPTags: "FirstPartyUsage:arohcpprodoutboundsvc" + istio: + istioctlVersion: "1.24.1" + tag: "prod-stable" + targetVersion: "asm-1-23" + versions: "asm-1-23" + ingressGatewayIPAddressName: "aro-hcp-istio-ingress" + ingressGatewayIPAddressIPTags: "FirstPartyUsage:arohcpprodinboundsvc" + + # MGMT cluster specifics + mgmt: + clusterServiceResourceId: 'todo' + subscription: hcp-{{ .ctx.region }} + rg: hcp-underlay-{{ .ctx.region }}-mgmt-{{ .ctx.stamp }} + aks: + vnetAddressPrefix: "10.128.0.0/14" + subnetPrefix: "10.128.8.0/21" + podSubnetPrefix: "10.128.64.0/18" + kubernetesVersion: 1.31.2 + etcd: + kvName: arohcp-etcd-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + kvSoftDelete: true + clusterOutboundIPAddressIPTags: "FirstPartyUsage:arohcpprodoutboundcx" + + # Frontend + frontend: + cosmosDB: + deploy: true + disableLocalAuth: true + name: arohcp-rp-{{ .ctx.regionShort }} + private: true + + # Maestro + maestro: + server: + mqttClientName: maestro-server + managedIdentityName: maestro-server + k8s: + namespace: maestro + serviceAccountName: maestro + eventGrid: + name: arohcp-maestro-{{ .ctx.regionShort }} + maxClientSessionsPerAuthName: 4 + private: false + certDomain: 'selfsigned.maestro.keyvault.azure.com' + postgres: + name: arohcp-maestro-{{ .ctx.regionShort }} + serverVersion: '15' + serverStorageSizeGB: 32 + deploy: true + private: false + minTLSVersion: 'TLSV1.2' + databaseName: maestro + restrictIstioIngress: true + consumerName: hcp-underlay-{{ .ctx.regionShort }}-mgmt-{{ .ctx.stamp }} + imageBase: quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro + + # Cluster Service + clusterService: + acrRG: 'global-shared-resources' + postgres: + name: arohcp-cs-{{ .ctx.regionShort }} + deploy: true + private: false + minTLSVersion: 'TLSV1.2' + managedIdentityName: clusters-service + k8s: + namespace: cluster-service + serviceAccountName: clusters-service + + # Image Sync + imageSync: + rg: global-shared-resources + acrRG: global-shared-resources + environmentName: global-shared-resources + componentSync: + enabled: true + imageRepo: image-sync/component-sync + repositories: arohcpsvcdev.azurecr.io/image-sync/component-sync,arohcpsvcdev.azurecr.io/arohcpfrontend,arohcpsvcdev.azurecr.io/arohcpbackend,quay.io/acm-d/rhtap-hypershift-operator,arohcpsvcdev.azurecr.io/image-sync/oc-mirror,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package + secrets: 'quay.io:quay-io-bearer,arohcpsvcdev.azurecr.io:arohcpsvcdev-bearer' + pullSecretName: component-sync-pull-secret + ocMirror: + enabled: true + imageRepo: image-sync/oc-mirror + pullSecretName: ocp-pull-secret + keyVault: + name: arohcp-imagesync-int + private: false + softDelete: true + + # MCE + mce: + clcStateMetrics: + imageDigest: bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7 + + serviceKeyVault: + name: arohcp-svc-{{ .ctx.regionShort }} + rg: hcp-underlay-{{ .ctx.region }}-svc + region: {{ .ctx.region }} + softDelete: false + private: false + + # Management Cluster KV + cxKeyVault: + name: arohcp-cx-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: false + private: false + msiKeyVault: + name: arohcp-msi-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: false + private: false + mgmtKeyVault: + name: arohcp-mgmt-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: false + private: false + + # DNS + dns: + baseDnsZoneRG: global-shared-resources + regionalSubdomain: '{{ .ctx.region }}' + + # Metrics + monitoring: + workspaceName: 'arohcp-{{ .ctx.regionShort }}' + msiName: 'aro-hcp-metrics-msi-{{ .ctx.regionShort }}' + +clouds: + public: + # this configuration serves as a template for for all RH DEV subscription deployments + # the following vars need approprivate overrides: + defaults: + maestro: + imageTag: c9a36e110a32c0c25aa5025cfe6d51af797e6d4b + clusterService: + imageTag: dca2a71 + imageRepo: app-sre/uhc-clusters-service + azureOperatorsManagedIdentities: + clusterApiAzure: + roleName: Contributor + controlPlane: + roleName: Contributor + cloudControllerManager: + roleName: Azure Red Hat OpenShift Cloud Controller Manager Role + ingress: + roleName: Azure Red Hat OpenShift Cluster Ingress Operator Role + diskCsiDriver: + roleName: Azure Red Hat OpenShift Storage Operator Role + fileCsiDriver: + roleName: Azure Red Hat OpenShift Azure Files Storage Operator Role + imageRegistry: + roleName: Azure Red Hat OpenShift Image Registry Operator Role + cloudNetworkConfig: + roleName: Azure Red Hat OpenShift Network Operator Role + hypershiftOperator: + imageTag: 9aca808 + imageSync: + componentSync: + imageTag: 0b076bf + ocMirror: + imageTag: 0b076bf + frontend: + imageTag: 0b076bf + backend: + imageTag: 0b076bf + + environments: + int: + # this is the MSFT INT environment + defaults: + # OIDC + oidcStorageAccountName: arohcpoidcint{{ .ctx.regionShort }} + # SVC + svc: + aks: + systemAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 32 + userAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 32 + azCount: 3 + clusterOutboundIPAddressIPTags: "FirstPartyUsage:/NonProd" + istio: + ingressGatewayIPAddressIPTags: "FirstPartyUsage:/NonProd" + # MC + mgmt: + aks: + # MGMTM AKS nodepools - big enough for 2 HCPs + systemAgentPool: + minCount: 1 + maxCount: 4 + vmSize: 'Standard_E8s_v3' + osDiskSizeGB: 128 + userAgentPool: + minCount: 1 + maxCount: 12 + vmSize: 'Standard_D16s_v3' + osDiskSizeGB: 128 + azCount: 3 + clusterOutboundIPAddressIPTags: "FirstPartyUsage:/NonProd" + # DNS + dns: + cxParentZoneName: aroapp-hcp.azure-test.net + svcParentZoneName: aro-hcp.azure-test.net + parentZoneName: azure-test.net + + # ACR + svcAcrName: arohcpsvcint + ocpAcrName: arohcpocpint + + # Frontend + frontend: + cosmosDB: + private: false + cert: + name: frontend-cert-{{ .ctx.regionShort }} + issuer: OneCertV2-PublicCA + + # 1P app + firstPartyAppClientId: 5bc505bc-50ef-4be9-9a82-2ed7973f1c37 + + # Mock Managed Identities Service Princiapl. + # This is a stub identity to be used by CS in environments where the MI (formerly MSI) RP isn't available. + miMockClientId: f13a22ee-4f55-4d33-a614-a703e5501202 + miMockPrincipalId: d9356bcd-fb81-483e-9b5f-180c0aa27a16 + + # ARM Helper + # This is a helper identity for DEV not required in higher envs. + armHelperClientId: f2af6a70-fc23-4a9a-bbf2-3236f86e65e4 + armHelperFPAPrincipalId: 4026d9e7-2897-4f0c-83d4-897858a5f8a8 + + # disable KV softdelete for easy cleanup and recreate in INT + cxKeyVault: + softDelete: false + private: false + msiKeyVault: + softDelete: false + private: false + mgmtKeyVault: + softDelete: false + private: false + + # Grafana + monitoring: + grafanaName: 'arohcp-int' + grafanaAdminGroupPrincipalId: '2fdb57d4-3fd3-415d-b604-1d0e37a188fe' # Azure Red Hat OpenShift MSFT Engineering + + # Global MSI + # Will move this MSI creationg to this repo. Currently it's in the hcp repo + aroDevopsMsiId: '/subscriptions/5299e6b7-b23b-46c8-8277-dc1147807117/resourcegroups/global-shared-resources/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-ev2-identity' + # Cert Officer used for KV signer registration + kvCertOfficerPrincipalId: '32af88de-a61c-4f71-b709-50538598c4f2' # aro-ev2-admin-int-sp diff --git a/config/config.schema.json b/config/config.schema.json new file mode 100644 index 000000000..d816f9734 --- /dev/null +++ b/config/config.schema.json @@ -0,0 +1,888 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Generated schema for Root", + "type": "object", + "definitions": { + "operatorConfig": { + "type": "object", + "properties": { + "roleName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "roleName" + ] + }, + "aksAgentPool": { + "type": "object", + "properties": { + "maxCount": { + "type": "number" + }, + "minCount": { + "type": "number" + }, + "osDiskSizeGB": { + "type": "number" + }, + "vmSize": { + "type": "string" + }, + "azCount": { + "type": "number" + } + }, + "additionalProperties": false, + "required": [ + "maxCount", + "minCount", + "osDiskSizeGB", + "vmSize" + ] + }, + "aksConfig": { + "type": "object", + "properties": { + "vnetAddressPrefix": { + "type": "string" + }, + "subnetPrefix": { + "type": "string" + }, + "podSubnetPrefix": { + "type": "string" + }, + "kubernetesVersion": { + "type": "string" + }, + "etcd": { + "type": "object", + "properties": { + "kvName": { + "type": "string" + }, + "kvSoftDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "kvName", + "kvSoftDelete" + ] + }, + "userAgentPool": { + "$ref": "#/definitions/aksAgentPool" + }, + "systemAgentPool": { + "$ref": "#/definitions/aksAgentPool" + }, + "clusterOutboundIPAddressIPTags": { + "$ref": "#/definitions/keyColonValueCSV" + } + }, + "required": [ + "vnetAddressPrefix", + "subnetPrefix", + "podSubnetPrefix", + "kubernetesVersion", + "etcd", + "userAgentPool", + "systemAgentPool" + ] + }, + "keyColonValueCSV": { + "type": "string", + "pattern": "^$|^[\\w-\\.]+:[\\w\\/-]+(,[\\w-\\.]+:[\\w\\/-]+)*$" + } + }, + "properties": { + "aksName": { + "type": "string" + }, + "aroDevopsMsiId": { + "type": "string" + }, + "kvCertOfficerPrincipalId": { + "type": "string", + "description": "The principal ID of the cert officer that will be used to manage KV certificate issuers" + }, + "dns": { + "type": "object", + "properties": { + "baseDnsZoneRG": { + "type": "string", + "description": "The Azure RG that holds the parent DNS zones" + }, + "cxParentZoneName": { + "type": "string", + "description": "The parent DNS zone name for regional HCP cluster DNS zones" + }, + "svcParentZoneName": { + "type": "string", + "description": "The parent DNS zone name for regional ARO-HCP infrastructure, e.g. the RP" + }, + "regionalSubdomain": { + "type": "string", + "description": "The regional subdomain to be used to construct the regional hcp and svc zones under their respective parents, e.g. regionalSubdomain.svcParentZoneName" + }, + "parentZoneName": { + "type": "string", + "description": "The global parent DNS zone name" + } + }, + "additionalProperties": false, + "required": [ + "baseDnsZoneRG", + "cxParentZoneName", + "svcParentZoneName", + "regionalSubdomain" + ] + }, + "pko": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "imageManager": { + "type": "string" + }, + "imageTag": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "image", + "imageManager", + "imageTag" + ] + }, + "clusterService": { + "type": "object", + "properties": { + "acrRG": { + "type": "string" + }, + "imageRepo": { + "type": "string" + }, + "imageTag": { + "type": "string" + }, + "managedIdentityName": { + "type": "string", + "description": "The name of the MSI that will be used by CS to interact with Azure" + }, + "k8s": { + "type": "object", + "properties": { + "namespace": { + "type": "string" + }, + "serviceAccountName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "namespace", + "serviceAccountName" + ] + }, + "postgres": { + "type": "object", + "properties": { + "deploy": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "minTLSVersion": { + "type": "string", + "enum": ["TLSV1.2", "TLSV1.3"] + } + }, + "required": [ + "deploy", + "name", + "private", + "minTLSVersion" + ] + }, + "azureOperatorsManagedIdentities": { + "type": "object", + "properties": { + "clusterApiAzure": { + "$ref": "#/definitions/operatorConfig" + }, + "controlPlane": { + "$ref": "#/definitions/operatorConfig" + }, + "cloudControllerManager": { + "$ref": "#/definitions/operatorConfig" + }, + "ingress": { + "$ref": "#/definitions/operatorConfig" + }, + "diskCsiDriver": { + "$ref": "#/definitions/operatorConfig" + }, + "fileCsiDriver": { + "$ref": "#/definitions/operatorConfig" + }, + "imageRegistry": { + "$ref": "#/definitions/operatorConfig" + }, + "cloudNetworkConfig": { + "$ref": "#/definitions/operatorConfig" + } + }, + "additionalProperties": false, + "required": [ + "cloudControllerManager", + "ingress", + "diskCsiDriver", + "fileCsiDriver", + "imageRegistry", + "cloudNetworkConfig" + ] + } + }, + "additionalProperties": false, + "required": [ + "acrRG", + "imageRepo", + "imageTag", + "managedIdentityName", + "k8s", + "azureOperatorsManagedIdentities", + "postgres" + ] + }, + "cxKeyVault": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "softDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "private", + "softDelete" + ] + }, + "extraVars": { + "type": "object", + "properties": {}, + "required": [] + }, + "firstPartyAppClientId": { + "type": "string" + }, + "miMockClientId": { + "type": "string" + }, + "miMockPrincipalId": { + "type": "string" + }, + "armHelperClientId": { + "type": "string" + }, + "armHelperFPAPrincipalId": { + "type": "string" + }, + "backend": { + "type": "object", + "properties": { + "imageTag": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "imageTag" + ] + }, + "frontend": { + "type": "object", + "properties": { + "imageTag": { + "type": "string" + }, + "cosmosDB": { + "type": "object", + "properties": { + "deploy": { + "type": "boolean" + }, + "disableLocalAuth": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "deploy", + "disableLocalAuth", + "name", + "private" + ] + }, + "cert": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "issuer": { + "type": "string", + "enum": [ + "Self", + "OneCertV2-PublicCA", + "OneCertV2-PrivateCA" + ] + } + }, + "additionalProperties": false, + "required": [ + "name", + "issuer" + ] + } + }, + "additionalProperties": false, + "required": [ + "imageTag", + "cosmosDB", + "cert" + ] + }, + "global": { + "type": "object", + "properties": { + "rg": { + "type": "string" + }, + "subscription": { + "type": "string" + }, + "region": { + "type": "string" + }, + "globalMSIName": { + "type": "string", + "description": "The name of the MSI that will be used for ev2" + } + }, + "required": [ + "rg", + "subscription", + "region" + ] + }, + "hypershift": { + "type": "object", + "properties": { + "additionalInstallArg": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "additionalInstallArg", + "namespace" + ] + }, + "hypershiftOperator": { + "type": "object", + "properties": { + "imageTag": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "imageTag" + ] + }, + "imageSync": { + "type": "object", + "properties": { + "acrRG": { + "type": "string" + }, + "environmentName": { + "type": "string" + }, + "componentSync": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "imageRepo": { + "type": "string" + }, + "imageTag": { + "type": "string" + }, + "repositories": { + "type": "string" + }, + "secrets": { + "$ref": "#/definitions/keyColonValueCSV" + }, + "pullSecretName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "enabled", + "imageRepo", + "imageTag", + "repositories", + "secrets", + "pullSecretName" + ] + }, + "ocMirror": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "imageRepo": { + "type": "string" + }, + "imageTag": { + "type": "string" + }, + "pullSecretName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "enabled", + "imageRepo", + "imageTag", + "pullSecretName" + ] + }, + "keyVault": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "softDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "private", + "softDelete" + ] + }, + "rg": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "acrRG", + "environmentName", + "componentSync", + "ocMirror", + "keyVault", + "rg" + ] + }, + "acrPullImageDigest": { + "type": "string" + }, + "maestro": { + "type": "object", + "properties": { + "certDomain": { + "type": "string" + }, + "consumerName": { + "type": "string" + }, + "server": { + "type": "object", + "properties": { + "mqttClientName": { + "type": "string" + }, + "managedIdentityName": { + "type": "string" + }, + "k8s": { + "type": "object", + "properties": { + "namespace": { + "type": "string" + }, + "serviceAccountName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "namespace", + "serviceAccountName" + ] + } + }, + "additionalProperties": false, + "required": [ + "mqttClientName", + "managedIdentityName", + "k8s" + ] + }, + "eventGrid": { + "type": "object", + "properties": { + "maxClientSessionsPerAuthName": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "maxClientSessionsPerAuthName", + "name", + "private" + ] + }, + "imageBase": { + "type": "string" + }, + "imageTag": { + "type": "string" + }, + "postgres": { + "type": "object", + "properties": { + "deploy": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "serverStorageSizeGB": { + "type": "integer" + }, + "serverVersion": { + "type": "string" + }, + "minTLSVersion": { + "type": "string", + "enum": ["TLSV1.2", "TLSV1.3"] + }, + "databaseName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "deploy", + "name", + "private", + "serverStorageSizeGB", + "serverVersion", + "minTLSVersion", + "databaseName" + ] + }, + "restrictIstioIngress": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "certDomain", + "consumerName", + "server", + "eventGrid", + "imageBase", + "imageTag", + "postgres", + "restrictIstioIngress" + ] + }, + "mce": { + "type": "object", + "properties": { + "clcStateMetrics": { + "type": "object", + "properties": { + "imageDigest": { + "type": "string" + } + }, + "required": [ + "imageDigest" + ] + } + }, + "required": [ + "clcStateMetrics" + ] + }, + "mgmt": { + "type": "object", + "properties": { + "aks": { + "$ref": "#/definitions/aksConfig" + }, + "rg": { + "type": "string" + }, + "subscription": { + "type": "string" + }, + "clusterServiceResourceId": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "aks", + "clusterServiceResourceId", + "rg", + "subscription" + ] + }, + "mgmtKeyVault": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "softDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "private", + "softDelete" + ] + }, + "monitoring": { + "type": "object", + "properties": { + "grafanaAdminGroupPrincipalId": { + "type": "string" + }, + "grafanaName": { + "type": "string" + }, + "msiName": { + "type": "string" + }, + "workspaceName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "grafanaAdminGroupPrincipalId", + "grafanaName", + "msiName", + "workspaceName" + ] + }, + "msiKeyVault": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "softDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "private", + "softDelete" + ] + }, + "ocpAcrName": { + "type": "string" + }, + "oidcStorageAccountName": { + "type": "string" + }, + "region": { + "type": "string" + }, + "regionRG": { + "type": "string" + }, + "serviceKeyVault": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "private": { + "type": "boolean" + }, + "region": { + "type": "string" + }, + "rg": { + "type": "string" + }, + "softDelete": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "private", + "region", + "rg", + "softDelete" + ] + }, + "svc": { + "type": "object", + "properties": { + "aks": { + "$ref": "#/definitions/aksConfig" + }, + "rg": { + "type": "string" + }, + "subscription": { + "type": "string" + }, + "istio": { + "type": "object", + "properties": { + "istioctlVersion": { + "description": "Latest version of istioctl. This is used to download the istioctl", + "type": "string" + }, + "tag": { + "description": "The revision tag used in istioctl", + "type": "string" + }, + "versions": { + "description": "The current istio version in the AKS cluster as CSV, will need to change to array once tooling is ready", + "type": "string", + "pattern": "^[a-zA-Z0-9-]+(,[a-zA-Z0-9-]+)*$" + }, + "targetVersion": { + "description": "The target istio version that will be updated to", + "type": "string", + "pattern": "^[a-zA-Z0-9-]+$" + }, + "ingressGatewayIPAddressName": { + "type": "string" + }, + "ingressGatewayIPAddressIPTags": { + "$ref": "#/definitions/keyColonValueCSV" + } + }, + "additionalProperties": false, + "required": [ + "ingressGatewayIPAddressName" + ] + } + }, + "additionalProperties": false, + "required": [ + "rg", + "subscription", + "aks", + "istio" + ] + }, + "svcAcrName": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "aksName", + "aroDevopsMsiId", + "kvCertOfficerPrincipalId", + "clusterService", + "cxKeyVault", + "firstPartyAppClientId", + "frontend", + "global", + "hypershift", + "hypershiftOperator", + "imageSync", + "acrPullImageDigest", + "maestro", + "mgmt", + "mgmtKeyVault", + "mce", + "monitoring", + "msiKeyVault", + "ocpAcrName", + "oidcStorageAccountName", + "region", + "regionRG", + "serviceKeyVault", + "svc", + "svcAcrName" + ] + } diff --git a/config/config.yaml b/config/config.yaml index ef1f14589..50b59fef9 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,166 +1,364 @@ +$schema: config.schema.json defaults: region: {{ .ctx.region }} - # Resourcegroups - globalRG: global - regionRG: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }} - serviceClusterRG: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }}-svc - managementClusterRG: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }}-mgmt-{{ .ctx.cxStamp }} - imageSyncRG: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }}-imagesync + regionRG: hcp-underlay-{{ .ctx.regionShort }} + + global: + rg: global + subscription: ARO Hosted Control Planes (EA Subscription 1) + region: westus3 + globalMSIName: "global-rollout-identity" # General AKS config - kubernetesVersion: 1.30.5 - istioVersion: "['asm-1-22']" - vnetAddressPrefix: "10.128.0.0/14" - subnetPrefix: "10.128.8.0/21" - podSubnetPrefix: "10.128.64.0/18" aksName: aro-hcp-aks - # ACR - serviceComponentAcrResourceGroups: global + # ACR Pull + acrPullImageDigest: sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca #v0.1.7 + + # Hypershift + hypershift: + namespace: hypershift + additionalInstallArg: '--tech-preview-no-upgrade' - # SVC cluster specifics - svcEtcdKVName: {{ azureKeyVaultName "aro-hcp-etcd" 5 .ctx.region .ctx.regionStamp }} - svcEtcdKVSoftDelete: true + svc: + subscription: ARO Hosted Control Planes (EA Subscription 1) + rg: hcp-underlay-{{ .ctx.regionShort }}-svc + istio: + istioctlVersion: "1.23.1" + tag: "prod-stable" + targetVersion: "asm-1-23" + versions: "asm-1-23" + ingressGatewayIPAddressName: "aro-hcp-istio-ingress" + ingressGatewayIPAddressIPTags: "" + aks: + vnetAddressPrefix: "10.128.0.0/14" + subnetPrefix: "10.128.8.0/21" + podSubnetPrefix: "10.128.64.0/18" + kubernetesVersion: 1.31.2 + etcd: + kvName: arohcp-etcd-{{ .ctx.regionShort }} + kvSoftDelete: true + clusterOutboundIPAddressIPTags: "" # MGMT cluster specifics - mgmtEtcdKVName: {{ azureKeyVaultName "aro-hcp-etcd" 5 .ctx.region .ctx.regionStamp .ctx.cxStamp }} - mgmtEtcdKVSoftDelete: true + mgmt: + clusterServiceResourceId: /subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourcegroups/hcp-underlay-{{ .ctx.regionShort }}-svc/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clusters-service + subscription: ARO Hosted Control Planes (EA Subscription 1) + rg: hcp-underlay-{{ .ctx.regionShort }}-mgmt-{{ .ctx.stamp }} + aks: + vnetAddressPrefix: "10.128.0.0/14" + subnetPrefix: "10.128.8.0/21" + podSubnetPrefix: "10.128.64.0/18" + kubernetesVersion: 1.31.2 + etcd: + kvName: arohcp-etcd-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + kvSoftDelete: true + clusterOutboundIPAddressIPTags: "" # Frontend - frontendCosmosDBDeploy: true - frontendCosmosDBDisableLocalAuth: true - frontendCosmosDBName: {{ azureCosmosDBName "aro-hcp-rp" 5 .ctx.region .ctx.regionStamp }} + frontend: + cosmosDB: + deploy: true + disableLocalAuth: true + name: arohcp-rp-{{ .ctx.regionShort }} + private: true + cert: + name: frontend-cert-{{ .ctx.regionShort }} + issuer: Self # Maestro - maestroKeyVaultName: {{ azureKeyVaultName "maestro" 5 .ctx.region .ctx.regionStamp }} - maestroEventgridName: {{ azureEventGridName "maestro" 5 .ctx.region .ctx.regionStamp }} - maestroEventGridMaxClientSessionsPerAuthName: '4' - maestroCertDomain: 'selfsigned.maestro.keyvault.azure.com' - maestroPostgresName: {{ azurePostgresName "maestro" 5 .ctx.region .ctx.regionStamp }} - maestroPostgresServerVersion: '15' - maestroPostgresServerStorageSizeGB: '32' - maestroPostgresDeploy: true - maestroPostgresPrivate: false - maestroRestrictIstioIngress: true - maestroConsumerName: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }}-mgmt-{{ .ctx.cxStamp }} + maestro: + server: + mqttClientName: maestro-server + managedIdentityName: maestro-server + k8s: + namespace: maestro + serviceAccountName: maestro + eventGrid: + name: arohcp-maestro-{{ .ctx.regionShort }} + maxClientSessionsPerAuthName: 4 + private: false + certDomain: 'selfsigned.maestro.keyvault.azure.com' + postgres: + name: arohcp-maestro-{{ .ctx.regionShort }} + serverVersion: '15' + serverStorageSizeGB: 32 + deploy: true + private: false + minTLSVersion: 'TLSV1.2' + databaseName: maestro + restrictIstioIngress: true + consumerName: hcp-underlay-{{ .ctx.regionShort }}-mgmt-{{ .ctx.stamp }} + imageBase: quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro + + pko: + image: arohcpsvcdev.azurecr.io/package-operator/package-operator-package + imageManager: arohcpsvcdev.azurecr.io/package-operator/package-operator-manager + imageTag: v1.15.0 # Cluster Service - clusterServicePostgresName: {{ azurePostgresName "cs" 5 .ctx.region .ctx.regionStamp }} - clusterServicePostgresDeploy: true - clusterServicePostgresPrivate: false - clusterServiceAcrRG: global + clusterService: + acrRG: global + postgres: + name: arohcp-cs-{{ .ctx.regionShort }} + deploy: true + private: false + minTLSVersion: 'TLSV1.2' + managedIdentityName: clusters-service + k8s: + namespace: cluster-service + serviceAccountName: clusters-service # Image Sync - imageSyncAcrRG: global - imageSyncEnvironmentName: aro-hcp-image-sync - imageSyncRepositories: registry.k8s.io/external-dns/external-dns,quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package - imageSyncImageRepo: image-sync/component-sync - imageSyncImageTag: latest - ocMirrorImageRepo: image-sync/oc-mirror - ocMirrorImageTag: 7abc8af - - # Service KeyVault - serviceKeyVaultName: {{ azureKeyVaultName "aro-hcp-svc" 5 .ctx.region .ctx.regionStamp }} - serviceKeyVaultRG: hcp-underlay-{{ .ctx.region }}-svc-{{ .ctx.regionStamp }} - serviceKeyVaultRegion: {{ .ctx.region }} - serviceKeyVaultSoftDelete: true - serviceKeyVaultPrivate: true + imageSync: + rg: hcp-underlay-{{ .ctx.regionShort }}-imagesync + acrRG: global + environmentName: aro-hcp-image-sync + componentSync: + enabled: true + imageRepo: image-sync/component-sync + imageTag: 8d3c113 + repositories: quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package,quay.io/package-operator/package-operator-manager + secrets: 'quay.io:bearer-secret' + pullSecretName: component-sync-pull-secret + ocMirror: + enabled: true + imageRepo: image-sync/oc-mirror + imageTag: 0b3c08f + pullSecretName: pull-secret + keyVault: + name: arohcp-imagesync-dev + private: false + softDelete: false + + # MCE + mce: + clcStateMetrics: + imageDigest: bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7 + + serviceKeyVault: + name: arohcp-svc-{{ .ctx.regionShort }} + rg: hcp-underlay-{{ .ctx.regionShort }} + region: {{ .ctx.region }} + softDelete: true + private: true # Management Cluster KV - cxKeyVaultName: {{ azureKeyVaultName "aro-hcp-cx" 5 .ctx.region .ctx.regionStamp .ctx.cxStamp }} - cxKeyVaultSoftDelete: true - cxKeyVaultPrivate: true - msiKeyVaultName: {{ azureKeyVaultName "aro-hcp-msi" 5 .ctx.region .ctx.regionStamp .ctx.cxStamp }} - msiKeyVaultSoftDelete: true - msiKeyVaultPrivate: true - mgmtKeyVaultName: {{ azureKeyVaultName "aro-hcp-mgmt" 5 .ctx.region .ctx.regionStamp .ctx.cxStamp }} - mgmtKeyVaultSoftDelete: true - mgmtKeyVaultPrivate: true - - # DNS - baseDnsZoneRG: 'global' + cxKeyVault: + name: arohcp-cx-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: true + private: true + msiKeyVault: + name: arohcp-msi-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: true + private: true + mgmtKeyVault: + name: arohcp-mgmt-{{ .ctx.regionShort }}-{{ .ctx.stamp }} + softDelete: true + private: true + clouds: public: # this configuration serves as a template for for all RH DEV subscription deployments # the following vars need approprivate overrides: defaults: # DNS - baseDnsZoneName: 'hcp.osadev.cloud' - # MGMTM AKS nodepools - big enough for 2 HCPs - mgmtSystemAgentPoolMinCount: 1 - mgmtSystemAgentPoolMaxCount: 4 - mgmtSystemAgentPoolVmSize: 'Standard_D2s_v3' - mgmtSystemAgentPoolOsDiskSizeGB: 32 - mgmtUserAgentPoolMinCount: 1 - mgmtUserAgentPoolMaxCount: 6 - mgmtUserAgentPoolVmSize: 'Standard_D4s_v3' - mgmtUserAgentPoolOsDiskSizeGB: 100 - mgmtUserAgentPoolAzCount: 3 + dns: + baseDnsZoneRG: global + cxParentZoneName: hcp.osadev.cloud + svcParentZoneName: hcpsvc.osadev.cloud + parentZoneName: osadev.cloud # 1P app firstPartyAppClientId: 57e54810-3138-4f38-bd3b-29cb33f4c358 + # Mock Managed Identities Service Princiapl + miMockClientId: 4daa4e3b-abc1-4f9c-812c-77bd37e06741 + miMockPrincipalId: a03f690c-4b2e-4eef-841e-f1904efe0e37 + # ARM Helper + armHelperClientId: 2c6ca254-36bd-43c8-a7a8-fe880bc2c489 + armHelperFPAPrincipalId: bc17c825-6cf8-40d0-8bd6-5536a993115e # Maestro - maestroPostgresDeploy: false - maestroImageBase: quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro - maestroImageTag: ea066c250a002f0cc458711945165591bc9f6d3f + maestro: + imageTag: c9a36e110a32c0c25aa5025cfe6d51af797e6d4b # Cluster Service - clusterServiceImageTag: a23276d - clusterServiceImageRepo: app-sre/uhc-clusters-service + clusterService: + imageTag: dca2a71 + imageRepo: app-sre/uhc-clusters-service + azureOperatorsManagedIdentities: + clusterApiAzure: + roleName: Contributor + controlPlane: + roleName: Contributor + cloudControllerManager: + roleName: Azure Red Hat OpenShift Cloud Controller Manager - Dev + ingress: + roleName: Azure Red Hat OpenShift Cluster Ingress Operator - Dev + diskCsiDriver: + roleName: Azure Red Hat OpenShift Disk Storage Operator - Dev + fileCsiDriver: + roleName: Azure Red Hat OpenShift File Storage Operator - Dev + imageRegistry: + roleName: Azure Red Hat OpenShift Image Registry Operator - Dev + cloudNetworkConfig: + roleName: Azure Red Hat OpenShift Network Operator - Dev # Hypershift Operator - hypershiftOperatorImageTag: 99a256f - externalDNSImageTag: v0.14.2 + hypershiftOperator: + imageTag: 9aca808 + # Frontend + frontend: + imageTag: '' # if empty uses commit sha of repo + # Backend + backend: + imageTag: '' # if empty uses commit sha of repo # Shared SVC KV - serviceKeyVaultName: 'aro-hcp-dev-svc-kv' - serviceKeyVaultRG: 'global' - serviceKeyVaultRegion: 'westus3' - serviceKeyVaultPrivate: false + serviceKeyVault: + name: 'aro-hcp-dev-svc-kv' + rg: 'global' + region: 'westus3' + private: false # Management Cluster KVs - cxKeyVaultSoftDelete: false - cxKeyVaultPrivate: false - msiKeyVaultSoftDelete: false - msiKeyVaultPrivate: false - mgmtKeyVaultSoftDelete: false - mgmtKeyVaultPrivate: false + cxKeyVault: + softDelete: false + private: false + msiKeyVault: + softDelete: false + private: false + mgmtKeyVault: + softDelete: false + private: false # disable soft delete on etcd KVs in DEV - svcEtcdKVSoftDelete: false - mgmtEtcdKVSoftDelete: false + svc: + subscription: ARO Hosted Control Planes (EA Subscription 1) + aks: + etcd: + kvSoftDelete: false + systemAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 32 + userAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 32 + azCount: 3 + + mgmt: + aks: + # MGMTM AKS nodepools - big enough for 2 HCPs + systemAgentPool: + minCount: 1 + maxCount: 4 + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 32 + userAgentPool: + minCount: 1 + maxCount: 6 + vmSize: 'Standard_D4s_v3' + osDiskSizeGB: 100 + azCount: 3 + etcd: + kvSoftDelete: false + subscription: ARO Hosted Control Planes (EA Subscription 1) # Shared ACRs - acrName: arohcpdev svcAcrName: arohcpsvcdev ocpAcrName: arohcpocpdev # Shared Image Sync - imageSyncRG: hcp-underlay-westus3-imagesync-dev + imageSync: + rg: hcp-underlay-westus3-imagesync-dev # OIDC - oidcStorageAccountName: {{ azureStorageAccountName "arohcpoidc" 5 .ctx.region .ctx.regionStamp }} + oidcStorageAccountName: arohcpoidc{{ .ctx.regionShort }} # Metrics - monitoringWorkspaceName: 'aro-hcp-monitor-{{ uniqueString 5 .ctx.region .ctx.regionStamp}}' - grafanaName: 'aro-hcp-grafana-{{ uniqueString 5 .ctx.region .ctx.regionStamp}}' - monitoringMsiName: 'aro-hcp-metrics-msi-{{ uniqueString 5 .ctx.region .ctx.regionStamp }}' - grafanaAdminGroupPrincipalId: 6b6d3adf-8476-4727-9812-20ffdef2b85c + monitoring: + workspaceName: 'arohcp-{{ .ctx.regionShort }}' + grafanaName: 'arohcp-dev' + msiName: 'aro-hcp-metrics-msi-{{ .ctx.regionShort }}' + grafanaAdminGroupPrincipalId: 6b6d3adf-8476-4727-9812-20ffdef2b85c # DEVOPS MSI - aroDevopsMsiId: '/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aro-hcp-devops' + aroDevopsMsiId: '/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-rollout-identity' + kvCertOfficerPrincipalId: '876db5bd-9a48-4bf7-a6a7-088437afa993' environments: dev: # this is the integrated DEV environment defaults: - # MGMTM AKS nodepools - big enough for multiple HCPs - mgmtUserAgentPoolMinCount: 2 - mgmtUserAgentPoolMaxCount: 12 + mgmt: + aks: + systemAgentPool: + minCount: 1 + maxCount: 4 + vmSize: 'Standard_E8s_v3' + osDiskSizeGB: 128 + # MC AKS nodepools + # big enough for multiple HCPs + userAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D16s_v3' + osDiskSizeGB: 128 # DNS - regionalDNSSubdomain: '{{ .ctx.region }}' + dns: + regionalSubdomain: '{{ .ctx.region }}' + # Maestro + maestro: + server: + mqttClientName: 'maestro-server-{{ .ctx.regionShort }}-dev' + # Frontend + frontend: + cosmosDB: + private: false cs-pr: # this is the cluster service PR check and full cycle test environment defaults: - # MGMTM AKS nodepools - big enough for multiple HCPs - mgmtUserAgentPoolMinCount: 2 - mgmtUserAgentPoolMaxCount: 12 + svc: + aks: + # MC AKS nodepools + # big enough for multiple CS instances during PR checks + userAgentPool: + minCount: 2 + maxCount: 12 + mgmt: + aks: + systemAgentPool: + minCount: 1 + maxCount: 4 + vmSize: 'Standard_E8s_v3' + osDiskSizeGB: 128 + # MC AKS nodepools + # big enough for multiple HCPs + userAgentPool: + minCount: 1 + maxCount: 3 + vmSize: 'Standard_D16s_v3' + osDiskSizeGB: 128 # DNS - regionalDNSSubdomain: '{{ .ctx.region }}-cs' + dns: + regionalSubdomain: '{{ .ctx.region }}-cs' # Maestro - maestroRestrictIstioIngress: false + maestro: + restrictIstioIngress: false + server: + mqttClientName: 'maestro-server-{{ .ctx.regionShort }}-cs' + # Frontend + frontend: + cosmosDB: + private: false personal-dev: # this is the personal DEV environment defaults: # Cluster Service - clusterServicePostgresDeploy: false + clusterService: + postgres: + deploy: false # DNS - regionalDNSSubdomain: '{{ .ctx.region }}-{{ uniqueString 5 .ctx.region .ctx.regionStamp }}' + dns: + regionalSubdomain: '{{ .ctx.regionShort }}' + # Maestro + maestro: + postgres: + deploy: false + server: + mqttClientName: 'maestro-server-{{ .ctx.regionShort }}' + # Frontend + frontend: + cosmosDB: + private: false diff --git a/config/public-cloud-cs-pr.json b/config/public-cloud-cs-pr.json index c83df8590..e486efae4 100644 --- a/config/public-cloud-cs-pr.json +++ b/config/public-cloud-cs-pr.json @@ -1,86 +1,251 @@ { - "acrName": "arohcpdev", + "acrPullImageDigest": "sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca", "aksName": "aro-hcp-aks", - "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aro-hcp-devops", - "baseDnsZoneName": "hcp.osadev.cloud", - "baseDnsZoneRG": "global", - "clusterServiceAcrRG": "global", - "clusterServiceImageRepo": "app-sre/uhc-clusters-service", - "clusterServiceImageTag": "a23276d", - "clusterServicePostgresDeploy": true, - "clusterServicePostgresName": "cs-9c782", - "clusterServicePostgresPrivate": false, - "cxKeyVaultName": "aro-hcp-cx-1abb8", - "cxKeyVaultPrivate": false, - "cxKeyVaultSoftDelete": false, - "externalDNSImageTag": "v0.14.2", + "armHelperClientId": "2c6ca254-36bd-43c8-a7a8-fe880bc2c489", + "armHelperFPAPrincipalId": "bc17c825-6cf8-40d0-8bd6-5536a993115e", + "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-rollout-identity", + "backend": { + "imageTag": "" + }, + "clusterService": { + "acrRG": "global", + "azureOperatorsManagedIdentities": { + "cloudControllerManager": { + "roleName": "Azure Red Hat OpenShift Cloud Controller Manager - Dev" + }, + "cloudNetworkConfig": { + "roleName": "Azure Red Hat OpenShift Network Operator - Dev" + }, + "clusterApiAzure": { + "roleName": "Contributor" + }, + "controlPlane": { + "roleName": "Contributor" + }, + "diskCsiDriver": { + "roleName": "Azure Red Hat OpenShift Disk Storage Operator - Dev" + }, + "fileCsiDriver": { + "roleName": "Azure Red Hat OpenShift File Storage Operator - Dev" + }, + "imageRegistry": { + "roleName": "Azure Red Hat OpenShift Image Registry Operator - Dev" + }, + "ingress": { + "roleName": "Azure Red Hat OpenShift Cluster Ingress Operator - Dev" + } + }, + "imageRepo": "app-sre/uhc-clusters-service", + "imageTag": "dca2a71", + "k8s": { + "namespace": "cluster-service", + "serviceAccountName": "clusters-service" + }, + "managedIdentityName": "clusters-service", + "postgres": { + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-cs-cspr", + "private": false + } + }, + "cxKeyVault": { + "name": "arohcp-cx-cspr-1", + "private": false, + "softDelete": false + }, + "dns": { + "baseDnsZoneRG": "global", + "cxParentZoneName": "hcp.osadev.cloud", + "parentZoneName": "osadev.cloud", + "regionalSubdomain": "westus3-cs", + "svcParentZoneName": "hcpsvc.osadev.cloud" + }, + "extraVars": {}, "firstPartyAppClientId": "57e54810-3138-4f38-bd3b-29cb33f4c358", - "frontendCosmosDBDeploy": true, - "frontendCosmosDBDisableLocalAuth": true, - "frontendCosmosDBName": "aro-hcp-rp-9c782", - "globalRG": "global", - "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", - "grafanaName": "aro-hcp-grafana-9c782", - "hypershiftOperatorImageTag": "99a256f", - "imageSyncAcrRG": "global", - "imageSyncEnvironmentName": "aro-hcp-image-sync", - "imageSyncImageRepo": "image-sync/component-sync", - "imageSyncImageTag": "latest", - "imageSyncRG": "hcp-underlay-westus3-imagesync-dev", - "imageSyncRepositories": "registry.k8s.io/external-dns/external-dns,quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package", - "istioVersion": "['asm-1-22']", - "kubernetesVersion": "1.30.5", - "maestroCertDomain": "selfsigned.maestro.keyvault.azure.com", - "maestroConsumerName": "hcp-underlay-westus3-cs-pr-mgmt-1", - "maestroEventGridMaxClientSessionsPerAuthName": "4", - "maestroEventgridName": "maestro-9c782", - "maestroImageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", - "maestroImageTag": "ea066c250a002f0cc458711945165591bc9f6d3f", - "maestroKeyVaultName": "maestro-9c782", - "maestroPostgresDeploy": false, - "maestroPostgresName": "maestro-9c782", - "maestroPostgresPrivate": false, - "maestroPostgresServerStorageSizeGB": "32", - "maestroPostgresServerVersion": "15", - "maestroRestrictIstioIngress": false, - "managementClusterRG": "hcp-underlay-westus3-cs-pr-mgmt-1", - "mgmtEtcdKVName": "aro-hcp-etcd-1abb8", - "mgmtEtcdKVSoftDelete": false, - "mgmtKeyVaultName": "aro-hcp-mgmt-1abb8", - "mgmtKeyVaultPrivate": false, - "mgmtKeyVaultSoftDelete": false, - "mgmtSystemAgentPoolMaxCount": 4, - "mgmtSystemAgentPoolMinCount": 1, - "mgmtSystemAgentPoolOsDiskSizeGB": 32, - "mgmtSystemAgentPoolVmSize": "Standard_D2s_v3", - "mgmtUserAgentPoolAzCount": 3, - "mgmtUserAgentPoolMaxCount": 12, - "mgmtUserAgentPoolMinCount": 2, - "mgmtUserAgentPoolOsDiskSizeGB": 100, - "mgmtUserAgentPoolVmSize": "Standard_D4s_v3", - "monitoringMsiName": "aro-hcp-metrics-msi-9c782", - "monitoringWorkspaceName": "aro-hcp-monitor-9c782", - "msiKeyVaultName": "aro-hcp-msi-1abb8", - "msiKeyVaultPrivate": false, - "msiKeyVaultSoftDelete": false, - "ocMirrorImageRepo": "image-sync/oc-mirror", - "ocMirrorImageTag": "7abc8af", + "frontend": { + "cert": { + "issuer": "Self", + "name": "frontend-cert-cspr" + }, + "cosmosDB": { + "deploy": true, + "disableLocalAuth": true, + "name": "arohcp-rp-cspr", + "private": false + }, + "imageTag": "" + }, + "global": { + "globalMSIName": "global-rollout-identity", + "region": "westus3", + "rg": "global", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "hypershift": { + "additionalInstallArg": "--tech-preview-no-upgrade", + "namespace": "hypershift" + }, + "hypershiftOperator": { + "imageTag": "9aca808" + }, + "imageSync": { + "acrRG": "global", + "componentSync": { + "enabled": true, + "imageRepo": "image-sync/component-sync", + "imageTag": "8d3c113", + "pullSecretName": "component-sync-pull-secret", + "repositories": "quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package,quay.io/package-operator/package-operator-manager", + "secrets": "quay.io:bearer-secret" + }, + "environmentName": "aro-hcp-image-sync", + "keyVault": { + "name": "arohcp-imagesync-dev", + "private": false, + "softDelete": false + }, + "ocMirror": { + "enabled": true, + "imageRepo": "image-sync/oc-mirror", + "imageTag": "0b3c08f", + "pullSecretName": "pull-secret" + }, + "rg": "hcp-underlay-westus3-imagesync-dev" + }, + "kvCertOfficerPrincipalId": "876db5bd-9a48-4bf7-a6a7-088437afa993", + "maestro": { + "certDomain": "selfsigned.maestro.keyvault.azure.com", + "consumerName": "hcp-underlay-cspr-mgmt-1", + "eventGrid": { + "maxClientSessionsPerAuthName": 4, + "name": "arohcp-maestro-cspr", + "private": false + }, + "imageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", + "imageTag": "c9a36e110a32c0c25aa5025cfe6d51af797e6d4b", + "postgres": { + "databaseName": "maestro", + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-maestro-cspr", + "private": false, + "serverStorageSizeGB": 32, + "serverVersion": "15" + }, + "restrictIstioIngress": false, + "server": { + "k8s": { + "namespace": "maestro", + "serviceAccountName": "maestro" + }, + "managedIdentityName": "maestro-server", + "mqttClientName": "maestro-server-cspr-cs" + } + }, + "mce": { + "clcStateMetrics": { + "imageDigest": "bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7" + } + }, + "mgmt": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-cspr-1", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 4, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_E8s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_D16s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "clusterServiceResourceId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourcegroups/hcp-underlay-cspr-svc/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clusters-service", + "rg": "hcp-underlay-cspr-mgmt-1", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "mgmtKeyVault": { + "name": "arohcp-mgmt-cspr-1", + "private": false, + "softDelete": false + }, + "miMockClientId": "4daa4e3b-abc1-4f9c-812c-77bd37e06741", + "miMockPrincipalId": "a03f690c-4b2e-4eef-841e-f1904efe0e37", + "monitoring": { + "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", + "grafanaName": "arohcp-dev", + "msiName": "aro-hcp-metrics-msi-cspr", + "workspaceName": "arohcp-cspr" + }, + "msiKeyVault": { + "name": "arohcp-msi-cspr-1", + "private": false, + "softDelete": false + }, "ocpAcrName": "arohcpocpdev", - "oidcStorageAccountName": "arohcpoidc9c782", - "podSubnetPrefix": "10.128.64.0/18", + "oidcStorageAccountName": "arohcpoidccspr", + "pko": { + "image": "arohcpsvcdev.azurecr.io/package-operator/package-operator-package", + "imageManager": "arohcpsvcdev.azurecr.io/package-operator/package-operator-manager", + "imageTag": "v1.15.0" + }, "region": "westus3", - "regionRG": "hcp-underlay-westus3-cs-pr", - "regionalDNSSubdomain": "westus3-cs", - "serviceClusterRG": "hcp-underlay-westus3-cs-pr-svc", - "serviceComponentAcrResourceGroups": "global", - "serviceKeyVaultName": "aro-hcp-dev-svc-kv", - "serviceKeyVaultPrivate": false, - "serviceKeyVaultRG": "global", - "serviceKeyVaultRegion": "westus3", - "serviceKeyVaultSoftDelete": true, - "subnetPrefix": "10.128.8.0/21", - "svcAcrName": "arohcpsvcdev", - "svcEtcdKVName": "aro-hcp-etcd-9c782", - "svcEtcdKVSoftDelete": false, - "vnetAddressPrefix": "10.128.0.0/14" + "regionRG": "hcp-underlay-cspr", + "serviceKeyVault": { + "name": "aro-hcp-dev-svc-kv", + "private": false, + "region": "westus3", + "rg": "global", + "softDelete": true + }, + "svc": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-cspr", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 12, + "minCount": 2, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "istio": { + "ingressGatewayIPAddressIPTags": "", + "ingressGatewayIPAddressName": "aro-hcp-istio-ingress", + "istioctlVersion": "1.23.1", + "tag": "prod-stable", + "targetVersion": "asm-1-23", + "versions": "asm-1-23" + }, + "rg": "hcp-underlay-cspr-svc", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "svcAcrName": "arohcpsvcdev" } diff --git a/config/public-cloud-dev.json b/config/public-cloud-dev.json index 6f39aaa93..0112a9b9c 100644 --- a/config/public-cloud-dev.json +++ b/config/public-cloud-dev.json @@ -1,86 +1,251 @@ { - "acrName": "arohcpdev", + "acrPullImageDigest": "sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca", "aksName": "aro-hcp-aks", - "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aro-hcp-devops", - "baseDnsZoneName": "hcp.osadev.cloud", - "baseDnsZoneRG": "global", - "clusterServiceAcrRG": "global", - "clusterServiceImageRepo": "app-sre/uhc-clusters-service", - "clusterServiceImageTag": "a23276d", - "clusterServicePostgresDeploy": true, - "clusterServicePostgresName": "cs-157ff", - "clusterServicePostgresPrivate": false, - "cxKeyVaultName": "aro-hcp-cx-08101", - "cxKeyVaultPrivate": false, - "cxKeyVaultSoftDelete": false, - "externalDNSImageTag": "v0.14.2", + "armHelperClientId": "2c6ca254-36bd-43c8-a7a8-fe880bc2c489", + "armHelperFPAPrincipalId": "bc17c825-6cf8-40d0-8bd6-5536a993115e", + "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-rollout-identity", + "backend": { + "imageTag": "" + }, + "clusterService": { + "acrRG": "global", + "azureOperatorsManagedIdentities": { + "cloudControllerManager": { + "roleName": "Azure Red Hat OpenShift Cloud Controller Manager - Dev" + }, + "cloudNetworkConfig": { + "roleName": "Azure Red Hat OpenShift Network Operator - Dev" + }, + "clusterApiAzure": { + "roleName": "Contributor" + }, + "controlPlane": { + "roleName": "Contributor" + }, + "diskCsiDriver": { + "roleName": "Azure Red Hat OpenShift Disk Storage Operator - Dev" + }, + "fileCsiDriver": { + "roleName": "Azure Red Hat OpenShift File Storage Operator - Dev" + }, + "imageRegistry": { + "roleName": "Azure Red Hat OpenShift Image Registry Operator - Dev" + }, + "ingress": { + "roleName": "Azure Red Hat OpenShift Cluster Ingress Operator - Dev" + } + }, + "imageRepo": "app-sre/uhc-clusters-service", + "imageTag": "dca2a71", + "k8s": { + "namespace": "cluster-service", + "serviceAccountName": "clusters-service" + }, + "managedIdentityName": "clusters-service", + "postgres": { + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-cs-dev", + "private": false + } + }, + "cxKeyVault": { + "name": "arohcp-cx-dev-1", + "private": false, + "softDelete": false + }, + "dns": { + "baseDnsZoneRG": "global", + "cxParentZoneName": "hcp.osadev.cloud", + "parentZoneName": "osadev.cloud", + "regionalSubdomain": "westus3", + "svcParentZoneName": "hcpsvc.osadev.cloud" + }, + "extraVars": {}, "firstPartyAppClientId": "57e54810-3138-4f38-bd3b-29cb33f4c358", - "frontendCosmosDBDeploy": true, - "frontendCosmosDBDisableLocalAuth": true, - "frontendCosmosDBName": "aro-hcp-rp-157ff", - "globalRG": "global", - "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", - "grafanaName": "aro-hcp-grafana-157ff", - "hypershiftOperatorImageTag": "99a256f", - "imageSyncAcrRG": "global", - "imageSyncEnvironmentName": "aro-hcp-image-sync", - "imageSyncImageRepo": "image-sync/component-sync", - "imageSyncImageTag": "latest", - "imageSyncRG": "hcp-underlay-westus3-imagesync-dev", - "imageSyncRepositories": "registry.k8s.io/external-dns/external-dns,quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package", - "istioVersion": "['asm-1-22']", - "kubernetesVersion": "1.30.5", - "maestroCertDomain": "selfsigned.maestro.keyvault.azure.com", - "maestroConsumerName": "hcp-underlay-westus3-dev-mgmt-1", - "maestroEventGridMaxClientSessionsPerAuthName": "4", - "maestroEventgridName": "maestro-157ff", - "maestroImageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", - "maestroImageTag": "ea066c250a002f0cc458711945165591bc9f6d3f", - "maestroKeyVaultName": "maestro-157ff", - "maestroPostgresDeploy": false, - "maestroPostgresName": "maestro-157ff", - "maestroPostgresPrivate": false, - "maestroPostgresServerStorageSizeGB": "32", - "maestroPostgresServerVersion": "15", - "maestroRestrictIstioIngress": true, - "managementClusterRG": "hcp-underlay-westus3-dev-mgmt-1", - "mgmtEtcdKVName": "aro-hcp-etcd-08101", - "mgmtEtcdKVSoftDelete": false, - "mgmtKeyVaultName": "aro-hcp-mgmt-08101", - "mgmtKeyVaultPrivate": false, - "mgmtKeyVaultSoftDelete": false, - "mgmtSystemAgentPoolMaxCount": 4, - "mgmtSystemAgentPoolMinCount": 1, - "mgmtSystemAgentPoolOsDiskSizeGB": 32, - "mgmtSystemAgentPoolVmSize": "Standard_D2s_v3", - "mgmtUserAgentPoolAzCount": 3, - "mgmtUserAgentPoolMaxCount": 12, - "mgmtUserAgentPoolMinCount": 2, - "mgmtUserAgentPoolOsDiskSizeGB": 100, - "mgmtUserAgentPoolVmSize": "Standard_D4s_v3", - "monitoringMsiName": "aro-hcp-metrics-msi-157ff", - "monitoringWorkspaceName": "aro-hcp-monitor-157ff", - "msiKeyVaultName": "aro-hcp-msi-08101", - "msiKeyVaultPrivate": false, - "msiKeyVaultSoftDelete": false, - "ocMirrorImageRepo": "image-sync/oc-mirror", - "ocMirrorImageTag": "7abc8af", + "frontend": { + "cert": { + "issuer": "Self", + "name": "frontend-cert-dev" + }, + "cosmosDB": { + "deploy": true, + "disableLocalAuth": true, + "name": "arohcp-rp-dev", + "private": false + }, + "imageTag": "" + }, + "global": { + "globalMSIName": "global-rollout-identity", + "region": "westus3", + "rg": "global", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "hypershift": { + "additionalInstallArg": "--tech-preview-no-upgrade", + "namespace": "hypershift" + }, + "hypershiftOperator": { + "imageTag": "9aca808" + }, + "imageSync": { + "acrRG": "global", + "componentSync": { + "enabled": true, + "imageRepo": "image-sync/component-sync", + "imageTag": "8d3c113", + "pullSecretName": "component-sync-pull-secret", + "repositories": "quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package,quay.io/package-operator/package-operator-manager", + "secrets": "quay.io:bearer-secret" + }, + "environmentName": "aro-hcp-image-sync", + "keyVault": { + "name": "arohcp-imagesync-dev", + "private": false, + "softDelete": false + }, + "ocMirror": { + "enabled": true, + "imageRepo": "image-sync/oc-mirror", + "imageTag": "0b3c08f", + "pullSecretName": "pull-secret" + }, + "rg": "hcp-underlay-westus3-imagesync-dev" + }, + "kvCertOfficerPrincipalId": "876db5bd-9a48-4bf7-a6a7-088437afa993", + "maestro": { + "certDomain": "selfsigned.maestro.keyvault.azure.com", + "consumerName": "hcp-underlay-dev-mgmt-1", + "eventGrid": { + "maxClientSessionsPerAuthName": 4, + "name": "arohcp-maestro-dev", + "private": false + }, + "imageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", + "imageTag": "c9a36e110a32c0c25aa5025cfe6d51af797e6d4b", + "postgres": { + "databaseName": "maestro", + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-maestro-dev", + "private": false, + "serverStorageSizeGB": 32, + "serverVersion": "15" + }, + "restrictIstioIngress": true, + "server": { + "k8s": { + "namespace": "maestro", + "serviceAccountName": "maestro" + }, + "managedIdentityName": "maestro-server", + "mqttClientName": "maestro-server-dev-dev" + } + }, + "mce": { + "clcStateMetrics": { + "imageDigest": "bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7" + } + }, + "mgmt": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-dev-1", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 4, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_E8s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_D16s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "clusterServiceResourceId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourcegroups/hcp-underlay-dev-svc/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clusters-service", + "rg": "hcp-underlay-dev-mgmt-1", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "mgmtKeyVault": { + "name": "arohcp-mgmt-dev-1", + "private": false, + "softDelete": false + }, + "miMockClientId": "4daa4e3b-abc1-4f9c-812c-77bd37e06741", + "miMockPrincipalId": "a03f690c-4b2e-4eef-841e-f1904efe0e37", + "monitoring": { + "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", + "grafanaName": "arohcp-dev", + "msiName": "aro-hcp-metrics-msi-dev", + "workspaceName": "arohcp-dev" + }, + "msiKeyVault": { + "name": "arohcp-msi-dev-1", + "private": false, + "softDelete": false + }, "ocpAcrName": "arohcpocpdev", - "oidcStorageAccountName": "arohcpoidc157ff", - "podSubnetPrefix": "10.128.64.0/18", + "oidcStorageAccountName": "arohcpoidcdev", + "pko": { + "image": "arohcpsvcdev.azurecr.io/package-operator/package-operator-package", + "imageManager": "arohcpsvcdev.azurecr.io/package-operator/package-operator-manager", + "imageTag": "v1.15.0" + }, "region": "westus3", - "regionRG": "hcp-underlay-westus3-dev", - "regionalDNSSubdomain": "westus3", - "serviceClusterRG": "hcp-underlay-westus3-dev-svc", - "serviceComponentAcrResourceGroups": "global", - "serviceKeyVaultName": "aro-hcp-dev-svc-kv", - "serviceKeyVaultPrivate": false, - "serviceKeyVaultRG": "global", - "serviceKeyVaultRegion": "westus3", - "serviceKeyVaultSoftDelete": true, - "subnetPrefix": "10.128.8.0/21", - "svcAcrName": "arohcpsvcdev", - "svcEtcdKVName": "aro-hcp-etcd-157ff", - "svcEtcdKVSoftDelete": false, - "vnetAddressPrefix": "10.128.0.0/14" + "regionRG": "hcp-underlay-dev", + "serviceKeyVault": { + "name": "aro-hcp-dev-svc-kv", + "private": false, + "region": "westus3", + "rg": "global", + "softDelete": true + }, + "svc": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-dev", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "istio": { + "ingressGatewayIPAddressIPTags": "", + "ingressGatewayIPAddressName": "aro-hcp-istio-ingress", + "istioctlVersion": "1.23.1", + "tag": "prod-stable", + "targetVersion": "asm-1-23", + "versions": "asm-1-23" + }, + "rg": "hcp-underlay-dev-svc", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "svcAcrName": "arohcpsvcdev" } diff --git a/config/public-cloud-msft-int.json b/config/public-cloud-msft-int.json new file mode 100644 index 000000000..336d8dda4 --- /dev/null +++ b/config/public-cloud-msft-int.json @@ -0,0 +1,246 @@ +{ + "acrPullImageDigest": "sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca", + "aksName": "aro-hcp-aks", + "armHelperClientId": "f2af6a70-fc23-4a9a-bbf2-3236f86e65e4", + "armHelperFPAPrincipalId": "4026d9e7-2897-4f0c-83d4-897858a5f8a8", + "aroDevopsMsiId": "/subscriptions/5299e6b7-b23b-46c8-8277-dc1147807117/resourcegroups/global-shared-resources/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-ev2-identity", + "backend": { + "imageTag": "0b076bf" + }, + "clusterService": { + "acrRG": "global-shared-resources", + "azureOperatorsManagedIdentities": { + "cloudControllerManager": { + "roleName": "Azure Red Hat OpenShift Cloud Controller Manager Role" + }, + "cloudNetworkConfig": { + "roleName": "Azure Red Hat OpenShift Network Operator Role" + }, + "clusterApiAzure": { + "roleName": "Contributor" + }, + "controlPlane": { + "roleName": "Contributor" + }, + "diskCsiDriver": { + "roleName": "Azure Red Hat OpenShift Storage Operator Role" + }, + "fileCsiDriver": { + "roleName": "Azure Red Hat OpenShift Azure Files Storage Operator Role" + }, + "imageRegistry": { + "roleName": "Azure Red Hat OpenShift Image Registry Operator Role" + }, + "ingress": { + "roleName": "Azure Red Hat OpenShift Cluster Ingress Operator Role" + } + }, + "imageRepo": "app-sre/uhc-clusters-service", + "imageTag": "dca2a71", + "k8s": { + "namespace": "cluster-service", + "serviceAccountName": "clusters-service" + }, + "managedIdentityName": "clusters-service", + "postgres": { + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-cs-int", + "private": false + } + }, + "cxKeyVault": { + "name": "arohcp-cx-int-1", + "private": false, + "softDelete": false + }, + "dns": { + "baseDnsZoneRG": "global-shared-resources", + "cxParentZoneName": "aroapp-hcp.azure-test.net", + "parentZoneName": "azure-test.net", + "regionalSubdomain": "westus3", + "svcParentZoneName": "aro-hcp.azure-test.net" + }, + "extraVars": {}, + "firstPartyAppClientId": "5bc505bc-50ef-4be9-9a82-2ed7973f1c37", + "frontend": { + "cert": { + "issuer": "OneCertV2-PublicCA", + "name": "frontend-cert-int" + }, + "cosmosDB": { + "deploy": true, + "disableLocalAuth": true, + "name": "arohcp-rp-int", + "private": false + }, + "imageTag": "0b076bf" + }, + "global": { + "globalMSIName": "global-ev2-identity", + "region": "uksouth", + "rg": "global-shared-resources", + "subscription": "hcp-westus3" + }, + "hypershift": { + "additionalInstallArg": "--tech-preview-no-upgrade", + "namespace": "hypershift" + }, + "hypershiftOperator": { + "imageTag": "9aca808" + }, + "imageSync": { + "acrRG": "global-shared-resources", + "componentSync": { + "enabled": true, + "imageRepo": "image-sync/component-sync", + "imageTag": "0b076bf", + "pullSecretName": "component-sync-pull-secret", + "repositories": "arohcpsvcdev.azurecr.io/image-sync/component-sync,arohcpsvcdev.azurecr.io/arohcpfrontend,arohcpsvcdev.azurecr.io/arohcpbackend,quay.io/acm-d/rhtap-hypershift-operator,arohcpsvcdev.azurecr.io/image-sync/oc-mirror,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package", + "secrets": "quay.io:quay-io-bearer,arohcpsvcdev.azurecr.io:arohcpsvcdev-bearer" + }, + "environmentName": "global-shared-resources", + "keyVault": { + "name": "arohcp-imagesync-int", + "private": false, + "softDelete": true + }, + "ocMirror": { + "enabled": true, + "imageRepo": "image-sync/oc-mirror", + "imageTag": "0b076bf", + "pullSecretName": "ocp-pull-secret" + }, + "rg": "global-shared-resources" + }, + "kvCertOfficerPrincipalId": "32af88de-a61c-4f71-b709-50538598c4f2", + "maestro": { + "certDomain": "selfsigned.maestro.keyvault.azure.com", + "consumerName": "hcp-underlay-int-mgmt-1", + "eventGrid": { + "maxClientSessionsPerAuthName": 4, + "name": "arohcp-maestro-int", + "private": false + }, + "imageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", + "imageTag": "c9a36e110a32c0c25aa5025cfe6d51af797e6d4b", + "postgres": { + "databaseName": "maestro", + "deploy": true, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-maestro-int", + "private": false, + "serverStorageSizeGB": 32, + "serverVersion": "15" + }, + "restrictIstioIngress": true, + "server": { + "k8s": { + "namespace": "maestro", + "serviceAccountName": "maestro" + }, + "managedIdentityName": "maestro-server", + "mqttClientName": "maestro-server" + } + }, + "mce": { + "clcStateMetrics": { + "imageDigest": "bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7" + } + }, + "mgmt": { + "aks": { + "clusterOutboundIPAddressIPTags": "FirstPartyUsage:/NonProd", + "etcd": { + "kvName": "arohcp-etcd-int-1", + "kvSoftDelete": true + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 4, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_E8s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 12, + "minCount": 1, + "osDiskSizeGB": 128, + "vmSize": "Standard_D16s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "clusterServiceResourceId": "todo", + "rg": "hcp-underlay-westus3-mgmt-1", + "subscription": "hcp-westus3" + }, + "mgmtKeyVault": { + "name": "arohcp-mgmt-int-1", + "private": false, + "softDelete": false + }, + "miMockClientId": "f13a22ee-4f55-4d33-a614-a703e5501202", + "miMockPrincipalId": "d9356bcd-fb81-483e-9b5f-180c0aa27a16", + "monitoring": { + "grafanaAdminGroupPrincipalId": "2fdb57d4-3fd3-415d-b604-1d0e37a188fe", + "grafanaName": "arohcp-int", + "msiName": "aro-hcp-metrics-msi-int", + "workspaceName": "arohcp-int" + }, + "msiKeyVault": { + "name": "arohcp-msi-int-1", + "private": false, + "softDelete": false + }, + "ocpAcrName": "arohcpocpint", + "oidcStorageAccountName": "arohcpoidcintint", + "region": "westus3", + "regionRG": "westus3-shared-resources", + "serviceKeyVault": { + "name": "arohcp-svc-int", + "private": false, + "region": "westus3", + "rg": "hcp-underlay-westus3-svc", + "softDelete": false + }, + "svc": { + "aks": { + "clusterOutboundIPAddressIPTags": "FirstPartyUsage:/NonProd", + "etcd": { + "kvName": "arohcp-etcd-int", + "kvSoftDelete": true + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "istio": { + "ingressGatewayIPAddressIPTags": "FirstPartyUsage:/NonProd", + "ingressGatewayIPAddressName": "aro-hcp-istio-ingress", + "istioctlVersion": "1.24.1", + "tag": "prod-stable", + "targetVersion": "asm-1-23", + "versions": "asm-1-23" + }, + "rg": "hcp-underlay-westus3-svc", + "subscription": "hcp-westus3" + }, + "svcAcrName": "arohcpsvcint" +} diff --git a/config/public-cloud-personal-dev.json b/config/public-cloud-personal-dev.json index 20789f073..01fce48d9 100644 --- a/config/public-cloud-personal-dev.json +++ b/config/public-cloud-personal-dev.json @@ -1,86 +1,251 @@ { - "acrName": "arohcpdev", + "acrPullImageDigest": "sha256:1d18e828564dcd509a8551185808549bd8bfddec1fcc4a2783914dc2103bc2ca", "aksName": "aro-hcp-aks", - "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aro-hcp-devops", - "baseDnsZoneName": "hcp.osadev.cloud", - "baseDnsZoneRG": "global", - "clusterServiceAcrRG": "global", - "clusterServiceImageRepo": "app-sre/uhc-clusters-service", - "clusterServiceImageTag": "a23276d", - "clusterServicePostgresDeploy": false, - "clusterServicePostgresName": "cs-76fc6", - "clusterServicePostgresPrivate": false, - "cxKeyVaultName": "aro-hcp-cx-85fcc", - "cxKeyVaultPrivate": false, - "cxKeyVaultSoftDelete": false, - "externalDNSImageTag": "v0.14.2", + "armHelperClientId": "2c6ca254-36bd-43c8-a7a8-fe880bc2c489", + "armHelperFPAPrincipalId": "bc17c825-6cf8-40d0-8bd6-5536a993115e", + "aroDevopsMsiId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourceGroups/global/providers/Microsoft.ManagedIdentity/userAssignedIdentities/global-rollout-identity", + "backend": { + "imageTag": "" + }, + "clusterService": { + "acrRG": "global", + "azureOperatorsManagedIdentities": { + "cloudControllerManager": { + "roleName": "Azure Red Hat OpenShift Cloud Controller Manager - Dev" + }, + "cloudNetworkConfig": { + "roleName": "Azure Red Hat OpenShift Network Operator - Dev" + }, + "clusterApiAzure": { + "roleName": "Contributor" + }, + "controlPlane": { + "roleName": "Contributor" + }, + "diskCsiDriver": { + "roleName": "Azure Red Hat OpenShift Disk Storage Operator - Dev" + }, + "fileCsiDriver": { + "roleName": "Azure Red Hat OpenShift File Storage Operator - Dev" + }, + "imageRegistry": { + "roleName": "Azure Red Hat OpenShift Image Registry Operator - Dev" + }, + "ingress": { + "roleName": "Azure Red Hat OpenShift Cluster Ingress Operator - Dev" + } + }, + "imageRepo": "app-sre/uhc-clusters-service", + "imageTag": "dca2a71", + "k8s": { + "namespace": "cluster-service", + "serviceAccountName": "clusters-service" + }, + "managedIdentityName": "clusters-service", + "postgres": { + "deploy": false, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-cs-usw3tst", + "private": false + } + }, + "cxKeyVault": { + "name": "arohcp-cx-usw3tst-1", + "private": false, + "softDelete": false + }, + "dns": { + "baseDnsZoneRG": "global", + "cxParentZoneName": "hcp.osadev.cloud", + "parentZoneName": "osadev.cloud", + "regionalSubdomain": "usw3tst", + "svcParentZoneName": "hcpsvc.osadev.cloud" + }, + "extraVars": {}, "firstPartyAppClientId": "57e54810-3138-4f38-bd3b-29cb33f4c358", - "frontendCosmosDBDeploy": true, - "frontendCosmosDBDisableLocalAuth": true, - "frontendCosmosDBName": "aro-hcp-rp-76fc6", - "globalRG": "global", - "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", - "grafanaName": "aro-hcp-grafana-76fc6", - "hypershiftOperatorImageTag": "99a256f", - "imageSyncAcrRG": "global", - "imageSyncEnvironmentName": "aro-hcp-image-sync", - "imageSyncImageRepo": "image-sync/component-sync", - "imageSyncImageTag": "latest", - "imageSyncRG": "hcp-underlay-westus3-imagesync-dev", - "imageSyncRepositories": "registry.k8s.io/external-dns/external-dns,quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package", - "istioVersion": "['asm-1-22']", - "kubernetesVersion": "1.30.5", - "maestroCertDomain": "selfsigned.maestro.keyvault.azure.com", - "maestroConsumerName": "hcp-underlay-westus3-tst-mgmt-1", - "maestroEventGridMaxClientSessionsPerAuthName": "4", - "maestroEventgridName": "maestro-76fc6", - "maestroImageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", - "maestroImageTag": "ea066c250a002f0cc458711945165591bc9f6d3f", - "maestroKeyVaultName": "maestro-76fc6", - "maestroPostgresDeploy": false, - "maestroPostgresName": "maestro-76fc6", - "maestroPostgresPrivate": false, - "maestroPostgresServerStorageSizeGB": "32", - "maestroPostgresServerVersion": "15", - "maestroRestrictIstioIngress": true, - "managementClusterRG": "hcp-underlay-westus3-tst-mgmt-1", - "mgmtEtcdKVName": "aro-hcp-etcd-85fcc", - "mgmtEtcdKVSoftDelete": false, - "mgmtKeyVaultName": "aro-hcp-mgmt-85fcc", - "mgmtKeyVaultPrivate": false, - "mgmtKeyVaultSoftDelete": false, - "mgmtSystemAgentPoolMaxCount": 4, - "mgmtSystemAgentPoolMinCount": 1, - "mgmtSystemAgentPoolOsDiskSizeGB": 32, - "mgmtSystemAgentPoolVmSize": "Standard_D2s_v3", - "mgmtUserAgentPoolAzCount": 3, - "mgmtUserAgentPoolMaxCount": 6, - "mgmtUserAgentPoolMinCount": 1, - "mgmtUserAgentPoolOsDiskSizeGB": 100, - "mgmtUserAgentPoolVmSize": "Standard_D4s_v3", - "monitoringMsiName": "aro-hcp-metrics-msi-76fc6", - "monitoringWorkspaceName": "aro-hcp-monitor-76fc6", - "msiKeyVaultName": "aro-hcp-msi-85fcc", - "msiKeyVaultPrivate": false, - "msiKeyVaultSoftDelete": false, - "ocMirrorImageRepo": "image-sync/oc-mirror", - "ocMirrorImageTag": "7abc8af", + "frontend": { + "cert": { + "issuer": "Self", + "name": "frontend-cert-usw3tst" + }, + "cosmosDB": { + "deploy": true, + "disableLocalAuth": true, + "name": "arohcp-rp-usw3tst", + "private": false + }, + "imageTag": "" + }, + "global": { + "globalMSIName": "global-rollout-identity", + "region": "westus3", + "rg": "global", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "hypershift": { + "additionalInstallArg": "--tech-preview-no-upgrade", + "namespace": "hypershift" + }, + "hypershiftOperator": { + "imageTag": "9aca808" + }, + "imageSync": { + "acrRG": "global", + "componentSync": { + "enabled": true, + "imageRepo": "image-sync/component-sync", + "imageTag": "8d3c113", + "pullSecretName": "component-sync-pull-secret", + "repositories": "quay.io/acm-d/rhtap-hypershift-operator,quay.io/app-sre/uhc-clusters-service,quay.io/package-operator/package-operator-package,quay.io/package-operator/package-operator-manager", + "secrets": "quay.io:bearer-secret" + }, + "environmentName": "aro-hcp-image-sync", + "keyVault": { + "name": "arohcp-imagesync-dev", + "private": false, + "softDelete": false + }, + "ocMirror": { + "enabled": true, + "imageRepo": "image-sync/oc-mirror", + "imageTag": "0b3c08f", + "pullSecretName": "pull-secret" + }, + "rg": "hcp-underlay-westus3-imagesync-dev" + }, + "kvCertOfficerPrincipalId": "876db5bd-9a48-4bf7-a6a7-088437afa993", + "maestro": { + "certDomain": "selfsigned.maestro.keyvault.azure.com", + "consumerName": "hcp-underlay-usw3tst-mgmt-1", + "eventGrid": { + "maxClientSessionsPerAuthName": 4, + "name": "arohcp-maestro-usw3tst", + "private": false + }, + "imageBase": "quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro", + "imageTag": "c9a36e110a32c0c25aa5025cfe6d51af797e6d4b", + "postgres": { + "databaseName": "maestro", + "deploy": false, + "minTLSVersion": "TLSV1.2", + "name": "arohcp-maestro-usw3tst", + "private": false, + "serverStorageSizeGB": 32, + "serverVersion": "15" + }, + "restrictIstioIngress": true, + "server": { + "k8s": { + "namespace": "maestro", + "serviceAccountName": "maestro" + }, + "managedIdentityName": "maestro-server", + "mqttClientName": "maestro-server-usw3tst" + } + }, + "mce": { + "clcStateMetrics": { + "imageDigest": "bf5bb514e4d8af5e38317c3727d4cd9f90c22b293fe3e2367f9f0e179e0ee0c7" + } + }, + "mgmt": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-usw3tst-1", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 4, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 6, + "minCount": 1, + "osDiskSizeGB": 100, + "vmSize": "Standard_D4s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "clusterServiceResourceId": "/subscriptions/1d3378d3-5a3f-4712-85a1-2485495dfc4b/resourcegroups/hcp-underlay-usw3tst-svc/providers/Microsoft.ManagedIdentity/userAssignedIdentities/clusters-service", + "rg": "hcp-underlay-usw3tst-mgmt-1", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "mgmtKeyVault": { + "name": "arohcp-mgmt-usw3tst-1", + "private": false, + "softDelete": false + }, + "miMockClientId": "4daa4e3b-abc1-4f9c-812c-77bd37e06741", + "miMockPrincipalId": "a03f690c-4b2e-4eef-841e-f1904efe0e37", + "monitoring": { + "grafanaAdminGroupPrincipalId": "6b6d3adf-8476-4727-9812-20ffdef2b85c", + "grafanaName": "arohcp-dev", + "msiName": "aro-hcp-metrics-msi-usw3tst", + "workspaceName": "arohcp-usw3tst" + }, + "msiKeyVault": { + "name": "arohcp-msi-usw3tst-1", + "private": false, + "softDelete": false + }, "ocpAcrName": "arohcpocpdev", - "oidcStorageAccountName": "arohcpoidc76fc6", - "podSubnetPrefix": "10.128.64.0/18", + "oidcStorageAccountName": "arohcpoidcusw3tst", + "pko": { + "image": "arohcpsvcdev.azurecr.io/package-operator/package-operator-package", + "imageManager": "arohcpsvcdev.azurecr.io/package-operator/package-operator-manager", + "imageTag": "v1.15.0" + }, "region": "westus3", - "regionRG": "hcp-underlay-westus3-tst", - "regionalDNSSubdomain": "westus3-76fc6", - "serviceClusterRG": "hcp-underlay-westus3-tst-svc", - "serviceComponentAcrResourceGroups": "global", - "serviceKeyVaultName": "aro-hcp-dev-svc-kv", - "serviceKeyVaultPrivate": false, - "serviceKeyVaultRG": "global", - "serviceKeyVaultRegion": "westus3", - "serviceKeyVaultSoftDelete": true, - "subnetPrefix": "10.128.8.0/21", - "svcAcrName": "arohcpsvcdev", - "svcEtcdKVName": "aro-hcp-etcd-76fc6", - "svcEtcdKVSoftDelete": false, - "vnetAddressPrefix": "10.128.0.0/14" + "regionRG": "hcp-underlay-usw3tst", + "serviceKeyVault": { + "name": "aro-hcp-dev-svc-kv", + "private": false, + "region": "westus3", + "rg": "global", + "softDelete": true + }, + "svc": { + "aks": { + "clusterOutboundIPAddressIPTags": "", + "etcd": { + "kvName": "arohcp-etcd-usw3tst", + "kvSoftDelete": false + }, + "kubernetesVersion": "1.31.2", + "podSubnetPrefix": "10.128.64.0/18", + "subnetPrefix": "10.128.8.0/21", + "systemAgentPool": { + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "userAgentPool": { + "azCount": 3, + "maxCount": 3, + "minCount": 1, + "osDiskSizeGB": 32, + "vmSize": "Standard_D2s_v3" + }, + "vnetAddressPrefix": "10.128.0.0/14" + }, + "istio": { + "ingressGatewayIPAddressIPTags": "", + "ingressGatewayIPAddressName": "aro-hcp-istio-ingress", + "istioctlVersion": "1.23.1", + "tag": "prod-stable", + "targetVersion": "asm-1-23", + "versions": "asm-1-23" + }, + "rg": "hcp-underlay-usw3tst-svc", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)" + }, + "svcAcrName": "arohcpsvcdev" } diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 000000000..427501537 --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1,2 @@ +cluster.json +node_pool.json diff --git a/demo/01-register-sub.sh b/demo/01-register-sub.sh new file mode 100755 index 000000000..36924089f --- /dev/null +++ b/demo/01-register-sub.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source "$(dirname "$0")"/common.sh +source env_vars + +correlation_headers | curl -sSi -H @- -X PUT "localhost:8443/subscriptions/${SUBSCRIPTION_ID}?api-version=2.0" --json "{\"state\":\"Registered\", \"registrationDate\": \"now\", \"properties\": { \"tenantId\": \"${TENANT_ID}\"}}" diff --git a/demo/02-customer-infra.sh b/demo/02-customer-infra.sh new file mode 100755 index 000000000..26beb8ae6 --- /dev/null +++ b/demo/02-customer-infra.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source env_vars + +az group create --name "${CUSTOMER_RG_NAME}" --location ${LOCATION} + +az network nsg create -g ${CUSTOMER_RG_NAME} --name ${CUSTOMER_NSG} +NSG_ID=$(az network nsg list --query "[?name=='${CUSTOMER_NSG}'].id" -g ${CUSTOMER_RG_NAME} -o tsv) + +az network vnet create \ + --name ${CUSTOMER_VNET_NAME} \ + --resource-group ${CUSTOMER_RG_NAME} \ + --address-prefix 10.0.0.0/16 \ + --subnet-name ${CUSTOMER_VNET_SUBNET1} \ + --subnet-prefixes 10.0.0.0/24 \ + --nsg "${NSG_ID}" --location ${LOCATION} diff --git a/demo/03-create-cluster.sh b/demo/03-create-cluster.sh new file mode 100755 index 000000000..7e6ddc230 --- /dev/null +++ b/demo/03-create-cluster.sh @@ -0,0 +1,219 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source env_vars +source "$(dirname "$0")"/common.sh + +initialize_control_plane_identities_uamis_names() { + for operator_name in "${CONTROL_PLANE_OPERATORS_NAMES[@]}" + do + CONTROL_PLANE_IDENTITIES_UAMIS_NAMES+=("${USER}-${CLUSTER_NAME}-cp-${operator_name}-${OPERATORS_UAMIS_SUFFIX}") + done +} + +initialize_data_plane_identities_uamis_names() { + for operator_name in "${DATA_PLANE_OPERATORS_NAMES[@]}" + do + DATA_PLANE_IDENTITIES_UAMIS_NAMES+=("${USER}-${CLUSTER_NAME}-dp-${operator_name}-${OPERATORS_UAMIS_SUFFIX}") + done +} + +initialize_uamis_json_map() { + +UAMIS_JSON_MAP=$(cat << 'EOF' +{ + "controlPlaneOperators": {}, + "dataPlaneOperators": {}, + "serviceManagedIdentity": "" +} +EOF +) + +service_managed_identity_uami_resource_id="${UAMIS_RESOURCE_IDS_PREFIX}/${service_managed_identity_uami_name}" +UAMIS_JSON_MAP=$(echo -n "${UAMIS_JSON_MAP}" | jq \ + --arg service_managed_identity_resource_id "$service_managed_identity_uami_resource_id" \ + ' + .serviceManagedIdentity = $service_managed_identity_resource_id + ' +) + +for i in "${!CONTROL_PLANE_IDENTITIES_UAMIS_NAMES[@]}"; do + curr_operator_name="${CONTROL_PLANE_OPERATORS_NAMES[$i]}" + curr_uami_name="${CONTROL_PLANE_IDENTITIES_UAMIS_NAMES[$i]}" + curr_uami_resource_id="${UAMIS_RESOURCE_IDS_PREFIX}/${curr_uami_name}" + UAMIS_JSON_MAP=$(echo -n "${UAMIS_JSON_MAP}" | jq \ + --arg operator_name $curr_operator_name \ + --arg uami_resource_id $curr_uami_resource_id \ + ' + .controlPlaneOperators[$operator_name] = $uami_resource_id + ' + ) +done + +for i in "${!DATA_PLANE_IDENTITIES_UAMIS_NAMES[@]}"; do + curr_operator_name="${DATA_PLANE_OPERATORS_NAMES[$i]}" + curr_uami_name="${DATA_PLANE_IDENTITIES_UAMIS_NAMES[$i]}" + curr_uami_resource_id="${UAMIS_RESOURCE_IDS_PREFIX}/${curr_uami_name}" + UAMIS_JSON_MAP=$(echo -n ${UAMIS_JSON_MAP} | jq \ + --arg operator_name $curr_operator_name \ + --arg uami_resource_id $curr_uami_resource_id \ + ' + .dataPlaneOperators[$operator_name] = $uami_resource_id + ' + ) +done + +} + +initialize_uamis_identity_json_map() { + +IDENTITY_UAMIS_JSON_MAP=$(cat << 'EOF' +{ +} +EOF +) + +for i in "${!CONTROL_PLANE_IDENTITIES_UAMIS_NAMES[@]}"; do + curr_operator_name="${CONTROL_PLANE_OPERATORS_NAMES[$i]}" + curr_uami_name="${CONTROL_PLANE_IDENTITIES_UAMIS_NAMES[$i]}" + curr_uami_resource_id="${UAMIS_RESOURCE_IDS_PREFIX}/${curr_uami_name}" + IDENTITY_UAMIS_JSON_MAP=$(echo -n "${IDENTITY_UAMIS_JSON_MAP}" | jq \ + --arg operator_name $curr_operator_name \ + --arg uami_resource_id $curr_uami_resource_id \ + ' + .[$uami_resource_id] = {} + ' + ) +done + +} + +create_azure_managed_identities_for_cluster() { + for uami_name in "${CONTROL_PLANE_IDENTITIES_UAMIS_NAMES[@]}" + do + echo "creating azure user-assigned identity ${uami_name} in resource group ${CUSTOMER_RG_NAME}" + az identity create -n "${uami_name}" -g "${CUSTOMER_RG_NAME}" + echo "user-assigned identity ${uami_name} created" + done + + for uami_name in "${DATA_PLANE_IDENTITIES_UAMIS_NAMES[@]}" + do + echo "creating azure user-assigned identity ${uami_name} in resource group ${CUSTOMER_RG_NAME}" + az identity create -n "${uami_name}" -g "${CUSTOMER_RG_NAME}" + echo "user-assigned identity ${uami_name} created" + done + + echo "creating azure user-assigned identity ${service_managed_identity_uami_name} in resource group ${CUSTOMER_RG_NAME}" + az identity create -n ${service_managed_identity_uami_name} -g ${CUSTOMER_RG_NAME} + echo "user-assigned identity ${uami_name} created" +} + +arm_x_ms_identity_url_header() { + # Requests directly against the frontend + # need to send a X-Ms-Identity-Url HTTP + # header, which simulates what ARM performs. + # By default we set a dummy value, which is + # enough in the environments where a real + # Managed Identities Data Plane does not + # exist like in the development or integration + # environments. The default can be overwritten + # by providing the environment variable + # ARM_X_MS_IDENTITY_URL when running the script. + : ${ARM_X_MS_IDENTITY_URL:="https://dummyhost.identity.azure.net"} + echo "X-Ms-Identity-Url: ${ARM_X_MS_IDENTITY_URL}" +} + +main() { + NSG_ID=$(az network nsg list -g ${CUSTOMER_RG_NAME} --query "[?name=='${CUSTOMER_NSG}'].id" -o tsv) + SUBNET_ID=$(az network vnet subnet show -g ${CUSTOMER_RG_NAME} --vnet-name ${CUSTOMER_VNET_NAME} --name ${CUSTOMER_VNET_SUBNET1} --query id -o tsv) + + UAMIS_RESOURCE_IDS_PREFIX="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.ManagedIdentity/userAssignedIdentities" + + # A suffix that will be appended to all the + # user-assigned managed identities names that + # will be created for the cluster. + # By default we generate a 6 characters random + # suffix for the azure user-assigned managed + # identites to be used by the cluster to be created. + # The default can be overwritten by providing the + # environment variable OPERATORS_UAMIS_SUFFIX + # when running the script. + : OPERATORS_UAMIS_SUFFIX=${OPERATORS_UAMIS_SUFFIX:=$(openssl rand -hex 3)} + + # control plane operator names required for OCP 4.17. + # TODO in the future the information of the required + # identities for a given OCP version will be provided + # via API. + CONTROL_PLANE_OPERATORS_NAMES=( + "cluster-api-azure" + "control-plane" + "cloud-controller-manager" + "ingress" + "disk-csi-driver" + "file-csi-driver" + "image-registry" + "cloud-network-config" + ) + + # data plane operator names required for OCP 4.17. + # TODO in the future the information of the required + # identities for a given OCP version will be provided + # via API. + DATA_PLANE_OPERATORS_NAMES=( + "disk-csi-driver" + "file-csi-driver" + "image-registry" + ) + + # We declare and initialize the control plane + # user assigned identities names to the + # empty array. + CONTROL_PLANE_IDENTITIES_UAMIS_NAMES=() + initialize_control_plane_identities_uamis_names + + # We declare and initialize the data plane + # user assigned identities names to the + # empty array. + DATA_PLANE_IDENTITIES_UAMIS_NAMES=() + initialize_data_plane_identities_uamis_names + + # We define the service managed identity + # user assigned identity. + service_managed_identity_uami_name="${USER}-${CLUSTER_NAME}-service-managed-identity-${OPERATORS_UAMIS_SUFFIX}" + + UAMIS_JSON_MAP="" + initialize_uamis_json_map + IDENTITY_UAMIS_JSON_MAP="" + initialize_uamis_identity_json_map + + CURRENT_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") + + CLUSTER_TMPL_FILE="cluster.tmpl.json" + CLUSTER_FILE="cluster.json" + + create_azure_managed_identities_for_cluster + + jq \ + --arg managed_rg "$MANAGED_RESOURCE_GROUP" \ + --arg subnet_id "$SUBNET_ID" \ + --arg nsg_id "$NSG_ID" \ + --argjson uamis_json_map "$UAMIS_JSON_MAP" \ + --argjson identity_uamis_json_map "$IDENTITY_UAMIS_JSON_MAP" \ + ' + .properties.spec.platform.managedResourceGroup = $managed_rg | + .properties.spec.platform.subnetId = $subnet_id | + .properties.spec.platform.networkSecurityGroupId = $nsg_id | + .properties.spec.platform.operatorsAuthentication.userAssignedIdentities = $uamis_json_map | + .identity.userAssignedIdentities = $identity_uamis_json_map + ' "${CLUSTER_TMPL_FILE}" > ${CLUSTER_FILE} + + (arm_system_data_header; correlation_headers; arm_x_ms_identity_url_header) | curl -sSi -X PUT "localhost:8443/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.RedHatOpenshift/hcpOpenShiftClusters/${CLUSTER_NAME}?api-version=2024-06-10-preview" \ + --header @- \ + --json @${CLUSTER_FILE} +} + +# Call to the `main` function in the script +main "$@" diff --git a/demo/04-create-nodepool.sh b/demo/04-create-nodepool.sh new file mode 100755 index 000000000..75c2c6cbe --- /dev/null +++ b/demo/04-create-nodepool.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source env_vars +source "$(dirname "$0")"/common.sh + +NODEPOOL_TMPL_FILE="node_pool.tmpl.json" +NODEPOOL_FILE="node_pool.json" + +SUBNET_ID=$(az network vnet subnet show -g ${CUSTOMER_RG_NAME} --vnet-name ${CUSTOMER_VNET_NAME} --name ${CUSTOMER_VNET_SUBNET1} --query id -o tsv) + +jq \ + --arg subnet_id "$SUBNET_ID" \ + '.properties.spec.platform.subnetId = $subnet_id' "${NODEPOOL_TMPL_FILE}" > ${NODEPOOL_FILE} + +(arm_system_data_header; correlation_headers) | curl -sSi -X PUT "localhost:8443/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.RedHatOpenshift/hcpOpenShiftClusters/${CLUSTER_NAME}/nodePools/${NP_NAME}?api-version=2024-06-10-preview" \ + --header @- \ + --json @${NODEPOOL_FILE} diff --git a/demo/05-delete-cluster.sh b/demo/05-delete-cluster.sh new file mode 100755 index 000000000..0d7891190 --- /dev/null +++ b/demo/05-delete-cluster.sh @@ -0,0 +1,115 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +source env_vars +source "$(dirname "$0")"/common.sh + +get_existing_cluster_payload() { + EXISTING_CLUSTER_PAYLOAD=$(curl -sS "${FRONTEND_HOST}:${FRONTEND_PORT}${CLUSTER_RESOURCE_ID}?${FRONTEND_API_VERSION_QUERY_PARAM}") +} + +delete_managed_identities_from_cluster() { + UAMIS_JSON_MAP=$(echo ${EXISTING_CLUSTER_PAYLOAD} | jq '.properties.spec.platform.operatorsAuthentication.userAssignedIdentities') + + CP_UAMIS_ENTRIES=$(echo ${UAMIS_JSON_MAP}| jq -c '.controlPlaneOperators | to_entries | .[]') + while read cp_uami_entry; do + cp_operator_name=$(echo -n "${cp_uami_entry}" | jq .key) + cp_operator_mi=$(echo -n "${cp_uami_entry}" | jq .value -r) + echo "deleting $cp_operator_name operator's managed identity $cp_operator_mi" + az identity delete --ids $cp_operator_mi + echo "deleted managed identity $cp_operator_mi" + done <<< "${CP_UAMIS_ENTRIES}" + + DP_UAMIS_ENTRIES=$(echo ${UAMIS_JSON_MAP} | jq -c '.dataPlaneOperators | to_entries | .[]') + while read dp_uami_entry; do + dp_operator_name=$(echo -n "${dp_uami_entry}" | jq .key) + dp_operator_mi=$(echo -n "${dp_uami_entry}" | jq .value -r) + echo "deleting $dp_operator_name operator's managed identity $dp_operator_mi" + az identity delete --ids $dp_operator_mi + echo "deleted managed identity $dp_operator_mi" + done <<< "${DP_UAMIS_ENTRIES}" + + SMI_UAMI_ENTRY=$(echo ${UAMIS_JSON_MAP} | jq .serviceManagedIdentity -r) + echo "deleting service managed identity ${SMI_UAMI_ENTRY}" + az identity delete --ids ${SMI_UAMI_ENTRY} + echo "deleted service managed identity ${SMI_UAMI_ENTRY}" +} + +delete_cluster() { + echo "deleting cluster ${CLUSTER_RESOURCE_ID}" + correlation_headers | curl -sSi -H @- -X DELETE "${FRONTEND_HOST}:${FRONTEND_PORT}${CLUSTER_RESOURCE_ID}?${FRONTEND_API_VERSION_QUERY_PARAM}" + if [ "${WAIT_FOR_CLUSTER_DELETION}" -eq "0" ]; then + echo "wait for cluster deletion disabled. Continuing" + return + fi + + echo "waiting for cluster to be fully deleted ..." + SLEEP_DURATION_SECONDS=10 + while true ; do + CLUSTER_GET_RESP=$(curl -sS "${FRONTEND_HOST}:${FRONTEND_PORT}${CLUSTER_RESOURCE_ID}?${FRONTEND_API_VERSION_QUERY_PARAM}") + CLUSTER_GET_RESP_PAYLOAD=$(echo ${CLUSTER_GET_RESP} | jq -r .) + if [ "$?" -ne "0" ]; then + echo "HTTP GET ${CLUSTER_RESOURCE_ID} returned invalid json:" + echo "${CLUSTER_GET_RESP_PAYLOAD}" + exit 1 + fi + RESP_ID_ATTR=$(echo ${CLUSTER_GET_RESP_PAYLOAD} | jq -r '. | .id') + if [ "${RESP_ID_ATTR}" == "null" ]; then + RESP_ERR_CODE_ATTR=$(echo ${CLUSTER_GET_RESP_PAYLOAD} | jq -r '.error.code') + if [ "${RESP_ERR_CODE_ATTR}" == "ResourceNotFound" ]; then + # Cluster has been fully deleted so we return + echo "deleted cluster ${CLUSTER_RESOURCE_ID}" + return + else + echo "unexpected response when performing HTTP GET ${CLUSTER_RESOURCE_ID}": + echo "${CLUSTER_GET_RESP_PAYLOAD}" + exit 1 + fi + fi + + if [ "${RESP_ID_ATTR}" != "${CLUSTER_RESOURCE_ID}" ]; then + echo "unexpected cluster resource id when performing HTTP GET ${CLUSTER_RESOURCE_ID}": + echo "${RESP_ID_ATTR}" + exit 1 + fi + + echo "cluster not fully deleted yet. waiting for ${SLEEP_DURATION_SECONDS} seconds ..." + sleep ${SLEEP_DURATION_SECONDS} + + done +} + +main() { + CLUSTER_RESOURCE_ID="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.RedHatOpenshift/hcpOpenShiftClusters/${CLUSTER_NAME}" + FRONTEND_API_VERSION_QUERY_PARAM="api-version=2024-06-10-preview" + FRONTEND_HOST="localhost" + FRONTEND_PORT="8443" + + EXISTING_CLUSTER_PAYLOAD="" + get_existing_cluster_payload + if [ -z "${EXISTING_CLUSTER_PAYLOAD}" ]; then + echo "cluster with resource id ${CLUSTER_RESOURCE_ID} not found" + exit 0 + fi + + # WAIT_FOR_CLUSTER_DELETION controls whether the script + # should wait until the cluster is fully deleted before + # continuing with the managed identities deletion. + # By default it is set to 1, which signals + # that the script should wait until the cluster is + # fully deleted before continuing. + # To disable the wait set it to 0. However, this means + # that the managed identities will be deleted while the + # cluster is being deleted but still exists, which can + # cause unexpected behavior / consequences, so use + # with caution. + WAIT_FOR_CLUSTER_DELETION=${WAIT_FOR_CLUSTER_DELETION:=1} + + delete_cluster + delete_managed_identities_from_cluster +} + +main "$@" diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 000000000..fda2910ac --- /dev/null +++ b/demo/README.md @@ -0,0 +1,148 @@ +# Create an HCP + +## Prepare + +* have a `KUBECONFIG` for a SC and MC, e.g. for the [integrated DEV environment](../dev-infrastructure/docs/development-setup.md#access-integrated-dev-environment) +* port-forward RP running on SC: `kubectl port-forward -n aro-hcp svc/aro-hcp-frontend 8443:8443` +* (optional but useful) port-forward CS running on SC: `kubectl port-forward -n cluster-service svc/clusters-service 8001:8000` +* (optional but useful) port-forward Maestro running on SC: `kubectl port-forward -n maestro svc/maestro 8002:8000` + +## Register the subscription with the RP + +The RP needs to know the subscription in order to be able to create cluters in it. +Run the following command `once` to make the subscription known to the RP. + +```bash +./01-register-sub.sh +``` + +## Create VNET and NSG + +We provision HCPs with BYO VNET, so we need to create the VNET, Subnet and NSG upfront. + +```bash +./02-customer-infra.sh +``` + +The resources are created in a resourcegroup named `$USER-net-rg`. + +## Create cluster + +Create an HCP by sending a request to the port-forwarded RP. You can find a payload template in `cluster.tmpl.json`. +To fill that template with some user specific defaults and send it to the RP, run the following command: + +```bash +./03-create-cluster.sh +``` + +This creates an HCP named `$USER`. If you want to use a different name, run + +```bash +CLUSTER_NAME=abc ./03-create-cluster.sh +``` + +Observe the cluster creation with `./query-cluster-rp.sh` until `properties.provisioningState` is (hopefully) `Succeeded`. +`properties.spec.api.url` holds the URL to the API server of the HCP. + +See [Get the kubeconfig for an HCP](#get-the-kubeconfig-for-an-hcp) on how to get the kubeconfig for the HCP. + +## Create nodepool + +```bash +./04-create-nodepool.sh +``` + +This creates a nodepool named `np-1` for the previously created cluster. + +To check progress on + +* the RP, run `./query-nodepool-rp.sh` +* the MC, run `kubectl get nodepool -A` and `kubectl get azuremachine -A` +* within the HCP, run `kubectl get nodes` while using your HCP kubeconfig + +## Delete cluster + +```bash +./05-delete-cluster.sh +``` + +## Observe and debug + +### Check RP pod logs + +```bash +kubectl logs deployment/aro-hcp-frontend -c aro-hcp-frontend -n aro-hcp -f +kubectl logs deployment/aro-hcp-backend -c aro-hcp-backend -n aro-hcp -f +``` + +### Check cluster state in RP + +```bash +./query-cluster-rp.sh +``` + +### Check CS pod logs + +```bash +kubectl logs deployment/clusters-service -c service -f +``` + +### Check cluster state in CS + +```bash +curl localhost:8001/api/clusters_mgmt/v1/clusters | jq +``` + +### Check Maestro logs + +```bash +kubectl logs deployment/maestro -n maestro -c service -f +``` + +### Check MC consumer registration in Maestro + +```bash +curl localhost:8002/api/maestro/v1/consumers | jq +``` + +### Check MC resource bundles in Maestro + +```bash +curl localhost:8002/api/maestro/v1/resource-bundles | jq +``` + +### Check for manifestwork on MC + +```bash +CS_CLUSTER_ID=$(curl localhost:8001/api/clusters_mgmt/v1/clusters | jq .items[0].id -r) +kubectl get manifestwork -n local-cluster | grep ^${CS_CLUSTER_ID} +``` + +### Check for `HostedCluster` CR on MC + +```bash +kubectl get hostedcluster -A +``` + +### Check for namespaces on MC + +```bash +kubectl get ns | grep "ocm.*${CS_CLUSTER_ID}" +``` + +### Two namespaces should show up + +* `ocm-xxx-${CS_CLUSTER_ID}` - contains Hypershift CRs and secrets for an HCP +* `ocm-xxx-${CS_CLUSTER_ID}-${CLUSTER_NAME}` - contains the hosted controlplane (e.g. pods, secrets, ...) + +### Get the kubeconfig for an HCP + +```bash +kubectl get secret -n ocm-aro-hcp-dev-${CS_CLUSTER_ID} ${CLUSTER_NAME}-admin-kubeconfig -o json | jq .data.kubeconfig -r | base64 -d > my.kubeconfig +``` + +### Check nodepool on RP + +```bash +./query-nodepool-rp.sh +``` diff --git a/demo/cluster.tmpl.json b/demo/cluster.tmpl.json new file mode 100644 index 000000000..245a9a99e --- /dev/null +++ b/demo/cluster.tmpl.json @@ -0,0 +1,43 @@ +{ + "properties": { + "spec": { + "version": { + "id": "openshift-v4.17.0", + "channelGroup": "stable" + }, + "dns": {}, + "network": { + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16", + "machineCidr": "10.0.0.0/16", + "hostPrefix": 23 + }, + "console": {}, + "api": { + "visibility": "public" + }, + "proxy": {}, + "platform": { + "managedResourceGroup": "$managed-resource-group", + "subnetId": "/subscriptions/$sub/resourceGroups/$customer-rg/providers/Microsoft.Network/virtualNetworks/customer-vnet/subnets/customer-subnet-1", + "outboundType": "loadBalancer", + "networkSecurityGroupId": "/subscriptions/$sub/resourceGroups/$customer-rg/providers/Microsoft.Network/networkSecurityGroups/customer-nsg", + "operatorsAuthentication": { + "userAssignedIdentities": { + "controlPlaneOperators": {"example_operator": "example_resource_id"}, + "dataPlaneOperators": {"example_operator": "example_resource_id"}, + "serviceManagedIdentity": "example_resource_id" + } + } + }, + "externalAuth": {} + } + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "example_resource_id": {} + } + } +} diff --git a/demo/common.sh b/demo/common.sh new file mode 100644 index 000000000..3c6d302ff --- /dev/null +++ b/demo/common.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +arm_system_data_header() { + echo "X-Ms-Arm-Resource-System-Data: {\"createdBy\": \"${USER}\", \"createdByType\": \"User\", \"createdAt\": \"$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")\"}" +} + +correlation_headers() { + local HEADERS=( ) + if [ -n "$(which uuidgen 2> /dev/null)" ]; then + HEADERS+=( "X-Ms-Correlation-Request-Id: $(uuidgen)" ) + HEADERS+=( "X-Ms-Client-Request-Id: $(uuidgen)" ) + HEADERS+=( "X-Ms-Return-Client-Request-Id: true" ) + fi + printf '%s\n' "${HEADERS[@]}" +} diff --git a/demo/env_vars b/demo/env_vars new file mode 100644 index 000000000..e54f76f14 --- /dev/null +++ b/demo/env_vars @@ -0,0 +1,22 @@ +#!/bin/bash + + +if [ -z "${CUSTOMER_RG_NAME:-}" ]; then + export CUSTOMER_RG_NAME="$USER-net-rg" +fi +export CUSTOMER_VNET_NAME="customer-vnet" +export CUSTOMER_VNET_SUBNET1="customer-subnet-1" +export CUSTOMER_NSG="customer-nsg" +if [ -z "${LOCATION:-}" ]; then + export LOCATION="westus3" +fi +export SUBSCRIPTION_ID=$(az account show --query id -o tsv) +export TENANT_ID=$(az account show --query tenantId -o tsv) +if [ -z "${CLUSTER_NAME:-}" ]; then + export CLUSTER_NAME="$USER" +fi +MANAGED_RESOURCE_GROUP="$CLUSTER_NAME-rg" + +if [ -z "${NP_NAME:-}" ]; then + export NP_NAME="np-1" +fi diff --git a/demo/node_pool.tmpl.json b/demo/node_pool.tmpl.json new file mode 100644 index 000000000..def911ab7 --- /dev/null +++ b/demo/node_pool.tmpl.json @@ -0,0 +1,17 @@ +{ + "properties": { + "spec": { + "version": { + "id": "openshift-v4.17.0", + "channelGroup": "stable" + }, + "platform": { + "subnetId": "/subscriptions/$sub/resourceGroups/$customer-rg/providers/Microsoft.Network/virtualNetworks/customer-vnet/subnets/customer-subnet-1", + "vmSize": "Standard_D8s_v3", + "diskSizeGiB": 30, + "diskStorageAccountType": "StandardSSD_LRS" + }, + "replicas": 2 + } + } +} diff --git a/demo/query-cluster-rp.sh b/demo/query-cluster-rp.sh new file mode 100755 index 000000000..547c37d2b --- /dev/null +++ b/demo/query-cluster-rp.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +source env_vars +source "$(dirname "$0")"/common.sh + +SUBSCRIPTION_ID=$(az account show --query id -o tsv) + +correlation_headers | curl -s -H @- "localhost:8443/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.RedHatOpenshift/hcpOpenShiftClusters/${CLUSTER_NAME}?api-version=2024-06-10-preview" | jq diff --git a/demo/query-nodepool-rp.sh b/demo/query-nodepool-rp.sh new file mode 100755 index 000000000..555e3c399 --- /dev/null +++ b/demo/query-nodepool-rp.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +source env_vars +source "$(dirname "$0")"/common.sh + +SUBSCRIPTION_ID=$(az account show --query id -o tsv) + +correlation_headers | curl -s -H @- "localhost:8443/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${CUSTOMER_RG_NAME}/providers/Microsoft.RedHatOpenshift/hcpOpenShiftClusters/${CLUSTER_NAME}/nodePools/${NP_NAME}?api-version=2024-06-10-preview" | jq diff --git a/dev-infrastructure/.gitignore b/dev-infrastructure/.gitignore index a4c761b68..58b2a7d87 100644 --- a/dev-infrastructure/.gitignore +++ b/dev-infrastructure/.gitignore @@ -1,5 +1,7 @@ configurations/mgmt-cluster.bicepparam +configurations/mgmt-infra.bicepparam configurations/svc-cluster.bicepparam +configurations/svc-infra.bicepparam configurations/region.bicepparam configurations/metrics.bicepparam configurations/acr-svc.bicepparam @@ -7,4 +9,12 @@ configurations/acr-ocp.bicepparam configurations/image-sync.bicepparam configurations/dev-role-assignments.bicepparam configurations/cs-integ-msi.bicepparam +configurations/output-region.bicepparam +configurations/output-global.bicepparam +configurations/output-svc.bicepparam +configurations/mock-identities.bicepparam +configurations/global-acr.bicepparam +configurations/global-infra.bicepparam config.mk + +istio-* diff --git a/dev-infrastructure/Makefile b/dev-infrastructure/Makefile index 29a5adda5..3c234d7a9 100644 --- a/dev-infrastructure/Makefile +++ b/dev-infrastructure/Makefile @@ -27,23 +27,18 @@ list: @grep '^[^#[:space:]].*:' Makefile .PHONY: list -fmt: - set -e; \ - FILES="$$(find . -type f -name "*.bicep*" ! -name "*.tmpl.bicepparam")"; \ - for file in $$FILES; do \ - echo "az bicep format --file $${file}"; \ - az bicep format --file $$file; \ - done -.PHONY: fmt - -lint: - set -e; \ - FILES="$$(find . -type f -name "*.bicep*" ! -name "*.tmpl.bicepparam")"; \ - for file in $$FILES; do \ - echo "az bicep lint --file $${file}"; \ - az bicep lint --file $$file; \ - done -.PHONY: lint +modules := $(wildcard ./templates/*.bicep) +parameters := $(filter-out $(wildcard ./templates/*.tmpl.bicepparam),$(wildcard ./templates/*.bicepparam)) + +fmt: $(modules:.bicep=.bicep.fmt) $(parameters:.bicepparam=.biceparam.fmt) + +lint: $(modules:.bicep=.bicep.lint) $(parameters:.bicepparam=.biceparam.lint) + +%.bicep.fmt %.bicepparam.fmt: + az bicep format --file $(basename $@) + +%.bicep.lint %.bicepparam.lint: + az bicep lint --file $(basename $@) feature-registration: # hardcoded to eastus as this is a subscription deployment, not a resource group @az deployment sub create \ @@ -74,10 +69,6 @@ create-mock-identities: SUBSCRIPTION_ID=$(shell az account show --query id --output tsv) \ ./scripts/create-sp-for-rbac.sh - app_id=$(shell az ad sp list --display-name aro-dev-first-party --query "[].appId" -o tsv) && \ - subscription_id=$(shell az account show --query id --output tsv) && \ - az role assignment create --role Contributor --assignee $${app_id} --scope "/subscriptions/$${subscription_id}" - APPLICATION_NAME=aro-dev-arm-helper \ KEY_VAULT_NAME=aro-hcp-dev-svc-kv \ CERTIFICATE_NAME=armHelperCert \ @@ -88,7 +79,7 @@ create-mock-identities: APPLICATION_NAME=aro-dev-msi-mock \ KEY_VAULT_NAME=aro-hcp-dev-svc-kv \ CERTIFICATE_NAME=msiMockCert \ - ROLE_DEFINITION_NAME=Contributor \ + ROLE_DEFINITION_NAME=dev-msi-mock \ SUBSCRIPTION_ID=$(shell az account show --query id --output tsv) \ ./scripts/create-sp-for-rbac.sh .PHONY: create-mock-identities @@ -98,10 +89,11 @@ create-mock-identities: # imagesync.rg: - @if [ "$$(az group exists --name $(IMAGE_SYNC_RESOURCEGROUP))" = "false" ]; then \ + @if [ "$$(az group exists --name $(IMAGE_SYNC_RESOURCEGROUP) --output json)" = "false" ]; then \ az group create \ --name $(IMAGE_SYNC_RESOURCEGROUP) \ --location $(REGION) \ + --tags persist=$(PERSIST) \ --output none; \ fi .PHONY: imagesyncRg @@ -130,7 +122,7 @@ imagesync.what-if: imagesync.rg imagesync.wait .PHONY: imagesync.what-if imagesync.clean: - @if [ "$$(az group exists --name $(IMAGE_SYNC_RESOURCEGROUP))" = "true" ]; then \ + @if [ "$$(az group exists --name $(IMAGE_SYNC_RESOURCEGROUP) --output json)" = "true" ]; then \ az group delete -g $(IMAGE_SYNC_RESOURCEGROUP); \ fi .PHONY: imagesync.clean @@ -140,7 +132,7 @@ imagesync.clean: # regional.rg: - @if [ "$$(az group exists --name $(REGIONAL_RESOURCEGROUP))" = "false" ]; then \ + @if [ "$$(az group exists --name $(REGIONAL_RESOURCEGROUP) --output json)" = "false" ]; then \ az group create \ --name $(REGIONAL_RESOURCEGROUP) \ --location $(REGION) \ @@ -166,7 +158,8 @@ region: region.wait regional.rg .PHONY: region region.clean: - @if [ "$$(az group exists --name $(REGIONAL_RESOURCEGROUP))" = "true" ]; then \ + @if [ "$$(az group exists --name $(REGIONAL_RESOURCEGROUP) --output json)" = "true" ]; then \ + echo "Will delete Azure resource group $(REGIONAL_RESOURCEGROUP)"; \ az group delete -g $(REGIONAL_RESOURCEGROUP); \ fi .PHONY: region.clean @@ -185,7 +178,7 @@ region.what-if: region.wait regional.rg # svc.rg: - @if [ "$$(az group exists --name $(SVC_RESOURCEGROUP))" = "false" ]; then \ + @if [ "$$(az group exists --name $(SVC_RESOURCEGROUP) --output json)" = "false" ]; then \ az group create \ --name $(SVC_RESOURCEGROUP) \ --location $(REGION) \ @@ -193,12 +186,19 @@ svc.rg: fi .PHONY: svc.rg -svc.wait: - @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) $(SVC_RG_DEPLOYMENT_NAME) -.PHONY: svc.wait - -svc: svc.wait svc.rg +svc: svc.rg @scripts/cleanup-orphaned-rolebindings.sh $(SVC_RESOURCEGROUP) + @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) $(SVC_RG_DEPLOYMENT_NAME)-infra + az deployment group create \ + --name $(SVC_RG_DEPLOYMENT_NAME)-infra \ + --resource-group $(SVC_RESOURCEGROUP) \ + --template-file templates/svc-infra.bicep \ + $(PROMPT_TO_CONFIRM) \ + --parameters \ + configurations/svc-infra.bicepparam \ + --parameters \ + persist=${PERSIST} + @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) $(SVC_RG_DEPLOYMENT_NAME) az deployment group create \ --name $(SVC_RG_DEPLOYMENT_NAME) \ --resource-group $(SVC_RESOURCEGROUP) \ @@ -210,17 +210,15 @@ svc: svc.wait svc.rg persist=${PERSIST} .PHONY: svc -svc.enable-aks-metrics: - @if [ "$$(az aks show --resource-group $(SVC_RESOURCEGROUP) --name ${AKS_NAME} --query 'azureMonitorProfile.metrics.enabled' -o tsv)" = "true" ]; then \ - echo "Azure Monitor metrics are already enabled."; \ - else \ - az aks update --enable-azure-monitor-metrics \ - --resource-group $(SVC_RESOURCEGROUP) \ - --name ${AKS_NAME} \ - --azure-monitor-workspace-resource-id $$(az deployment group show --resource-group $(REGIONAL_RESOURCEGROUP) --name metrics-infra --output tsv --query properties.outputs.monitorId.value) \ - --grafana-resource-id $$(az deployment group show --resource-group $(REGIONAL_RESOURCEGROUP) --name metrics-infra --output tsv --query properties.outputs.grafanaId.value); \ - fi -.PHONY: svc.enable-aks-metrics +svc.istio: svc.rg svc.aks.admin-access svc.aks.kubeconfig + @KUBECONFIG=$(SVC_KUBECONFIG_FILE) \ + TARGET_VERSION=$(ISTIO_TARGET_VERSION) \ + ISTIOCTL_VERSION=$(ISTIOCTL_VERSION) \ + ISTIO_INGRESS_GATEWAY_IP_ADDRESS_NAME=$(ISTIO_INGRESS_GATEWAY_IP_ADDRESS_NAME) \ + TAG=$(ISTIO_TAG) \ + SVC_RESOURCEGROUP=$(SVC_RESOURCEGROUP) \ + scripts/istio.sh +.PHONY: svc.istio svc.cs-pr-check-msi: svc.rg @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) cs-integ-msi @@ -246,10 +244,37 @@ svc.aks.kubeconfigfile: @echo ${SVC_KUBECONFIG_FILE} .PHONY: svc.aks.kubeconfigfile -svc.init: region svc svc.aks.admin-access svc.aks.kubeconfig metrics-infra svc.enable-aks-metrics +svc.oidc.storage.permissions: + @USER_TYPE=$(shell az account show -o json | jq -r '.user.type') && \ + if [ "$${USER_TYPE}" = "user" ]; then \ + STORAGEACCOUNTID=$(shell az storage account show -n ${OIDC_STORAGE_ACCOUNT} -g ${SVC_RESOURCEGROUP} --query id -o tsv) && \ + az role assignment create \ + --role "Storage Blob Data Contributor" \ + --assignee ${PRINCIPAL_ID} \ + --scope "$${STORAGEACCOUNTID}" \ + --only-show-errors; \ + fi +.PHONY: svc.oidc.storage.permissions + +svc.kv.permission: + @scripts/kv-permissions.sh $(PRINCIPAL_ID) $(SVC_KV_RESOURCEGROUP) $(SVC_KV_NAME) +.PHONY: svc.kv.permission + +svc.dev.permissions: svc.oidc.storage.permissions svc.kv.permission +.PHONY: svc.dev.permissions + +svc.init: region metrics-infra svc svc.aks.admin-access svc.aks.kubeconfig svc.istio svc.dev.permissions .PHONY: svc.init svc.what-if: svc.rg + @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) $(SVC_RG_DEPLOYMENT_NAME)-infra + az deployment group what-if \ + --name $(SVC_RG_DEPLOYMENT_NAME)-infra \ + --resource-group $(SVC_RESOURCEGROUP) \ + --template-file templates/svc-infra.bicep \ + --parameters \ + configurations/svc-infra.bicepparam + @./ensure-no-running-deployment.sh $(SVC_RESOURCEGROUP) $(SVC_RG_DEPLOYMENT_NAME) az deployment group what-if \ --name $(SVC_RG_DEPLOYMENT_NAME) \ --resource-group $(SVC_RESOURCEGROUP) \ @@ -269,7 +294,8 @@ svc.dev-role-assignments: .PHONY: svc.dev-role-assignments svc.clean: - @if [ "$$(az group exists --name $(SVC_RESOURCEGROUP))" = "true" ]; then \ + @if [ "$$(az group exists --name $(SVC_RESOURCEGROUP) --output json)" = "true" ]; then \ + echo "Will delete Azure resource group $(SVC_RESOURCEGROUP)"; \ az group delete -g $(SVC_RESOURCEGROUP); \ fi .PHONY: svc.clean @@ -279,7 +305,7 @@ svc.clean: # mgmt.rg: - @if [ "$$(az group exists --name $(MGMT_RESOURCEGROUP))" = "false" ]; then \ + @if [ "$$(az group exists --name $(MGMT_RESOURCEGROUP) --output json)" = "false" ]; then \ az group create \ --name $(MGMT_RESOURCEGROUP) \ --location $(REGION) \ @@ -292,6 +318,16 @@ mgmt.wait: .PHONY: mgmt.wait mgmt: mgmt.wait mgmt.rg + @./ensure-no-running-deployment.sh $(MGMT_RESOURCEGROUP) $(MGMT_RESOURCEGROUP)-infra + az deployment group create \ + --name $(MGMT_RESOURCEGROUP)-infra \ + --resource-group $(MGMT_RESOURCEGROUP) \ + --template-file templates/mgmt-infra.bicep \ + $(PROMPT_TO_CONFIRM) \ + --parameters \ + configurations/mgmt-infra.bicepparam \ + --parameters \ + persist=${PERSIST} @scripts/cleanup-orphaned-rolebindings.sh $(MGMT_RESOURCEGROUP) az deployment group create \ --name $(MGMG_RG_DEPLOYMENT_NAME) \ @@ -304,23 +340,11 @@ mgmt: mgmt.wait mgmt.rg persist=${PERSIST} .PHONY: mgmt -mgmt.enable-aks-metrics: - @if [ "$$(az aks show --resource-group $(MGMT_RESOURCEGROUP) --name ${AKS_NAME} --query 'azureMonitorProfile.metrics.enabled' -o tsv)" = "true" ]; then \ - echo "Azure Monitor metrics are already enabled."; \ - else \ - az aks update --enable-azure-monitor-metrics \ - --resource-group $(MGMT_RESOURCEGROUP) \ - --name ${AKS_NAME} \ - --azure-monitor-workspace-resource-id $$(az deployment group show --resource-group $(REGIONAL_RESOURCEGROUP) --name metrics-infra --output tsv --query properties.outputs.monitorId.value) \ - --grafana-resource-id $$(az deployment group show --resource-group $(REGIONAL_RESOURCEGROUP) --name metrics-infra --output tsv --query properties.outputs.grafanaId.value); \ - fi -.PHONY: mgmt.enable-aks-metrics - mgmt.aks.admin-access: @scripts/aks-admin-access.sh $(MGMT_RESOURCEGROUP) $(PRINCIPAL_ID) .PHONY: mgmt.aks.admin-access -mgmt.aks.kubeconfig: mgmt.aks.kubeconfigfile +mgmt.aks.kubeconfig: @az aks get-credentials --overwrite-existing --only-show-errors -n ${AKS_NAME} -g $(MGMT_RESOURCEGROUP) -f "${MGMT_KUBECONFIG_FILE}" @kubelogin convert-kubeconfig -l azurecli --kubeconfig "${MGMT_KUBECONFIG_FILE}" .PHONY: mgmt.aks.kubeconfig @@ -329,10 +353,18 @@ mgmt.aks.kubeconfigfile: @echo ${MGMT_KUBECONFIG_FILE} .PHONY: mgmt.aks.kubeconfigfile -mgmt.init: region mgmt mgmt.aks.admin-access mgmt.aks.kubeconfig metrics-infra mgmt.enable-aks-metrics +mgmt.init: region metrics-infra mgmt mgmt.aks.admin-access mgmt.aks.kubeconfig mgmt.dev.permissions .PHONY: mgmt.init mgmt.what-if: mgmt.rg + @./ensure-no-running-deployment.sh $(MGMT_RESOURCEGROUP) $(MGMT_RESOURCEGROUP)-infra + az deployment group what-if \ + --name $(MGMG_RG_DEPLOYMENT_NAME)-infra \ + --resource-group $(MGMT_RESOURCEGROUP) \ + --template-file templates/mgmt-infra.bicep \ + --parameters \ + configurations/mgmt-infra.bicepparam + @./ensure-no-running-deployment.sh $(MGMT_RESOURCEGROUP) $(MGMT_RESOURCEGROUP) az deployment group what-if \ --name $(MGMG_RG_DEPLOYMENT_NAME) \ --resource-group $(MGMT_RESOURCEGROUP) \ @@ -342,15 +374,25 @@ mgmt.what-if: mgmt.rg .PHONY: mgmt.what-if mgmt.clean: - @if [ "$$(az group exists --name $(MGMT_RESOURCEGROUP))" = "true" ]; then \ + @if [ "$$(az group exists --name $(MGMT_RESOURCEGROUP) --output json)" = "true" ]; then \ + echo "Will delete Azure resource group $(MGMT_RESOURCEGROUP)"; \ az group delete -g $(MGMT_RESOURCEGROUP); \ fi .PHONY: mgmt.clean +mgmt.kv.permission: + @scripts/kv-permissions.sh $(PRINCIPAL_ID) $(MGMT_RESOURCEGROUP) $(CX_KV_NAME) + @scripts/kv-permissions.sh $(PRINCIPAL_ID) $(MGMT_RESOURCEGROUP) $(MSI_KV_NAME) + @scripts/kv-permissions.sh $(PRINCIPAL_ID) $(MGMT_RESOURCEGROUP) $(MGMT_KV_NAME) +.PHONY: mgmt.kv.permission + +mgmt.dev.permissions: mgmt.kv.permission +.PHONY: mgmt.dev.permissions + # ACR global.rg: - @if [ "$$(az group exists --name $(GLOBAL_RESOURCEGROUP))" = "false" ]; then \ + @if [ "$$(az group exists --name $(GLOBAL_RESOURCEGROUP) --output json)" = "false" ]; then \ az group create \ --name $(GLOBAL_RESOURCEGROUP) \ --location $(REGION) \ @@ -358,7 +400,27 @@ global.rg: fi .PHONY: global.rg -acr-svc: global.rg +acr: global.rg + @./ensure-no-running-deployment.sh $(GLOBAL_RESOURCEGROUP) ${GLOBAL_RG_DEPLOYMENT_NAME}-acr + az deployment group create \ + --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr \ + --resource-group $(GLOBAL_RESOURCEGROUP) \ + --template-file templates/global-acr.bicep \ + $(PROMPT_TO_CONFIRM) \ + --parameters \ + configurations/global-acr.bicepparam +.PHONY: acr + +acr.what-if: global.rg + az deployment group what-if \ + --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr \ + --resource-group $(GLOBAL_RESOURCEGROUP) \ + --template-file templates/global-acr.bicep \ + --parameters \ + configurations/global-acr.bicepparam +.PHONY: acr.what-if + +acr-svc-cfg: acr @./ensure-no-running-deployment.sh $(GLOBAL_RESOURCEGROUP) ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-svc az deployment group create \ --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-svc \ @@ -367,18 +429,18 @@ acr-svc: global.rg $(PROMPT_TO_CONFIRM) \ --parameters \ configurations/acr-svc.bicepparam -.PHONY: acr-svc +.PHONY: acr-svc-cfg -acr-svc.what-if: global.rg +acr-svc-cfg.what-if: global.rg az deployment group what-if \ --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-svc \ --resource-group $(GLOBAL_RESOURCEGROUP) \ --template-file templates/dev-acr.bicep \ --parameters \ configurations/acr-svc.bicepparam -.PHONY: acr-svc.what-if +.PHONY: acr-svc-cfg.what-if -acr-ocp: global.rg +acr-ocp-cfg: acr @./ensure-no-running-deployment.sh $(GLOBAL_RESOURCEGROUP) ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-ocp az deployment group create \ --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-ocp \ @@ -387,16 +449,16 @@ acr-ocp: global.rg $(PROMPT_TO_CONFIRM) \ --parameters \ configurations/acr-ocp.bicepparam -.PHONY: acr-ocp +.PHONY: acr-ocp-cfg -acr-ocp.what-if: global.rg +acr-ocp-cfg.what-if: global.rg az deployment group what-if \ --name ${GLOBAL_RG_DEPLOYMENT_NAME}-acr-ocp \ --resource-group $(GLOBAL_RESOURCEGROUP) \ --template-file templates/dev-acr.bicep \ --parameters \ configurations/acr-ocp.bicepparam -.PHONY: acr-ocp.what-if +.PHONY: acr-ocp-cfg.what-if # # Postgres Authentication Helpers @@ -407,7 +469,7 @@ cs-current-user-pg-connect: .PHONY: cs-current-user-pg-connect cs-miwi-pg-connect: - @scripts/cs-miwi-pg-connect.sh $(SVC_RESOURCEGROUP) $(CS_PG_NAME) "clusters-service" "cluster-service" "clusters-service" + @scripts/cs-miwi-pg-connect.sh $(SVC_RESOURCEGROUP) $(CS_PG_NAME) $(CS_MI_NAME) $(CS_NS_NAME) $(CS_SA_NAME) .PHONY: cs-miwi-pg-connect maestro-current-user-pg-connect: @@ -429,7 +491,8 @@ metrics-infra: regional.rg --resource-group $(REGIONAL_RESOURCEGROUP) \ --template-file modules/metrics/metrics.bicep \ $(PROMPT_TO_CONFIRM) \ - --parameters configurations/metrics.bicepparam + --parameters configurations/metrics.bicepparam; + @scripts/add-grafana-datasource.sh $(GRAFANA_NAME) $(GLOBAL_RESOURCEGROUP) $(MONITOR_NAME) $(REGIONAL_RESOURCEGROUP) .PHONY: metrics-infra metrics-infra.what-if: regional.rg @@ -459,11 +522,32 @@ secrets-yes-i-want-to-update-the-shared-secrets: rm secrets.tar.gz .PHONY: secrets-yes-i-want-to-update-the-shared-secrets +# +# Operator roles for platform workload identity +# + +operator-roles: + az deployment sub create \ + --location westus3 \ + --name operator-roles \ + --template-file templates/dev-operator-roles.bicep \ + $(PROMPT_TO_CONFIRM) \ + --parameters configurations/dev-operator-roles.bicepparam +.PHONY: operator-roles + +operator-roles.what-if: + az deployment sub what-if \ + --location westus3 \ + --name operator-roles \ + --template-file templates/dev-operator-roles.bicep \ + --parameters configurations/dev-operator-roles.bicepparam +.PHONY: operator-roles.what-if + # # Common # -what-if: acr-svc.what-if acr-ocp.what-if region.what-if svc.what-if mgmt.what-if metrics-infra.what-if imagesync.what-if +what-if: acr.what-if acr-svc-cfg.what-if acr-ocp-cfg.what-if region.what-if svc.what-if mgmt.what-if metrics-infra.what-if imagesync.what-if operator-roles.what-if .PHONY: what-if infra: region svc.init mgmt.init @@ -471,3 +555,10 @@ infra: region svc.init mgmt.init clean: svc.clean mgmt.clean region.clean .PHONY: clean + +# +# Local CS Development +# + +local-cs-permissions: svc.dev.permissions mgmt.dev.permissions +.PHONY: local-cs-permissions diff --git a/dev-infrastructure/config.tmpl.mk b/dev-infrastructure/config.tmpl.mk index bebf2beea..65fc68f0d 100644 --- a/dev-infrastructure/config.tmpl.mk +++ b/dev-infrastructure/config.tmpl.mk @@ -1,13 +1,28 @@ REGION ?= {{ .region }} -SVC_RESOURCEGROUP ?= {{ .serviceClusterRG }} -MGMT_RESOURCEGROUP ?= {{ .managementClusterRG }} +SVC_RESOURCEGROUP ?= {{ .svc.rg }} +MGMT_RESOURCEGROUP ?= {{ .mgmt.rg }} REGIONAL_RESOURCEGROUP ?= {{ .regionRG }} -SVC_KV_RESOURCEGROUP ?= {{ .serviceKeyVaultRG }} -GLOBAL_RESOURCEGROUP ?= {{ .globalRG }} -IMAGE_SYNC_RESOURCEGROUP ?= {{ .imageSyncRG }} -IMAGE_SYNC_ENVIRONMENT ?= {{ .imageSyncEnvironmentName }} +SVC_KV_RESOURCEGROUP ?= {{ .serviceKeyVault.rg }} +SVC_KV_NAME ?= {{ .serviceKeyVault.name }} +GLOBAL_RESOURCEGROUP ?= {{ .global.rg }} +GLOBAL_REGION ?= {{ .global.region }} +IMAGE_SYNC_RESOURCEGROUP ?= {{ .imageSync.rg }} +IMAGE_SYNC_ENVIRONMENT ?= {{ .imageSync.environmentName }} ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} -REPOSITORIES_TO_SYNC ?= '{{ .imageSyncRepositories }}' AKS_NAME ?= {{ .aksName }} -CS_PG_NAME ?= {{ .clusterServicePostgresName }} -MAESTRO_PG_NAME ?= {{ .maestroPostgresName }} +CS_PG_NAME ?= {{ .clusterService.postgres.name }} +CS_MI_NAME ?= {{ .clusterService.managedIdentityName }} +CS_NS_NAME ?= {{ .clusterService.k8s.namespace }} +CS_SA_NAME ?= {{ .clusterService.k8s.serviceAccountName }} +MAESTRO_PG_NAME ?= {{ .maestro.postgres.name }} +OIDC_STORAGE_ACCOUNT ?= {{ .oidcStorageAccountName }} +CX_KV_NAME ?= {{ .cxKeyVault.name }} +MSI_KV_NAME ?= {{ .msiKeyVault.name }} +MGMT_KV_NAME ?= {{ .mgmtKeyVault.name }} + +ISTIO_TARGET_VERSION ?= {{ .svc.istio.targetVersion }} +ISTIOCTL_VERSION ?= {{ .svc.istio.istioctlVersion }} +ISTIO_TAG ?= {{ .svc.istio.tag }} + +GRAFANA_NAME ?= {{ .monitoring.grafanaName }} +MONITOR_NAME ?= '{{ .monitoring.workspaceName }}' \ No newline at end of file diff --git a/dev-infrastructure/configurations/.gitignore b/dev-infrastructure/configurations/.gitignore new file mode 100644 index 000000000..f00e9b5b7 --- /dev/null +++ b/dev-infrastructure/configurations/.gitignore @@ -0,0 +1,2 @@ +mock-identities.bicepparam +svc-infra.bicepparam diff --git a/dev-infrastructure/configurations/acr-ocp.tmpl.bicepparam b/dev-infrastructure/configurations/acr-ocp.tmpl.bicepparam index ecd1e1279..0d9dc4616 100644 --- a/dev-infrastructure/configurations/acr-ocp.tmpl.bicepparam +++ b/dev-infrastructure/configurations/acr-ocp.tmpl.bicepparam @@ -1,8 +1,6 @@ using '../templates/dev-acr.bicep' param acrName = '{{ .ocpAcrName }}' -param acrSku = 'Premium' -param location = '{{ .region }}' param quayRepositoriesToCache = [ { @@ -23,4 +21,6 @@ param purgeJobs = [ } ] -param keyVaultName = '{{ .serviceKeyVaultName }}' +param keyVaultName = '{{ .serviceKeyVault.name }}' + +param location = '{{ .global.region }}' diff --git a/dev-infrastructure/configurations/acr-svc.tmpl.bicepparam b/dev-infrastructure/configurations/acr-svc.tmpl.bicepparam index 8d2c901f0..5d43eccfd 100644 --- a/dev-infrastructure/configurations/acr-svc.tmpl.bicepparam +++ b/dev-infrastructure/configurations/acr-svc.tmpl.bicepparam @@ -1,8 +1,6 @@ using '../templates/dev-acr.bicep' param acrName = '{{ .svcAcrName }}' -param acrSku = 'Premium' -param location = '{{ .region }}' param quayRepositoriesToCache = [ { @@ -36,4 +34,6 @@ param purgeJobs = [ } ] -param keyVaultName = '{{ .serviceKeyVaultName }}' +param keyVaultName = '{{ .serviceKeyVault.name }}' + +param location = '{{ .global.region }}' diff --git a/dev-infrastructure/configurations/cs-integ-msi.tmpl.bicepparam b/dev-infrastructure/configurations/cs-integ-msi.tmpl.bicepparam index 6a1915c5c..b7237ea3e 100644 --- a/dev-infrastructure/configurations/cs-integ-msi.tmpl.bicepparam +++ b/dev-infrastructure/configurations/cs-integ-msi.tmpl.bicepparam @@ -1,5 +1,6 @@ using '../templates/cs-integration-msi.bicep' param namespaceFormatString = 'sandbox-jenkins-{0}-aro-hcp' -param clusterServiceManagedIdentityName = 'clusters-service' +param clusterServiceManagedIdentityName = '{{ .clusterService.managedIdentityName }}' param clusterName = '{{ .aksName }}' +param clusterServiceServiceAccountName = '{{ .clusterService.k8s.serviceAccountName }}' diff --git a/dev-infrastructure/configurations/dev-operator-roles.bicepparam b/dev-infrastructure/configurations/dev-operator-roles.bicepparam new file mode 100644 index 000000000..ba7efa2b4 --- /dev/null +++ b/dev-infrastructure/configurations/dev-operator-roles.bicepparam @@ -0,0 +1,138 @@ +using '../templates/dev-operator-roles.bicep' + +param roles = [ + { + roleName: 'Azure Red Hat OpenShift Cloud Controller Manager - Dev' + roleDescription: 'Enables permissions for the operator to manage and update the cloud controller managers deployed on top of OpenShift.' + actions: [ + 'Microsoft.Compute/virtualMachines/read' + 'Microsoft.Network/loadBalancers/read' + 'Microsoft.Network/loadBalancers/write' + 'Microsoft.Network/networkInterfaces/read' + 'Microsoft.Network/networkSecurityGroups/read' + 'Microsoft.Network/networkSecurityGroups/write' + 'Microsoft.Network/publicIPAddresses/join/action' + 'Microsoft.Network/publicIPAddresses/read' + 'Microsoft.Network/publicIPAddresses/write' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + 'Microsoft.Network/virtualNetworks/subnets/read' + 'Microsoft.Network/loadBalancers/backendAddressPools/join/action' + 'Microsoft.Network/networkInterfaces/write' + ] + notActions: [] + dataActions: [] + notDataActions: [] + } + { + roleName: 'Azure Red Hat OpenShift Cluster Ingress Operator - Dev' + roleDescription: 'Enables permissions for the operator to configure and manage the OpenShift router.' + actions: [ + 'Microsoft.Network/dnsZones/A/delete' + 'Microsoft.Network/dnsZones/A/write' + 'Microsoft.Network/privateDnsZones/A/delete' + 'Microsoft.Network/privateDnsZones/A/write' + 'Microsoft.Network/virtualNetworks/subnets/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + ] + notActions: [] + dataActions: [] + notDataActions: [] + } + { + roleName: 'Azure Red Hat OpenShift Disk Storage Operator - Dev' + roleDescription: 'Enables permissions to set OpenShift cluster-wide storage defaults. It ensures a default storageclass exists for clusters. It also installs Container Storage Interface (CSI) drivers which enable your cluster to use various storage backends.' + actions: [ + 'Microsoft.Compute/virtualMachines/write' + 'Microsoft.Compute/virtualMachines/read' + 'Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write' + 'Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read' + 'Microsoft.Compute/virtualMachineScaleSets/read' + 'Microsoft.Compute/snapshots/write' + 'Microsoft.Compute/snapshots/read' + 'Microsoft.Compute/snapshots/delete' + 'Microsoft.Compute/locations/operations/read' + 'Microsoft.Compute/locations/DiskOperations/read' + 'Microsoft.Compute/disks/write' + 'Microsoft.Compute/disks/read' + 'Microsoft.Compute/disks/delete' + 'Microsoft.Resources/subscriptions/resourceGroups/read' + ] + notActions: [] + dataActions: [] + notDataActions: [] + } + { + roleName: 'Azure Red Hat OpenShift File Storage Operator - Dev' + roleDescription: 'Enables permissions to set OpenShift cluster-wide storage defaults. It ensures a default storageclass exists for clusters. It also installs Container Storage Interface (CSI) drivers which enable your cluster to use Azure Files.' + actions: [ + 'Microsoft.Storage/storageAccounts/delete' + 'Microsoft.Storage/storageAccounts/fileServices/read' + 'Microsoft.Storage/storageAccounts/fileServices/shares/delete' + 'Microsoft.Storage/storageAccounts/fileServices/shares/read' + 'Microsoft.Storage/storageAccounts/fileServices/shares/write' + 'Microsoft.Storage/storageAccounts/listKeys/action' + 'Microsoft.Storage/storageAccounts/read' + 'Microsoft.Storage/storageAccounts/write' + 'Microsoft.Network/networkSecurityGroups/join/action' + 'Microsoft.Network/virtualNetworks/subnets/read' + 'Microsoft.Network/virtualNetworks/subnets/write' + ] + notActions: [] + dataActions: [] + notDataActions: [] + } + { + roleName: 'Azure Red Hat OpenShift Network Operator - Dev' + roleDescription: 'Enables permissions to install and upgrade the networking components on an OpenShift cluster.' + actions: [ + 'Microsoft.Network/networkInterfaces/read' + 'Microsoft.Network/networkInterfaces/write' + 'Microsoft.Network/virtualNetworks/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + 'Microsoft.Network/loadBalancers/backendAddressPools/join/action' + 'Microsoft.Compute/virtualMachines/read' + ] + notActions: [] + dataActions: [] + notDataActions: [] + } + { + roleName: 'Azure Red Hat OpenShift Image Registry Operator - Dev' + roleDescription: 'Enables permissions for the operator to manage a singleton instance of the OpenShift image registry. It manages all configuration of the registry including creating storage.' + actions: [ + 'Microsoft.Storage/storageAccounts/blobServices/read' + 'Microsoft.Storage/storageAccounts/blobServices/containers/read' + 'Microsoft.Storage/storageAccounts/blobServices/containers/write' + 'Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action' + 'Microsoft.Storage/storageAccounts/read' + 'Microsoft.Storage/storageAccounts/write' + 'Microsoft.Storage/storageAccounts/delete' + 'Microsoft.Storage/storageAccounts/listKeys/action' + 'Microsoft.Resources/tags/write' + 'Microsoft.Network/privateEndpoints/write' + 'Microsoft.Network/privateEndpoints/read' + 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups/write' + 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups/read' + 'Microsoft.Network/privateDnsZones/read' + 'Microsoft.Network/privateDnsZones/write' + 'Microsoft.Network/privateDnsZones/join/action' + 'Microsoft.Network/privateDnsZones/A/write' + 'Microsoft.Network/privateDnsZones/virtualNetworkLinks/write' + 'Microsoft.Network/privateDnsZones/virtualNetworkLinks/read' + 'Microsoft.Network/networkInterfaces/read' + 'Microsoft.Storage/storageAccounts/PrivateEndpointConnectionsApproval/action' + 'Microsoft.Network/virtualNetworks/subnets/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + 'Microsoft.Network/virtualNetworks/join/action' + ] + notActions: [] + dataActions: [ + 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete' + 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write' + 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read' + 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/add/action' + 'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/move/action' + ] + notDataActions: [] + } +] diff --git a/dev-infrastructure/configurations/dev-role-assignments.tmpl.bicepparam b/dev-infrastructure/configurations/dev-role-assignments.tmpl.bicepparam index 6003767fe..57304e979 100644 --- a/dev-infrastructure/configurations/dev-role-assignments.tmpl.bicepparam +++ b/dev-infrastructure/configurations/dev-role-assignments.tmpl.bicepparam @@ -2,7 +2,7 @@ using '../templates/dev-roleassignments.bicep' param aksClusterName = '{{ .aksName }}' param grantCosmosAccess = true -param cosmosDBName = '{{ .frontendCosmosDBName }}' -param sharedKvNames = ['{{ .serviceKeyVaultName }}'] -param sharedKvResourceGroup = '{{ .serviceKeyVaultRG }}' +param cosmosDBName = '{{ .frontend.cosmosDB.name }}' +param sharedKvNames = ['{{ .serviceKeyVault.name }}'] +param sharedKvResourceGroup = '{{ .serviceKeyVault.rg }}' param principalID = '' diff --git a/dev-infrastructure/configurations/global-acr.tmpl.bicepparam b/dev-infrastructure/configurations/global-acr.tmpl.bicepparam new file mode 100644 index 000000000..879a2976c --- /dev/null +++ b/dev-infrastructure/configurations/global-acr.tmpl.bicepparam @@ -0,0 +1,9 @@ +using '../templates/global-acr.bicep' + +param svcAcrName = '{{ .svcAcrName }}' +param svcAcrSku = 'Premium' + +param ocpAcrName = '{{ .ocpAcrName }}' +param ocpAcrSku = 'Premium' + +param location = '{{ .global.region }}' diff --git a/dev-infrastructure/configurations/global-infra.tmpl.bicepparam b/dev-infrastructure/configurations/global-infra.tmpl.bicepparam new file mode 100644 index 000000000..677dd3d8b --- /dev/null +++ b/dev-infrastructure/configurations/global-infra.tmpl.bicepparam @@ -0,0 +1,8 @@ +using '../templates/global-infra.bicep' + +param globalMSIName = '{{ .global.globalMSIName }}' +param cxParentZoneName = '{{ .dns.cxParentZoneName }}' +param svcParentZoneName = '{{ .dns.svcParentZoneName }}' +param grafanaName = '{{ .monitoring.grafanaName }}' +param msiName = '{{ .monitoring.msiName }}' +param grafanaAdminGroupPrincipalId = '{{ .monitoring.grafanaAdminGroupPrincipalId }}' diff --git a/dev-infrastructure/configurations/image-sync.tmpl.bicepparam b/dev-infrastructure/configurations/image-sync.tmpl.bicepparam index e33135933..c32fe8c33 100644 --- a/dev-infrastructure/configurations/image-sync.tmpl.bicepparam +++ b/dev-infrastructure/configurations/image-sync.tmpl.bicepparam @@ -1,18 +1,23 @@ using '../templates/image-sync.bicep' -param containerAppEnvName = '{{ .imageSyncEnvironmentName }}' +param containerAppEnvName = '{{ .imageSync.environmentName }}' -param acrResourceGroup = '{{ .imageSyncAcrRG }}' -param keyVaultName = '{{ .serviceKeyVaultName}}' -param keyVaultResourceGroup = '{{ .serviceKeyVaultRG }}' +param acrResourceGroup = '{{ .imageSync.acrRG }}' +param keyVaultName = '{{ .imageSync.keyVault.name}}' +param keyVaultPrivate = {{ .imageSync.keyVault.private }} +param keyVaultSoftDelete = {{ .imageSync.keyVault.softDelete }} + +param componentSyncPullSecretName = '{{ .imageSync.componentSync.pullSecretName }}' +param componentSyncImage = '{{ .svcAcrName }}.azurecr.io/{{ .imageSync.componentSync.imageRepo }}:{{ .imageSync.componentSync.imageTag }}' +param componentSyncEnabed = {{ .imageSync.componentSync.enabled }} +param componentSyncSecrets = '{{ .imageSync.componentSync.secrets }}' -param bearerSecretName = 'bearer-secret' -param componentSyncPullSecretName = 'component-sync-pull-secret' -param componentSyncImage = '{{ .svcAcrName }}.azurecr.io/{{ .imageSyncImageRepo }}:{{ .imageSyncImageTag }}' param svcAcrName = '{{ .svcAcrName }}' param ocpAcrName = '{{ .ocpAcrName }}' -param ocpPullSecretName = 'pull-secret' -param repositoriesToSync = '{{ .imageSyncRepositories }}' -param ocMirrorImage = '{{ .svcAcrName }}.azurecr.io/{{ .ocMirrorImageRepo }}:{{ .ocMirrorImageTag }}' +param ocpPullSecretName = '{{ .imageSync.ocMirror.pullSecretName }}' +param repositoriesToSync = '{{ .imageSync.componentSync.repositories }}' +param ocMirrorImage = '{{ .svcAcrName }}.azurecr.io/{{ .imageSync.ocMirror.imageRepo }}:{{ .imageSync.ocMirror.imageTag }}' +param ocMirrorEnabled = {{ .imageSync.ocMirror.enabled }} + param numberOfTags = 10 diff --git a/dev-infrastructure/configurations/metrics.tmpl.bicepparam b/dev-infrastructure/configurations/metrics.tmpl.bicepparam index 315f5aadd..a86cd80d9 100644 --- a/dev-infrastructure/configurations/metrics.tmpl.bicepparam +++ b/dev-infrastructure/configurations/metrics.tmpl.bicepparam @@ -1,7 +1,6 @@ using '../modules/metrics/metrics.bicep' -param monitorName = '{{ .monitoringWorkspaceName }}' -param grafanaName = '{{ .grafanaName }}' -param msiName = '{{ .monitoringMsiName }}' -param grafanaAdminGroupPrincipalId = '{{ .grafanaAdminGroupPrincipalId }}' -param globalResourceGroup = '{{ .regionRG }}' +param monitorName = '{{ .monitoring.workspaceName }}' +param grafanaName = '{{ .monitoring.grafanaName }}' +param msiName = '{{ .monitoring.msiName }}' +param globalResourceGroup = '{{ .global.rg }}' diff --git a/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam b/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam index fa7e12463..b388ccc9d 100644 --- a/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam +++ b/dev-infrastructure/configurations/mgmt-cluster.tmpl.bicepparam @@ -1,49 +1,46 @@ using '../templates/mgmt-cluster.bicep' // AKS -param kubernetesVersion = '{{ .kubernetesVersion}}' -param vnetAddressPrefix = '{{ .vnetAddressPrefix }}' -param subnetPrefix = '{{ .subnetPrefix }}' -param podSubnetPrefix = '{{ .podSubnetPrefix }}' +param kubernetesVersion = '{{ .mgmt.aks.kubernetesVersion }}' +param vnetAddressPrefix = '{{ .mgmt.aks.vnetAddressPrefix }}' +param subnetPrefix = '{{ .mgmt.aks.subnetPrefix }}' +param podSubnetPrefix = '{{ .mgmt.aks.podSubnetPrefix }}' param aksClusterName = '{{ .aksName }}' -param aksKeyVaultName = '{{ .mgmtEtcdKVName }}' -param aksEtcdKVEnableSoftDelete = {{ .mgmtEtcdKVSoftDelete }} -param systemAgentMinCount = {{ .mgmtSystemAgentPoolMinCount}} -param systemAgentMaxCount = {{ .mgmtSystemAgentPoolMaxCount }} -param systemAgentVMSize = '{{ .mgmtSystemAgentPoolVmSize }}' -param aksSystemOsDiskSizeGB = {{ .mgmtSystemAgentPoolOsDiskSizeGB }} -param userAgentMinCount = {{ .mgmtUserAgentPoolMinCount }} -param userAgentMaxCount = {{ .mgmtUserAgentPoolMaxCount }} -param userAgentVMSize = '{{ .mgmtUserAgentPoolVmSize }}' -param aksUserOsDiskSizeGB = {{ .mgmtUserAgentPoolOsDiskSizeGB }} -param userAgentPoolAZCount = {{ .mgmtUserAgentPoolAzCount }} +param aksKeyVaultName = '{{ .mgmt.aks.etcd.kvName }}' +param aksEtcdKVEnableSoftDelete = {{ .mgmt.aks.etcd.kvSoftDelete }} +param systemAgentMinCount = {{ .mgmt.aks.systemAgentPool.minCount}} +param systemAgentMaxCount = {{ .mgmt.aks.systemAgentPool.maxCount }} +param systemAgentVMSize = '{{ .mgmt.aks.systemAgentPool.vmSize }}' +param aksSystemOsDiskSizeGB = {{ .mgmt.aks.systemAgentPool.osDiskSizeGB }} +param userAgentMinCount = {{ .mgmt.aks.userAgentPool.minCount }} +param userAgentMaxCount = {{ .mgmt.aks.userAgentPool.maxCount }} +param userAgentVMSize = '{{ .mgmt.aks.userAgentPool.vmSize }}' +param userAgentPoolAZCount = {{ .mgmt.aks.userAgentPool.azCount }} +param aksUserOsDiskSizeGB = {{ .mgmt.aks.userAgentPool.osDiskSizeGB }} +param aksClusterOutboundIPAddressIPTags = '{{ .mgmt.aks.clusterOutboundIPAddressIPTags }}' // Maestro -param maestroConsumerName = '{{ .maestroConsumerName }}' -param maestroKeyVaultName = '{{ .maestroKeyVaultName }}' -param maestroEventGridNamespacesName = '{{ .maestroEventgridName }}' -param maestroCertDomain = '{{ .maestroCertDomain }}' - -// DNS -param regionalDNSZoneName = '{{ .regionalDNSSubdomain}}.{{ .baseDnsZoneName }}' +param maestroConsumerName = '{{ .maestro.consumerName }}' +param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}' +param maestroCertDomain = '{{ .maestro.certDomain }}' // ACR -param acrPullResourceGroups = ['{{ .serviceComponentAcrResourceGroups }}'] +param acrPullResourceGroups = ['{{ .global.rg }}'] // Region param regionalResourceGroup = '{{ .regionRG }}' // CX KV -param cxKeyVaultName = '{{ .cxKeyVaultName }}' -param cxKeyVaultPrivate = {{ .cxKeyVaultPrivate }} -param cxKeyVaultSoftDelete = {{ .cxKeyVaultSoftDelete }} +param cxKeyVaultName = '{{ .cxKeyVault.name }}' // MSI KV -param msiKeyVaultName = '{{ .msiKeyVaultName }}' -param msiKeyVaultPrivate = {{ .msiKeyVaultPrivate }} -param msiKeyVaultSoftDelete = {{ .msiKeyVaultSoftDelete }} +param msiKeyVaultName = '{{ .msiKeyVault.name }}' // MGMT KV -param mgmtKeyVaultName = '{{ .mgmtKeyVaultName }}' -param mgmtKeyVaultPrivate = {{ .mgmtKeyVaultPrivate }} -param mgmtKeyVaultSoftDelete = {{ .mgmtKeyVaultSoftDelete }} +param mgmtKeyVaultName = '{{ .mgmtKeyVault.name }}' + +// MI for deployment scripts +param aroDevopsMsiId = '{{ .aroDevopsMsiId }}' + +// Azure Monitor Workspace +param azureMonitorWorkspaceName = '{{ .monitoring.workspaceName }}' diff --git a/dev-infrastructure/configurations/mgmt-infra.tmpl.bicepparam b/dev-infrastructure/configurations/mgmt-infra.tmpl.bicepparam new file mode 100644 index 000000000..3a83f0103 --- /dev/null +++ b/dev-infrastructure/configurations/mgmt-infra.tmpl.bicepparam @@ -0,0 +1,20 @@ +using '../templates/mgmt-infra.bicep' + +// CX KV +param cxKeyVaultName = '{{ .cxKeyVault.name }}' +param cxKeyVaultPrivate = {{ .cxKeyVault.private }} +param cxKeyVaultSoftDelete = {{ .cxKeyVault.softDelete }} + +// MSI KV +param msiKeyVaultName = '{{ .msiKeyVault.name }}' +param msiKeyVaultPrivate = {{ .msiKeyVault.private }} +param msiKeyVaultSoftDelete = {{ .msiKeyVault.softDelete }} + +// MGMT KV +param mgmtKeyVaultName = '{{ .mgmtKeyVault.name }}' +param mgmtKeyVaultPrivate = {{ .mgmtKeyVault.private }} +param mgmtKeyVaultSoftDelete = {{ .mgmtKeyVault.softDelete }} + +// Cluster Service identity +// used for Key Vault access +param clusterServiceMIResourceId = '{{ .mgmt.clusterServiceResourceId }}' diff --git a/dev-infrastructure/configurations/mock-identities.bicepparam b/dev-infrastructure/configurations/mock-identities.bicepparam deleted file mode 100644 index c923a3e13..000000000 --- a/dev-infrastructure/configurations/mock-identities.bicepparam +++ /dev/null @@ -1,5 +0,0 @@ -using '../templates/mock-identities.bicep' - -param kvCertOfficerManagedIdentityName = 'aro-hcp-dev-fp-kv-script' - -param keyVaultName = 'aro-hcp-dev-svc-kv' diff --git a/dev-infrastructure/configurations/mock-identities.tmpl.bicepparam b/dev-infrastructure/configurations/mock-identities.tmpl.bicepparam new file mode 100644 index 000000000..8cf3e7b3c --- /dev/null +++ b/dev-infrastructure/configurations/mock-identities.tmpl.bicepparam @@ -0,0 +1,5 @@ +using '../templates/mock-identities.bicep' + +param aroDevopsMsiId = '{{ .aroDevopsMsiId }}' + +param keyVaultName = '{{ .serviceKeyVault.name }}' diff --git a/dev-infrastructure/configurations/output-global.tmpl.bicepparam b/dev-infrastructure/configurations/output-global.tmpl.bicepparam new file mode 100644 index 000000000..441b7de14 --- /dev/null +++ b/dev-infrastructure/configurations/output-global.tmpl.bicepparam @@ -0,0 +1,7 @@ +using '../templates/output-global.bicep' + +param svcAcrName = '{{ .svcAcrName }}' +param ocpAcrName = '{{ .ocpAcrName }}' +param cxParentZoneName = '{{ .dns.cxParentZoneName }}' +param svcParentZoneName = '{{ .dns.svcParentZoneName }}' +param grafanaName = '{{ .monitoring.grafanaName }}' diff --git a/dev-infrastructure/configurations/output-region.tmpl.bicepparam b/dev-infrastructure/configurations/output-region.tmpl.bicepparam new file mode 100644 index 000000000..0e9c13734 --- /dev/null +++ b/dev-infrastructure/configurations/output-region.tmpl.bicepparam @@ -0,0 +1,4 @@ +using '../templates/output-region.bicep' + +param azureMonitorWorkspaceName = '{{ .monitoring.workspaceName }}' +param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}' diff --git a/dev-infrastructure/configurations/output-svc.tmpl.bicepparam b/dev-infrastructure/configurations/output-svc.tmpl.bicepparam new file mode 100644 index 000000000..43ea317d0 --- /dev/null +++ b/dev-infrastructure/configurations/output-svc.tmpl.bicepparam @@ -0,0 +1,3 @@ +using '../templates/output-svc.bicep' + +param csMIName = '{{ .clusterService.managedIdentityName }}' diff --git a/dev-infrastructure/configurations/region.tmpl.bicepparam b/dev-infrastructure/configurations/region.tmpl.bicepparam index 220f6192a..766afc9ba 100644 --- a/dev-infrastructure/configurations/region.tmpl.bicepparam +++ b/dev-infrastructure/configurations/region.tmpl.bicepparam @@ -1,11 +1,21 @@ using '../templates/region.bicep' +// general +param globalRegion = '{{ .global.region }}' +param globalResourceGroup = '{{ .global.rg }}' +param regionalRegion = '{{ .region }}' + +// acr +param ocpAcrName = '{{ .ocpAcrName }}' +param svcAcrName = '{{ .svcAcrName }}' + // dns -param baseDNSZoneName = '{{ .baseDnsZoneName }}' -param baseDNSZoneResourceGroup = '{{ .baseDnsZoneRG }}' -param regionalDNSSubdomain = '{{ .regionalDNSSubdomain }}' +param cxBaseDNSZoneName = '{{ .dns.cxParentZoneName }}' +param svcBaseDNSZoneName = '{{ .dns.svcParentZoneName }}' +param baseDNSZoneResourceGroup = '{{ .dns.baseDnsZoneRG }}' +param regionalDNSSubdomain = '{{ .dns.regionalSubdomain }}' // maestro -param maestroKeyVaultName = '{{ .maestroKeyVaultName }}' -param maestroEventGridNamespacesName = '{{ .maestroEventgridName }}' -param maestroEventGridMaxClientSessionsPerAuthName = {{ .maestroEventGridMaxClientSessionsPerAuthName }} +param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}' +param maestroEventGridMaxClientSessionsPerAuthName = {{ .maestro.eventGrid.maxClientSessionsPerAuthName }} +param maestroEventGridPrivate = {{ .maestro.eventGrid.private }} diff --git a/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam b/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam index 6a3ac77fe..22e54dc46 100644 --- a/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam +++ b/dev-infrastructure/configurations/svc-cluster.tmpl.bicepparam @@ -1,44 +1,71 @@ using '../templates/svc-cluster.bicep' -param kubernetesVersion = '{{ .kubernetesVersion }}' -param istioVersion = {{ .istioVersion }} -param vnetAddressPrefix = '{{ .vnetAddressPrefix }}' -param subnetPrefix = '{{ .subnetPrefix }}' -param podSubnetPrefix = '{{ .podSubnetPrefix }}' +param istioVersions = '{{ .svc.istio.versions }}' + +// AKS +param kubernetesVersion = '{{ .svc.aks.kubernetesVersion }}' +param vnetAddressPrefix = '{{ .svc.aks.vnetAddressPrefix }}' +param subnetPrefix = '{{ .svc.aks.subnetPrefix }}' +param podSubnetPrefix = '{{ .svc.aks.podSubnetPrefix }}' +param istioIngressGatewayIPAddressName = '{{ .svc.istio.ingressGatewayIPAddressName }}' +param istioIngressGatewayIPAddressIPTags = '{{ .svc.istio.ingressGatewayIPAddressIPTags }}' param aksClusterName = '{{ .aksName }}' -param aksKeyVaultName = '{{ .svcEtcdKVName }}' -param aksEtcdKVEnableSoftDelete = {{ .svcEtcdKVSoftDelete }} - -param disableLocalAuth = {{ .frontendCosmosDBDisableLocalAuth }} -param deployFrontendCosmos = {{ .frontendCosmosDBDeploy }} -param rpCosmosDbName = '{{ .frontendCosmosDBName }}' - -param maestroKeyVaultName = '{{ .maestroKeyVaultName }}' -param maestroEventGridNamespacesName = '{{ .maestroEventgridName }}' -param maestroCertDomain = '{{ .maestroCertDomain}}' -param maestroPostgresServerName = '{{ .maestroPostgresName }}' -param maestroPostgresServerVersion = '{{ .maestroPostgresServerVersion }}' -param maestroPostgresServerStorageSizeGB = {{ .maestroPostgresServerStorageSizeGB }} -param deployMaestroPostgres = {{ .maestroPostgresDeploy }} -param maestroPostgresPrivate = {{ .maestroPostgresPrivate }} - -param deployCsInfra = {{ .clusterServicePostgresDeploy }} -param csPostgresServerName = '{{ .clusterServicePostgresName }}' -param clusterServicePostgresPrivate = {{ .clusterServicePostgresPrivate }} - -param serviceKeyVaultName = '{{ .serviceKeyVaultName }}' -param serviceKeyVaultResourceGroup = '{{ .serviceKeyVaultRG }}' -param serviceKeyVaultLocation = '{{ .serviceKeyVaultRegion }}' -param serviceKeyVaultSoftDelete = {{ .serviceKeyVaultSoftDelete }} -param serviceKeyVaultPrivate = {{ .serviceKeyVaultPrivate }} - -param acrPullResourceGroups = ['{{ .serviceComponentAcrResourceGroups }}'] -param imageSyncAcrResourceGroupNames = ['{{ .imageSyncAcrRG }}'] -param clustersServiceAcrResourceGroupNames = ['{{ .clusterServiceAcrRG }}'] +param aksKeyVaultName = '{{ .svc.aks.etcd.kvName }}' +param aksEtcdKVEnableSoftDelete = {{ .svc.aks.etcd.kvSoftDelete }} +param systemAgentMinCount = {{ .svc.aks.systemAgentPool.minCount}} +param systemAgentMaxCount = {{ .svc.aks.systemAgentPool.maxCount }} +param systemAgentVMSize = '{{ .svc.aks.systemAgentPool.vmSize }}' +param aksSystemOsDiskSizeGB = {{ .svc.aks.systemAgentPool.osDiskSizeGB }} +param userAgentMinCount = {{ .svc.aks.userAgentPool.minCount }} +param userAgentMaxCount = {{ .svc.aks.userAgentPool.maxCount }} +param userAgentVMSize = '{{ .svc.aks.userAgentPool.vmSize }}' +param userAgentPoolAZCount = {{ .svc.aks.userAgentPool.azCount }} +param aksUserOsDiskSizeGB = {{ .svc.aks.userAgentPool.osDiskSizeGB }} +param aksClusterOutboundIPAddressIPTags = '{{ .svc.aks.clusterOutboundIPAddressIPTags }}' + +param disableLocalAuth = {{ .frontend.cosmosDB.disableLocalAuth }} +param deployFrontendCosmos = {{ .frontend.cosmosDB.deploy }} +param rpCosmosDbName = '{{ .frontend.cosmosDB.name }}' +param rpCosmosDbPrivate = {{ .frontend.cosmosDB.private }} + +param maestroMIName = '{{ .maestro.server.managedIdentityName }}' +param maestroNamespace = '{{ .maestro.server.k8s.namespace }}' +param maestroServiceAccountName = '{{ .maestro.server.k8s.serviceAccountName }}' +param maestroEventGridNamespacesName = '{{ .maestro.eventGrid.name }}' +param maestroServerMqttClientName = '{{ .maestro.server.mqttClientName }}' +param maestroCertDomain = '{{ .maestro.certDomain}}' +param maestroPostgresServerName = '{{ .maestro.postgres.name }}' +param maestroPostgresServerMinTLSVersion = '{{ .maestro.postgres.minTLSVersion }}' +param maestroPostgresServerVersion = '{{ .maestro.postgres.serverVersion }}' +param maestroPostgresServerStorageSizeGB = {{ .maestro.postgres.serverStorageSizeGB }} +param maestroPostgresDatabaseName = '{{ .maestro.postgres.databaseName }}' +param deployMaestroPostgres = {{ .maestro.postgres.deploy }} +param maestroPostgresPrivate = {{ .maestro.postgres.private }} + +param csPostgresDeploy = {{ .clusterService.postgres.deploy }} +param csPostgresServerName = '{{ .clusterService.postgres.name }}' +param csPostgresServerMinTLSVersion = '{{ .clusterService.postgres.minTLSVersion }}' +param clusterServicePostgresPrivate = {{ .clusterService.postgres.private }} +param csMIName = '{{ .clusterService.managedIdentityName }}' +param csNamespace = '{{ .clusterService.k8s.namespace }}' +param csServiceAccountName = '{{ .clusterService.k8s.serviceAccountName }}' + +param serviceKeyVaultName = '{{ .serviceKeyVault.name }}' +param serviceKeyVaultResourceGroup = '{{ .serviceKeyVault.rg }}' + +param acrPullResourceGroups = ['{{ .global.rg }}'] +param clustersServiceAcrResourceGroupNames = ['{{ .clusterService.acrRG }}'] param oidcStorageAccountName = '{{ .oidcStorageAccountName }}' param aroDevopsMsiId = '{{ .aroDevopsMsiId }}' -param regionalDNSZoneName = '{{ .regionalDNSSubdomain}}.{{ .baseDnsZoneName }}' +param regionalCXDNSZoneName = '{{ .dns.regionalSubdomain }}.{{ .dns.cxParentZoneName }}' +param regionalSvcDNSZoneName = '{{ .dns.regionalSubdomain }}.{{ .dns.svcParentZoneName }}' param regionalResourceGroup = '{{ .regionRG }}' + +param frontendIngressCertName = '{{ .frontend.cert.name }}' +param frontendIngressCertIssuer = '{{ .frontend.cert.issuer }}' + +// Azure Monitor Workspace +param azureMonitorWorkspaceName = '{{ .monitoring.workspaceName }}' diff --git a/dev-infrastructure/configurations/svc-infra.tmpl.bicepparam b/dev-infrastructure/configurations/svc-infra.tmpl.bicepparam new file mode 100644 index 000000000..8fd0f15cd --- /dev/null +++ b/dev-infrastructure/configurations/svc-infra.tmpl.bicepparam @@ -0,0 +1,10 @@ +using '../templates/svc-infra.bicep' + +param serviceKeyVaultName = '{{ .serviceKeyVault.name }}' +param serviceKeyVaultResourceGroup = '{{ .serviceKeyVault.rg }}' +param serviceKeyVaultLocation = '{{ .serviceKeyVault.region }}' +param serviceKeyVaultSoftDelete = {{ .serviceKeyVault.softDelete }} +param serviceKeyVaultPrivate = {{ .serviceKeyVault.private }} + +// SP for KV certificate issuer registration +param svcKvCertOfficerPrincipalId = '{{ .kvCertOfficerPrincipalId }}' diff --git a/dev-infrastructure/docs/development-setup.md b/dev-infrastructure/docs/development-setup.md index b49fe4bc6..4c023b783 100644 --- a/dev-infrastructure/docs/development-setup.md +++ b/dev-infrastructure/docs/development-setup.md @@ -10,7 +10,9 @@ The idea of this repo is to provide means to create a development environment th * `az` version >= 2.60, `jq`, `make`, `kubelogin` (from ), `kubectl` version >= 1.30, `helm` * `az login` with your Red Hat email -* Register the needed [AFEC](https://aka.ms/afec) feature flags using `cd dev-infrastructure && make feature-registration +* Register the needed [AFEC](https://aka.ms/afec) feature flags using `cd dev-infrastructure && make feature-registration` +* `openssl` CLI tool +* `jq` CLI tool * __NOTE:__ This will take awhile, you will have to wait until they're in a registered state. * Your Red Hat account has been added to the ARO HCP Engineering App Developer group in Azure portal. This will give your account access to resources on Azure for development purposes. Please reach out to your manager or team lead to add you to this group. @@ -118,11 +120,13 @@ defaults: (1) clouds: public: (2) defaults: (3) - baseDnsZoneName: "arohcp.azure.com" + dns: + cxParentZoneName: "arohcp.azure.com" environments: personal-dev: (4) defaults: - baseDnsZoneName: "hcp.osadev.cloud" (5) + dns: + cxParentZoneName: "hcp.osadev.cloud" (5) production: defaults: regions: @@ -239,14 +243,14 @@ There are more fine grained cleanup tasks available as well To followup sections describe how to deploy the components individually. But if you are looking for a quick and easy way to install or update ALL components on both clusters with one command, then run this: ```bash - make deploy.svc.all - make deploy.mgmt.all + make svc.deployall + make mgmt.deployall ``` Or even simpler with ```bash - make deploy.all + make deployall ``` ## Deploy Services to the service cluster @@ -256,7 +260,7 @@ Or even simpler with ### Maestro Server ```bash - make maestro.server.deploy + make maestro.server.deploy_pipeline ``` To validate, have a look at the `maestro` namespace on the service cluster. Some pod restarts are expected in the first 1 minute until the containerized DB is ready. @@ -273,7 +277,7 @@ To access the HTTP and GRPC endpoints of maestro, run > This might not work with `oc` 4.17.0, please use oc 4.16.x until this is fixed in 4.17 ```bash - make cs.deploy + make cluster-service.deploy_pipeline ``` To validate, have a look at the `cluster-service` namespace or the service cluster. @@ -283,8 +287,8 @@ To validate, have a look at the `cluster-service` namespace or the service clust The ARO-HCP resource provider consists of independent frontend and backend components. ```bash - make rp.frontend.deploy - make rp.backend.deploy + make frontend.deploy_pipeline + make backend.deploy_pipeline ``` To validate, have a look at the `aro-hcp` namespace on the service cluster. @@ -300,7 +304,7 @@ To validate, have a look at the `aro-hcp` namespace on the service cluster. ### Hypershift Operator and External DNS ```bash - make hypershift.deploy + make hypershiftoperator.deploy_pipeline ``` ### Maestro Agent @@ -308,7 +312,7 @@ To validate, have a look at the `aro-hcp` namespace on the service cluster. First install the agent ```bash - make maestro.agent.deploy + make maestro.agent.deploy_pipeline ``` Then register it with the Maestro Server @@ -317,233 +321,260 @@ Then register it with the Maestro Server make maestro.registration.deploy ``` -## CS Local Development Setup - -Should your development needs require a running instance of CS to test with, here is how to spin up a locally running Clusters Service with containerized database suitable enough for testing. - -To complete the below steps you will need: - -1) `podman`, `ocm` cli (latest), and [`yq`](https://github.com/mikefarah/yq) cli (version 4+) -2) An up-to-date [Clusters Service repo](https://gitlab.cee.redhat.com/service/uhc-clusters-service) cloned down (can also use a fork if you have one) - -> If you don't have or want to install `yq`, any steps below using `yq` can be done manually - -### Configure and run CS - -Option 1: Configure and initialize Cluster Service using the script: -Run ./dev-infrastructure/local_CS.sh from the root of ARO-HCP repo where "uhc-clusters-service" and "ARO-HCP" repos should be at the same level: - -* uhc-clusters-service/ -* ARO-HCP/ -* etc - -Option 2: You can follow the below manual steps from the root of the CS repo on our system: - -1) Follow [Azure Credentials and Pull Secret for HCP creation](#azure-credentials-and-pull-secret-for-hcp-creation) to fetch `azure-creds.json`. - -2) Setup required config files - -```bash -# Setup the development.yml -cp ./configs/development.yml . - -# Setup the azure-runtime-config.json -# Currently following properties are expected in the file: -# - `cloudEnvironment` : The Azure cloud environment where Cluster Service is running on. -# Possible values are 'AzurePublicCloud', 'AzureChinaCloud' and 'AzureUSGovernmentCloud'. -cp ./configs/azure/example-config.json ./azure-runtime-config.json - -# Get azure-first-party-application-client-id -# This property needs to be set in the forked development.yml file using the value obtained below -az ad app list --display-name aro-dev-first-party --query '[*]'.appId -o tsv - - -# Update any required empty strings to 'none' -yq -i '(.aws-access-key-id, .aws-secret-access-key, .route53-access-key-id, .route53-secret-access-key, .oidc-access-key-id, .oidc-secret-access-key, .network-verifier-access-key-id, .network-verifier-secret-access-key, .client-id, .client-secret) = "none"' development.yml - -# Generate a provision_shards.config for port-forwarded maestro ... -make -C $the_aro_hcp_dir/cluster-service provision-shard > provision_shards.config - -# the resulting configuration requires two portforwardings into the service cluster -kubectl port-forward svc/maestro 8001:8000 -n maestro -kubectl port-forward svc/maestro-grpc 8090 -n maestro - -# Alternatively, update provision shards config with new shard manually -cat < ./provision_shards.config -provision_shards: -- id: 1 - maestro_config: | +## Creating an ARO HCP Cluster via Cluster Service + +### Creating a cluster +1) Login to your CS deployment + - Access your CS deployment locally + ```bash + KUBECONFIG=$(make infra.svc.aks.kubeconfigfile) kubectl port-forward svc/clusters-service 8000:8000 -n cluster-service + ``` + - Login to your CS deployment + ```bash + ocm login --url=http://localhost:8000 --use-auth-code + ``` + +2) Create pre-requisite resources for cluster creation + + Replace `resource-group`, `vnet-name`, `nsg-name` and `subnet-name` with any valid names. + + - Create a resource group for your ARO HCP cluster. This is used, alongside the resource name and subscription ID, to represent + your ARO HCP cluster resource in Azure. + ``` + az group create --name --location "westus3" + ``` + - Create a Virtual Network. + > NOTE: This may be created in the same resource group above, or a different one. + ``` + az network vnet create -n -g --subnet-name + ``` + - Create a Network security group + > NOTE: This may be created in the same resource group above, or a different one. + ``` + az network nsg create -n -g + ``` + - Associate the created VNet with the subnet of the created NSG + ``` + az network vnet subnet update -g -n --vnet-name --network-security-group + ``` + - Generate a random alphanumeric string used as a suffix for the User-Assigned Managed Identities of the operators of the cluster + > NOTE: The random suffix used has to be different for each cluster to be created + ``` + export OPERATORS_UAMIS_SUFFIX=$(openssl rand -hex 3) + ``` + - Define and export an environment variable with the desired name of the ARO-HCP Cluster in CS + ``` + export CS_CLUSTER_NAME="" + ``` + - Create the User-Assigned Managed Identities for the Control Plane operators. This assumes OCP 4.17 based will be created. + > NOTE: Managed Identities cannot be reused between operators nor between clusters. This is, each operator must use + a different managed identity, and different clusters must use different managed identities, even for the same + operators. + + > NOTE: Remember to cleanup the created Managed Identities once you are done with the cluster. See the `Cleaning up a Cluster` section + ``` + # We create the control plane operators User-Assigned Managed Identities + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-cloud-controller-manager-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-ingress-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-disk-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-file-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-image-registry-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-cp-cloud-network-config-${OPERATORS_UAMIS_SUFFIX} -g + + # And then we create variables containing their Azure resource IDs and export them to be used later + export CP_CONTROL_PLANE_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-control-plane-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_CAPZ_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-cluster-api-azure-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_CCM_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-cloud-controller-manager-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_INGRESS_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-ingress-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_DISK_CSI_DRIVER_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-disk-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_FILE_CSI_DRIVER_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-file-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_IMAGE_REGISTRY_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-image-registry-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export CP_CNC_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-cp-cloud-network-config-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + ``` + + - Create the User-Assigned Managed Identities for the Data Plane operators. This assumes OCP 4.17 clusters will be created. + > NOTE: Managed Identities cannot be reused between operators nor between clusters. This is, each operator must use + a different managed identity, and different clusters must use different managed identities, even for the same + operators. + + > NOTE: Remember to cleanup the created Managed Identities once you are done with the cluster. See the `Cleaning up a Cluster` section + ``` + # We create the data plane operators User-Assigned Managed Identities + az identity create -n ${USER}-${CS_CLUSTER_NAME}-dp-disk-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-dp-image-registry-${OPERATORS_UAMIS_SUFFIX} -g + az identity create -n ${USER}-${CS_CLUSTER_NAME}-dp-file-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g + + # And then we create variables containing their Azure resource IDs and export them to be used later + export DP_DISK_CSI_DRIVER_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-dp-disk-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export DP_IMAGE_REGISTRY_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-dp-image-registry-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export DP_FILE_CSI_DRIVER_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-dp-file-csi-driver-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export DP_INGRESS_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-dp-ingress-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + export DP_CNC_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-dp-cloud-network-config-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + ``` + - Create the User-Assigned Service Managed Identity + > NOTE: Managed Identities cannot be reused between operators nor between clusters. This is, each operator must use + a different managed identity, and different clusters must use different managed identities, even for the same + operators. + + > NOTE: Remember to cleanup the created Managed Identities once you are done with the cluster. See the `Cleaning up a Cluster` section + ``` + az identity create -n ${USER}-${CS_CLUSTER_NAME}-service-managed-identity-${OPERATORS_UAMIS_SUFFIX} -g + + export SERVICE_MANAGED_IDENTITY_UAMI=$(az identity show -n ${USER}-${CS_CLUSTER_NAME}-service-managed-identity-${OPERATORS_UAMIS_SUFFIX} -g | jq -r '.id') + ``` + +3) Create the cluster. This assumes OCP 4.17 clusters will be created. + > **NOTE** See the [Cluster Service API](https://api.openshift.com/#/default/post_api_clusters_mgmt_v1_clusters) documentation + > for further information on the properties within the payload below + + ```bash + SUBSCRIPTION_NAME="ARO Hosted Control Planes (EA Subscription 1)" + RESOURCENAME="" + SUBSCRIPTION=$(echo $(az account subscription list | jq '.[] | select(.displayName == $SUBSCRIPTION_NAME)' | jq -r '.subscriptionId')) + RESOURCEGROUPNAME="" + TENANTID=$(echo $(cat azure-creds.json | jq -r '.tenantId')) + MANAGEDRGNAME="" + SUBNETRESOURCEID="" + NSG="" + cat < cluster-test.json { - "rest_api_config": { - "url": "http://localhost:8001" + "name": "$CS_CLUSTER_NAME", + "product": { + "id": "aro" }, - "grpc_api_config": { - "url": "localhost:8090" + "ccs": { + "enabled": true }, - "consumer_name": "<>" + "region": { + "id": "westus3" + }, + "hypershift": { + "enabled": true + }, + "multi_az": true, + "azure": { + "resource_name": "$RESOURCENAME", + "subscription_id": "$SUBSCRIPTION", + "resource_group_name": "$RESOURCEGROUPNAME", + "tenant_id": "$TENANTID", + "managed_resource_group_name": "$MANAGEDRGNAME", + "subnet_resource_id": "$SUBNETRESOURCEID", + "network_security_group_resource_id":"$NSG", + "operators_authentication": { + "managed_identities": { + "managed_identities_data_plane_identity_url": "https://dummyhost.identity.azure.net", + "control_plane_operators_managed_identities": { + "control-plane": { + "resource_id": "$CP_CONTROL_PLANE_UAMI" + }, + "cluster-api-azure": { + "resource_id": "$CP_CAPZ_UAMI" + }, + "cloud-controller-manager": { + "resource_id": "$CP_CCM_UAMI" + }, + "ingress": { + "resource_id": "$CP_INGRESS_UAMI" + }, + "disk-csi-driver": { + "resource_id": "$CP_DISK_CSI_DRIVER_UAMI" + }, + "file-csi-driver": { + "resource_id": "$CP_FILE_CSI_DRIVER_UAMI" + }, + "image-registry": { + "resource_id": "$CP_IMAGE_REGISTRY_UAMI" + }, + "cloud-network-config": { + "resource_id": "$CP_CNC_UAMI" + } + }, + "data_plane_operators_managed_identities": { + "disk-csi-driver": { + "resource_id": "$DP_DISK_CSI_DRIVER_UAMI" + }, + "image-registry": { + "resource_id": "$DP_IMAGE_REGISTRY_UAMI" + }, + "file-csi-driver": { + "resource_id": "$DP_FILE_CSI_DRIVER_UAMI" + } + }, + "service_managed_identity": { + "resource_id": "$SERVICE_MANAGED_IDENTITY_UAMI" + } + } + } + }, + "version": { + "id": "openshift-v4.17.0" + } } - status: active - azure_base_domain: "" - management_cluster_id: local-cluster - region: westus3 - cloud_provider: azure - topology: dedicated -EOF + EOF -# Enable the westus3 region in cloud region config + cat cluster-test.json | ocm post /api/clusters_mgmt/v1/clusters + ``` -cat <> ./configs/cloud-resources/cloud-regions.yaml - - id: westus3 - cloud_provider_id: azure - display_name: West US 3 - supports_multi_az: true -EOF - -cat <> ./configs/cloud-resources/cloud-regions-constraints.yaml - - id: westus3 - enabled: true - govcloud: false - ccs_only: true -EOF - -# you can verify the region change with the below -yq '.cloud_regions[] | select(.id == "westus3")' configs/cloud-resource-constraints/cloud-region-constraints.yaml - -# Update region_constraints.config with new cloud provider -cat < ./region_constraints.config -cloud_providers: -- name: azure - regions: - - name: westus3 - version_constraints: - min_version: 4.11.0 - product_constraints: - - product: hcp - version_constraints: - min_version: 4.12.23 -EOF + You should now have a cluster in OCM. You can verify using `ocm list clusters` or `ocm get cluster CLUSTERID` -cat < ./configs/cloud-resources/instance-types.yaml -instance_types: - - id: Standard_D4as_v4 - name: Standard_D4as_v4 - General purpose - cloud_provider_id: azure - cpu_cores: 4 - memory: 17179869184 - category: general_purpose - size: d4as_v4 - generic_name: standard-d4as_v4 -EOF - -cat < ./configs/cloud-resource-constraints/instance-type-constraints.yaml -instance_types: - - id: Standard_D4as_v4 - ccs_only: true - enabled: true -EOF -``` - -3) Get azure-first-party-application-certificate-bundle-path: -Run the following command to generate a file containing the base64 decoded first-party application certificate bundle. -This property needs to be set in the forked development.yml file using the value of the absolute path where the certificate resides -```shell -$ az keyvault secret show --vault-name "aro-hcp-dev-svc-kv" --name "firstPartyCert" --query "value" -o tsv | base64 -d > ~/fpa_cert -``` - -4) Follow CS dev setup process: - -```bash -# Build CS -make cmds - -# Setup local DB -make db/setup - -# Initialize the DB -./clusters-service init --config-file ./development.yml -``` - -5) Start CS: - -```bash -./clusters-service serve --config-file development.yml --runtime-mode aro-hcp --azure-auth-config-path azure-creds.json -``` - -You now have a running, functioning local CS deployment - -### Interact with CS - -1) Login to your local CS deployment - -```bash -ocm login --url=http://localhost:8000 --use-auth-code -``` - -2) In the previously created Resource Group: - - Create a Virtual Network and a Network security group - - Associate the created VNet with the subnet of the created NSG - - Go to settings→Subnets of NSG and associate Vnet - -3) Create a test cluster - note that `version.id` must match the version inserted into the database earlier. +### Creating node pools +> NOTE: See the [Cluster Service API](https://api.openshift.com/#/default/post_api_clusters_mgmt_v1_clusters__cluster_id__node_pools) documentation for further information on the properties within the payload below ```bash +CLUSTER_ID="" +UID="" NAME="" -SUBSCRIPTION_NAME="ARO Hosted Control Planes (EA Subscription 1)" -RESOURCENAME="" -SUBSCRIPTION=$(echo $(az account subscription list | jq '.[] | select(.displayName == $SUBSCRIPTION_NAME)' | jq -r '.subscriptionId')) -RESOURCEGROUPNAME="" -TENANTID=$(echo $(cat azure-creds.json | jq -r '.tenantId')) -MANAGEDRGNAME="" -SUBNETRESOURCEID="" -$NSG="" -cat < cluster-test.json +REPLICAS="" +cat < nodepool-test.json { - "name": "$NAME-aro-hcp", - "product": { - "id": "aro" - }, - "ccs": { - "enabled": true - }, - "region": { - "id": "westus3" - }, - "hypershift": { - "enabled": true - }, - "multi_az": true, - "azure": { - "resource_name": "$RESOURCENAME", - "subscription_id": "$SUBSCRIPTION", - "resource_group_name": "$RESOURCEGROUPNAME", - "tenant_id": "$TENANTID", - "managed_resource_group_name": "$MANAGEDRGNAME", - "subnet_resource_id": "$SUBNETRESOURCEID", - "network_security_group_resource_id":"$NSG" - }, - "properties": { - "provision_shard_id": "1" - }, - "version": { - "id": "openshift-v4.16.0" - } + "id": "$UID", + "replicas": $REPLICAS, + "auto_repair": false, + "azure_node_pool": { + "resource_name": "$NAME", + "vm_size": "Standard_D8s_v3", + "os_disk_size_gibibytes": 30, + "os_disk_storage_account_type": "StandardSSD_LRS", + "ephemeral_os_disk_enabled": false + } } EOF -cat cluster-test.json | ocm post /api/clusters_mgmt/v1/clusters +cat nodepool-test.json | ocm post /api/clusters_mgmt/v1/clusters/$CLUSTER_ID/node_pools ``` -You should now have a cluster in OCM. You can verify using `ocm list clusters` or `ocm get cluster CLUSTERID` +You should now have a nodepool for your cluster in Cluster Service. You can verify using: +``` +ocm get /api/clusters_mgmt/v1/clusters/$CLUSTER_ID/node_pools/$UID +``` -To create a cluster in CS using a locally running Frontend, see the frontend [README](../../frontend/README.md) +### Cleaning up a Cluster -## CS Dev Cleanup +1. Delete the cluster + ``` + ocm delete /api/clusters_mgmt/v1/clusters/$CLUSTER_ID + ``` + > NOTE: Deleting it will also delete all of its associated node pools. -To tear down your CS setup: +2. Delete the created managed identities that were initially created for the cluster: + ``` + az identity delete --ids "${CP_CONTROL_PLANE_UAMI}" + az identity delete --ids "${CP_CAPZ_UAMI}" + az identity delete --ids "${CP_INGRESS_UAMI}" + az identity delete --ids "${CP_DISK_CSI_DRIVER_UAMI}" + az identity delete --ids "${CP_FILE_CSI_DRIVER_UAMI}" + az identity delete --ids "${CP_IMAGE_REGISTRY_UAMI}" + az identity delete --ids "${CP_CNC_UAMI}" + az identity delete --ids "${DP_DISK_CSI_DRIVER_UAMI}" + az identity delete --ids "${DP_IMAGE_REGISTRY_UAMI}" + az identity delete --ids "${DP_FILE_CSI_DRIVER_UAMI}" + az identity delete --ids "${DP_INGRESS_UAMI}" + az identity delete --ids "${DP_CNC_UAMI}" + az identity delete --ids "${SERVICE_MANAGED_IDENTITY_UAMI}" + ``` -1) Kill the running clusters-service process -2) Clean up the database `make db/teardown` -3) Clean the certificate bundle `$ rm ~/fpa_cert_decoded` +## Creating an ARO HCP Cluster via Frontend +To create a cluster in CS using a locally running Frontend, see the frontend [README](../../frontend/README.md) ## Appendix diff --git a/dev-infrastructure/global-pipeline.yaml b/dev-infrastructure/global-pipeline.yaml new file mode 100644 index 000000000..021da626c --- /dev/null +++ b/dev-infrastructure/global-pipeline.yaml @@ -0,0 +1,45 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Global +rolloutName: Global Resource Rollout +resourceGroups: +- name: {{ .global.rg }} + subscription: {{ .global.subscription }} + steps: + # creates the parent DNS zones for the ARO HCP services + - name: global-infra + action: ARM + template: templates/global-infra.bicep + parameters: configurations/global-infra.tmpl.bicepparam + deploymentLevel: ResourceGroup + # creates DNS delegation for the ARO HCP global SVC zone + - name: svcChildZone + action: DelegateChildZone + parentZone: + configRef: dns.parentZoneName + childZone: + configRef: dns.svcParentZoneName + dependsOn: + - global-infra + # creates DNS delegation for the ARO HCP global CX zone + - name: cxChildZone + action: DelegateChildZone + parentZone: + configRef: dns.parentZoneName + childZone: + configRef: dns.cxParentZoneName + dependsOn: + - global-infra + # create global ARO HCP ACRs for OCP and SVC images + - name: global-acrs + action: ARM + template: templates/global-acr.bicep + parameters: configurations/global-acr.tmpl.bicepparam + deploymentLevel: ResourceGroup + # deploys the image mirror for the ACRs + - name: imagemirror + action: ARM + template: templates/image-sync.bicep + parameters: configurations/image-sync.tmpl.bicepparam + deploymentLevel: ResourceGroup + dependsOn: + - global-acrs diff --git a/dev-infrastructure/local_CS.sh b/dev-infrastructure/local_CS.sh index 5f0f722ed..97048b466 100755 --- a/dev-infrastructure/local_CS.sh +++ b/dev-infrastructure/local_CS.sh @@ -6,9 +6,9 @@ make db/teardown # Obtain Azure credentials from keyvault VAULTNAME=aro-hcp-dev-svc-kv -az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-pull-secret" | jq .value -r > pull-secret.json -az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-sp" | jq .value -r > azure-creds -az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-sp-cs" | jq .value -r > azure-creds.json +az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-pull-secret" --output json | jq .value -r > pull-secret.json +az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-sp" --output json | jq .value -r > azure-creds +az keyvault secret show --vault-name $VAULTNAME --name "aro-hcp-dev-sp-cs" --output json | jq .value -r > azure-creds.json # Setup the development.yml cp ./configs/development.yml . @@ -17,7 +17,7 @@ cp ./configs/development.yml . yq -i '(.aws-access-key-id, .aws-secret-access-key, .route53-access-key-id, .route53-secret-access-key, .oidc-access-key-id, .oidc-secret-access-key, .network-verifier-access-key-id, .network-verifier-secret-access-key, .client-id, .client-secret) = "none"' development.yml # Generate a provision_shards.config for port-forwarded maestro ... -make -C ../ARO-HCP/cluster-service provision-shard > provision_shards.config +make -C ../ARO-HCP/cluster-service local-deploy-provision-shard > provision_shards.config # Enable the westus3 region in cloud region config @@ -28,7 +28,7 @@ cat <> ./configs/cloud-resources/cloud-regions.yaml supports_multi_az: true EOF -cat <> ./configs/cloud-resources/cloud-regions-constraints.yaml +cat <> ./configs/cloud-resource-constraints/cloud-region-constraints.yaml - id: westus3 enabled: true govcloud: false diff --git a/dev-infrastructure/mgmt-pipeline.yaml b/dev-infrastructure/mgmt-pipeline.yaml new file mode 100644 index 000000000..9cffc5daa --- /dev/null +++ b/dev-infrastructure/mgmt-pipeline.yaml @@ -0,0 +1,52 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Management.Infra +rolloutName: Management Cluster Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + steps: + - name: svc-output + action: ARM + template: templates/output-svc.bicep + parameters: configurations/output-svc.tmpl.bicepparam + deploymentLevel: ResourceGroup + outputOnly: true +- name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + steps: + - name: mgmt-infra + action: ARM + template: templates/mgmt-infra.bicep + parameters: configurations/mgmt-infra.tmpl.bicepparam + deploymentLevel: ResourceGroup + variables: + - name: clusterServiceMIResourceId + input: + step: svc-output + name: cs + dependsOn: + - svc-output + - name: mgmt-cluster + action: ARM + template: templates/mgmt-cluster.bicep + parameters: configurations/mgmt-cluster.tmpl.bicepparam + deploymentLevel: ResourceGroup + dependsOn: + - mgmt-infra +- name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + aksCluster: {{ .aksName }} + steps: + # Install ACRpull + - name: acrpull + action: Shell + command: make -C ../acrpull deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ACRPULL_DIGEST + configRef: acrPullImageDigest + dependsOn: + - mgmt-cluster diff --git a/dev-infrastructure/modules/acr-permissions.bicep b/dev-infrastructure/modules/acr/acr-permissions.bicep similarity index 61% rename from dev-infrastructure/modules/acr-permissions.bicep rename to dev-infrastructure/modules/acr/acr-permissions.bicep index fa00b03bc..f728db7c2 100644 --- a/dev-infrastructure/modules/acr-permissions.bicep +++ b/dev-infrastructure/modules/acr/acr-permissions.bicep @@ -4,30 +4,34 @@ param principalId string @description('Whether to grant push access to the ACR') param grantPushAccess bool = false -@description('Whether to grant contributor access to the ACR') -param grantContributorAccess bool = false +@description('Whether to grant manage token access to the ACR') +param grantManageTokenAccess bool = false -@description('ACR Namespace Resource Group Name') +@description('ACR Namespace Resource Group Id') param acrResourceGroupid string +// https://www.azadvertizer.net/azrolesadvertizer/7f951dda-4ed3-4680-a7ca-43fe172d538d.html var acrPullRoleDefinitionId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d' ) +// https://www.azadvertizer.net/azrolesadvertizer/8311e382-0749-4cb8-b61a-304f252e45ec.html var acrPushRoleDefinitionId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec' ) +// https://www.azadvertizer.net/azrolesadvertizer/c2f4ef07-c644-48eb-af81-4b1b4947fb11.html var acrDeleteRoleDefinitionId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11' ) -var contributorRoleDefinitionId = subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions/', - 'b24988ac-6180-42a0-ab88-20f7382dd24c' +// https://www.azadvertizer.net/azrolesadvertizer/3bc748fc-213d-45c1-8d91-9da5725539b9.html +var acrContributorAndDataAccessConfigurationAdministratorRoleDefinitionId = subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3bc748fc-213d-45c1-8d91-9da5725539b9' ) resource acrPullRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!grantPushAccess) { @@ -57,10 +61,10 @@ resource acrDeleteRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if } } -resource acrContributorRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (grantContributorAccess) { - name: guid(acrResourceGroupid, principalId, contributorRoleDefinitionId) +resource acrContributorAndDataAccessConfigurationAdministratorRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (grantManageTokenAccess) { + name: guid(acrResourceGroupid, principalId, acrContributorAndDataAccessConfigurationAdministratorRoleDefinitionId) properties: { - roleDefinitionId: contributorRoleDefinitionId + roleDefinitionId: acrContributorAndDataAccessConfigurationAdministratorRoleDefinitionId principalId: principalId principalType: 'ServicePrincipal' } diff --git a/dev-infrastructure/modules/acr/acr-replication.bicep b/dev-infrastructure/modules/acr/acr-replication.bicep new file mode 100644 index 000000000..2b70bc2c2 --- /dev/null +++ b/dev-infrastructure/modules/acr/acr-replication.bicep @@ -0,0 +1,23 @@ +@description('ACR replication resource location') +param acrReplicationLocation string + +@description('Parent ACR resource name') +param acrReplicationParentAcrName string + +@minLength(5) +@maxLength(40) +@description('ACR replication name (must be globally unique)') +param acrReplicationReplicaName string + +resource parentAcr 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' existing = { + name: acrReplicationParentAcrName +} + +resource acrReplication 'Microsoft.ContainerRegistry/registries/replications@2023-11-01-preview' = { + parent: parentAcr + name: acrReplicationReplicaName + location: acrReplicationLocation + properties: { + regionEndpointEnabled: true + } +} diff --git a/dev-infrastructure/modules/aks-cluster-base.bicep b/dev-infrastructure/modules/aks-cluster-base.bicep index b503c0d69..803045479 100644 --- a/dev-infrastructure/modules/aks-cluster-base.bicep +++ b/dev-infrastructure/modules/aks-cluster-base.bicep @@ -3,6 +3,11 @@ param aksClusterName string param aksNodeResourceGroupName string param aksEtcdKVEnableSoftDelete bool +// Metrics +param dcrId string +param metricLabelsAllowlist string = '' +param metricAnnotationsAllowList string = '' + // System agentpool spec(Infra) param systemAgentMinCount int = 2 param systemAgentMaxCount int = 3 @@ -25,13 +30,41 @@ param persist bool = false param kubernetesVersion string param deployIstio bool -param istioVersion array = ['asm-1-22'] +param istioVersions array = [] param vnetAddressPrefix string param subnetPrefix string param podSubnetPrefix string param clusterType string param workloadIdentities array +@description('Istio Ingress Gateway Public IP Address resource name') +param istioIngressGatewayIPAddressName string = '' + +@description('IPTags to be set on the cluster outbound IP address in the format of ipTagType:tag,ipTagType:tag') +param aksClusterOutboundIPAddressIPTags string = '' +var aksClusterOutboundIPAddressIPTagsArray = [ + for tag in (aksClusterOutboundIPAddressIPTags == '') ? [] : split(aksClusterOutboundIPAddressIPTags, ','): { + ipTagType: split(tag, ':')[0] + tag: split(tag, ':')[1] + } +] + +@description('IPTags to be set on the Istio Ingress Gateway IP address in the format of ipTagType:tag,ipTagType:tag') +param istioIngressGatewayIPAddressIPTags string = '' +var istioIngressGatewayIPAddressIPTagsArray = [ + for tag in (istioIngressGatewayIPAddressIPTags == '') ? [] : split(istioIngressGatewayIPAddressIPTags, ','): { + ipTagType: split(tag, ':')[0] + tag: split(tag, ':')[1] + } +] + +@description('List of Availability Zones for zone-redundant resources') +param zoneRedundancyZones array = [ + '1' + '2' + '3' +] + @maxLength(24) param aksKeyVaultName string @@ -47,16 +80,31 @@ param userOsDiskSizeGB int param acrPullResourceGroups array = [] +@description('MSI that will take actions on the AKS cluster during service deployment time') +param aroDevopsMsiId string + @description('Perform cryptographic operations using keys. Only works for key vaults that use the Azure role-based access control permission model.') var keyVaultCryptoUserId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424' ) +// Azure Kubernetes Service Cluster Admin Role +// https://www.azadvertizer.net/azrolesadvertizer/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8.html var aksClusterAdminRoleId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions/', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' ) + +// Azure Kubernetes Service RBAC Cluster Admin Role +// https://www.azadvertizer.net/azrolesadvertizer/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b.html +var aksClusterAdminRBACRoleId = subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions/', + 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' +) + +// Network Contributor Role +// https://www.azadvertizer.net/azrolesadvertizer/4d97b98b-1d4f-4787-a291-c67834d212e7.html var networkContributorRoleId = subscriptionResourceId( 'Microsoft.Authorization/roleDefinitions/', '4d97b98b-1d4f-4787-a291-c67834d212e7' @@ -198,6 +246,39 @@ resource aksClusterAdminRoleAssignment 'Microsoft.Authorization/roleAssignments@ } } +module istioIngressGatewayIPAddress '../modules/network/publicipaddress.bicep' = if (deployIstio) { + name: istioIngressGatewayIPAddressName + params: { + name: istioIngressGatewayIPAddressName + ipTags: istioIngressGatewayIPAddressIPTagsArray + location: location + zones: zoneRedundancyZones + // Role Assignment needed for the public IP address to be used on the Load Balancer + roleAssignmentProperties: { + principalId: aksClusterUserDefinedManagedIdentity.properties.principalId + principalType: 'ServicePrincipal' + roleDefinitionId: networkContributorRoleId + } + } +} + +var aksClusterOutboundIPAddressName = 'aro-hcp-cluster-egress' +module aksClusterOutboundIPAddress '../modules/network/publicipaddress.bicep' = { + name: aksClusterOutboundIPAddressName + params: { + name: aksClusterOutboundIPAddressName + ipTags: aksClusterOutboundIPAddressIPTagsArray + location: location + zones: zoneRedundancyZones + // Role Assignment needed for the public IP address to be used on the Load Balancer + roleAssignmentProperties: { + principalId: aksClusterUserDefinedManagedIdentity.properties.principalId + principalType: 'ServicePrincipal' + roleDefinitionId: networkContributorRoleId + } + } +} + resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-preview' = { location: location kind: 'Base' @@ -254,11 +335,7 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-previ vnetSubnetID: aksNodeSubnet.id podSubnetID: aksPodSubnet.id maxPods: 100 - availabilityZones: [ - '1' - '2' - '3' - ] + availabilityZones: zoneRedundancyZones securityProfile: { enableSecureBoot: false enableVTPM: false @@ -287,6 +364,15 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-previ nodeOSUpgradeChannel: 'NodeImage' upgradeChannel: 'patch' } + azureMonitorProfile: { + metrics: { + enabled: true + kubeStateMetrics: { + metricLabelsAllowlist: metricLabelsAllowlist + metricAnnotationsAllowList: metricAnnotationsAllowList + } + } + } disableLocalAccounts: true dnsPrefix: dnsPrefix enableRBAC: true @@ -299,6 +385,15 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-previ networkProfile: { ipFamilies: ['IPv4'] loadBalancerSku: 'standard' + loadBalancerProfile: { + outboundIPs: { + publicIPs: [ + { + id: resourceId('Microsoft.Network/publicIPAddresses', aksClusterOutboundIPAddressName) + } + ] + } + } networkDataplane: 'cilium' networkPolicy: 'cilium' networkPlugin: 'azure' @@ -343,7 +438,7 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-previ } ] } - revisions: istioVersion + revisions: istioVersions } } : null @@ -361,6 +456,11 @@ resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-04-02-previ } supportPlan: 'KubernetesOfficial' } + dependsOn: [ + aksNetworkContributorRoleAssignment + aks_keyvault_crypto_user + aksClusterOutboundIPAddress + ] } resource userAgentPools 'Microsoft.ContainerService/managedClusters/agentPools@2024-04-02-preview' = [ @@ -418,7 +518,7 @@ resource acrRg 'Microsoft.Resources/resourceGroups@2023-07-01' existing = [ } ] -module acrPullRole 'acr-permissions.bicep' = [ +module acrPullRole 'acr/acr-permissions.bicep' = [ for (_, i) in acrPullResourceGroups: { name: guid(acrRg[i].id, aksCluster.id, acrPullRoleDefinitionId) scope: acrRg[i] @@ -450,6 +550,65 @@ resource uami_fedcred 'Microsoft.ManagedIdentity/userAssignedIdentities/federate } ] +// +// A C R P U L L C O N T R O L L E R +// + +resource pullerIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + location: location + name: 'image-puller' +} + +module acrPullerRoles 'acr/acr-permissions.bicep' = [ + for (_, i) in acrPullResourceGroups: { + name: guid(acrRg[i].id, aksCluster.id, acrPullRoleDefinitionId, 'puller-identity') + scope: acrRg[i] + params: { + principalId: pullerIdentity.properties.principalId + acrResourceGroupid: acrRg[i].id + } + } +] + +@batchSize(1) +resource puller_fedcred 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = [ + for i in range(0, length(workloadIdentities)): { + parent: pullerIdentity + name: '${workloadIdentities[i].value.uamiName}-${location}-puller-fedcred' + properties: { + audiences: [ + 'api://AzureCRTokenExchange' + ] + issuer: aksCluster.properties.oidcIssuerProfile.issuerURL + subject: 'system:serviceaccount:${workloadIdentities[i].value.namespace}:${workloadIdentities[i].value.serviceAccountName}' + } + } +] + + +// grant aroDevopsMsi the aksClusterAdmin role on the aksCluster so it can +// deploy services to the cluster +resource aroDevopsMSIClusterAdmin 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(aksCluster.id, aroDevopsMsiId, aksClusterAdminRBACRoleId) + scope: aksCluster + properties: { + principalId: reference(aroDevopsMsiId, '2023-01-31').principalId + principalType: 'ServicePrincipal' + roleDefinitionId: aksClusterAdminRBACRoleId + } +} + +// metrics dcr association +resource azuremonitormetrics_dcra_clusterResourceId 'Microsoft.Insights/dataCollectionRuleAssociations@2022-06-01' = { + name: '${resourceGroup().name}-${aksCluster.name}-dcra' + scope: aksCluster + properties: { + description: 'Association of data collection rule. Deleting this association will break the data collection for this AKS Cluster.' + dataCollectionRuleId: dcrId + } +} + + // Outputs output userAssignedIdentities array = [ for i in range(0, length(workloadIdentities)): { @@ -463,3 +622,5 @@ output aksVnetId string = vnet.id output aksNodeSubnetId string = aksNodeSubnet.id output aksOidcIssuerUrl string = aksCluster.properties.oidcIssuerProfile.issuerURL output aksClusterName string = aksClusterName +output aksClusterKeyVaultSecretsProviderPrincipalId string = aksCluster.properties.addonProfiles.azureKeyvaultSecretsProvider.identity.objectId +output istioIngressGatewayIPAddress string = istioIngressGatewayIPAddress.outputs.ipAddress diff --git a/dev-infrastructure/modules/cluster-service.bicep b/dev-infrastructure/modules/cluster-service.bicep index ed871f47e..258f7538b 100644 --- a/dev-infrastructure/modules/cluster-service.bicep +++ b/dev-infrastructure/modules/cluster-service.bicep @@ -1,43 +1,72 @@ -@description('The location for the PostGres DB') -param location string - @description('The managed identity name CS will use to interact with Azure resources') param clusterServiceManagedIdentityName string @description('The managed identity CS uses to interact with Azure resources') param clusterServiceManagedIdentityPrincipalId string +@description('Defines if the Postgres server should be deployed') +param deployPostgres bool + @description('The name of the database to create for CS') param csDatabaseName string = 'clusters-service' @description('The name of the Postgres server for CS') param postgresServerName string +@description('The minimum TLS version for the Postgres server') +param postgresServerMinTLSVersion string + +@description('Defines if the Postgres server is private') param postgresServerPrivate bool +@description('The subnet ID for the private endpoint of the Postgres server') param privateEndpointSubnetId string = '' +@description('The VNET ID for the private endpoint of the Postgres server') param privateEndpointVnetId string = '' -resource postgresAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: '${postgresServerName}-db-admin-msi' - location: location -} +@description('The name of the service keyvault') +param serviceKeyVaultName string + +@description('The resource group of the service keyvault') +param serviceKeyVaultResourceGroup string + +@description( + ''' + The regional DNS zone to hold ARO HCP customer cluster DNS records. + CS requires write access to this zone to provision the DNS records for HCPs. + ''' +) +param regionalCXDNSZoneName string + +@description('The regional resourece group') +param regionalResourceGroup string + +@description('The names of the ACR resource groups / will be refactored soon into dedicated ACR Resource IDs') +param acrResourceGroupNames array = [] -module postgres 'postgres/postgres.bicep' = { +@description('The resource ID of the managed identity used to manage the Postgres server') +param postgresAdministrationManagedIdentityId string + +// +// P O S T G R E S +// + +import * as res from 'resource.bicep' + +module postgres 'postgres/postgres.bicep' = if (deployPostgres) { name: '${deployment().name}-postgres' params: { name: postgresServerName databaseAdministrators: [ - // add the dedicated admin managed identity as administrator - // this one is going to be used to manage DB access { - principalId: postgresAdminManagedIdentity.properties.principalId - principalName: postgresAdminManagedIdentity.name + principalId: reference(postgresAdministrationManagedIdentityId, '2023-01-31').principalId + principalName: res.msiRefFromId(postgresAdministrationManagedIdentityId).name principalType: 'ServicePrincipal' } ] version: '12' + minTLSVersion: postgresServerMinTLSVersion configurations: [ // some configs taked over from the CS RDS instance // https://gitlab.cee.redhat.com/service/app-interface/-/blob/fc95453b1e0eaf162089525f5b94b6dc1e6a091f/resources/terraform/resources/ocm/clusters-service-production-rds-parameter-group-pg12.yml @@ -75,11 +104,11 @@ module postgres 'postgres/postgres.bicep' = { // Create DB user for the clusters-service managed identity and enable entra authentication // -module csManagedIdentityDatabaseAccess 'postgres/postgres-access.bicep' = { +module csManagedIdentityDatabaseAccess 'postgres/postgres-access.bicep' = if (deployPostgres) { name: '${deployment().name}-cs-db-access' params: { postgresServerName: postgresServerName - postgresAdminManagedIdentityName: postgresAdminManagedIdentity.name + postgresAdministrationManagedIdentityId: postgresAdministrationManagedIdentityId databaseName: csDatabaseName newUserName: clusterServiceManagedIdentityName newUserPrincipalId: clusterServiceManagedIdentityPrincipalId @@ -90,9 +119,53 @@ module csManagedIdentityDatabaseAccess 'postgres/postgres-access.bicep' = { } // -// output +// K E Y V A U L T A C C E S S // -output postgresHostname string = postgres.outputs.hostname -output csDatabaseName string = csDatabaseName -output csDatabaseUsername string = clusterServiceManagedIdentityName +module csServiceKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = { + name: guid(serviceKeyVaultName, 'cs', 'read') + scope: resourceGroup(serviceKeyVaultResourceGroup) + params: { + keyVaultName: serviceKeyVaultName + roleName: 'Key Vault Secrets User' + managedIdentityPrincipalId: clusterServiceManagedIdentityPrincipalId + } +} + +// +// D N S +// + +module csDnsZoneContributor '../modules/dns/zone-contributor.bicep' = { + name: guid(regionalCXDNSZoneName, clusterServiceManagedIdentityPrincipalId) + scope: resourceGroup(regionalResourceGroup) + params: { + zoneName: regionalCXDNSZoneName + zoneContributerManagedIdentityPrincipalId: clusterServiceManagedIdentityPrincipalId + } +} + +// +// O C P A C R P E R M I S S I O N S +// + +resource clustersServiceAcrResourceGroups 'Microsoft.Resources/resourceGroups@2023-07-01' existing = [ + for rg in acrResourceGroupNames: if (rg != '') { + // temp hack for MSFT pipelines + name: rg + scope: subscription() + } +] + +module acrManageTokenRole '../modules/acr/acr-permissions.bicep' = [ + for (_, i) in acrResourceGroupNames: if (acrResourceGroupNames[i] != '') { + // temp hack for MSFT pipelines + name: guid(clustersServiceAcrResourceGroups[i].id, resourceGroup().name, 'clusters-service', 'manage-tokens') + scope: clustersServiceAcrResourceGroups[i] + params: { + principalId: clusterServiceManagedIdentityPrincipalId + grantManageTokenAccess: true + acrResourceGroupid: clustersServiceAcrResourceGroups[i].id + } + } +] diff --git a/dev-infrastructure/modules/keyvault/identity-script-msi.bicep b/dev-infrastructure/modules/keyvault/identity-script-msi.bicep deleted file mode 100644 index 9f4eb4a89..000000000 --- a/dev-infrastructure/modules/keyvault/identity-script-msi.bicep +++ /dev/null @@ -1,38 +0,0 @@ -@description('Azure Region Location') -param location string = resourceGroup().location - -@description('The name of the key vault') -param keyVaultName string - -@description('Azure Region Location') -param kvCertOfficerManagedIdentityName string - -// -// M A N A G E D I D E N T I T Y C R E A T I O N -// - -resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { - name: keyVaultName -} - -resource kvCertOfficerManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: kvCertOfficerManagedIdentityName - location: location -} - -var keyVaultCertificateOfficerRoleId = subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions/', - 'a4417e6f-fecd-4de8-b567-7b0420556985' -) - -resource kvManagedIdentityRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: kv - name: guid(kvCertOfficerManagedIdentity.id, keyVaultCertificateOfficerRoleId, kv.id) - properties: { - roleDefinitionId: keyVaultCertificateOfficerRoleId - principalId: kvCertOfficerManagedIdentity.properties.principalId - principalType: 'ServicePrincipal' - } -} - -output kvCertOfficerManagedIdentityId string = kvCertOfficerManagedIdentity.id diff --git a/dev-infrastructure/modules/key-vault-cert.bicep b/dev-infrastructure/modules/keyvault/key-vault-cert.bicep similarity index 67% rename from dev-infrastructure/modules/key-vault-cert.bicep rename to dev-infrastructure/modules/keyvault/key-vault-cert.bicep index 7225b0fd3..fa7164575 100644 --- a/dev-infrastructure/modules/key-vault-cert.bicep +++ b/dev-infrastructure/modules/keyvault/key-vault-cert.bicep @@ -2,9 +2,6 @@ Creating certificates in Azure Key Vault is not supported by Bicep yet. This module leverages a deploymentscript to solve this for the time beeing. Proudly stolen from https://github.com/Azure/bicep/discussions/8457 - -We might not need certificates for MQTT authentication altogether if -Entra autentication can be leveraged: https://redhat-external.slack.com/archives/C03F6AA3HDH/p1713340078776669 */ param keyVaultName string @@ -14,11 +11,20 @@ param issuerName string param dnsNames array param now string = utcNow('F') param keyVaultManagedIdentityId string -param location string +param location string = resourceGroup().location param force bool = false var boolstring = force == false ? '$false' : '$true' param validityInMonths int = 12 +module certificateOfficerAccess 'keyvault-secret-access.bicep' = { + name: 'kv-cert-officer-access-${keyVaultName}-${uniqueString(keyVaultManagedIdentityId, deployment().name)}' + params: { + keyVaultName: keyVaultName + roleName: 'Key Vault Certificates Officer' + managedIdentityPrincipalId: reference(keyVaultManagedIdentityId, '2023-01-31').principalId + } +} + resource newCertwithRotationKV 'Microsoft.Resources/deploymentScripts@2023-08-01' = { name: 'newCertwithRotationKV-${certName}' identity: { @@ -30,9 +36,9 @@ resource newCertwithRotationKV 'Microsoft.Resources/deploymentScripts@2023-08-01 location: location kind: 'AzurePowerShell' properties: { - azPowerShellVersion: '7.5.0' + azPowerShellVersion: '12.0.0' arguments: ' -VaultName ${keyVaultName} -ValidityInMonths ${validityInMonths} -IssuerName ${issuerName} -CertName ${certName} -SubjectName ${subjectName} -DnsNames ${join(dnsNames,'_')} -Force ${boolstring}' - scriptContent: loadTextContent('../scripts/key-vault-cert.ps1') + scriptContent: loadTextContent('../../scripts/key-vault-cert.ps1') forceUpdateTag: now cleanupPreference: 'Always' retentionInterval: 'P1D' @@ -41,5 +47,5 @@ resource newCertwithRotationKV 'Microsoft.Resources/deploymentScripts@2023-08-01 } output Thumbprint string = newCertwithRotationKV.properties.outputs.Thumbprint -output CACert string = newCertwithRotationKV.properties.outputs.CACert +output CACert string = issuerName == 'Self' ? newCertwithRotationKV.properties.outputs.CACert : issuerName output KeyVaultCertId string = newCertwithRotationKV.properties.outputs.KeyVaultCertId diff --git a/dev-infrastructure/modules/keyvault/keyvault-private-endpoint.bicep b/dev-infrastructure/modules/keyvault/keyvault-private-endpoint.bicep deleted file mode 100644 index f1b9986d9..000000000 --- a/dev-infrastructure/modules/keyvault/keyvault-private-endpoint.bicep +++ /dev/null @@ -1,77 +0,0 @@ -@description('Location of the endpoint.') -param location string - -@description('ID of the subnet to create the private endpoint in.') -param subnetId string - -@description('ID of the vnet, needs to correlated with subnetId.') -param vnetId string - -@description('Name of the key vault to create this endpoint for.') -param keyVaultName string - -@description('ID of the key vault.') -param keyVaultId string - -// -// P R I V A T E E N D P O I N T -// - -var privateDnsZoneName = 'privatelink.vaultcore.azure.net' - -resource keyVaultPrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-01-01' = { - name: '${keyVaultName}-pe' - location: location - properties: { - privateLinkServiceConnections: [ - { - name: '${keyVaultName}-pe' - properties: { - groupIds: [ - 'vault' - ] - privateLinkServiceId: keyVaultId - } - } - ] - subnet: { - id: subnetId - } - } -} - -resource keyVaultPrivateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { - name: privateDnsZoneName - location: 'global' - properties: {} -} - -resource keyVaultPrivateDnsZoneVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { - parent: keyVaultPrivateEndpointDnsZone - name: uniqueString('keyvault-${uniqueString(vnetId)}') - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: vnetId - } - } -} - -resource privateEndpointDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-09-01' = { - parent: keyVaultPrivateEndpoint - name: '${keyVaultName}-dns-group' - properties: { - privateDnsZoneConfigs: [ - { - name: 'config1' - properties: { - privateDnsZoneId: keyVaultPrivateEndpointDnsZone.id - } - } - ] - } - dependsOn: [ - keyVaultPrivateDnsZoneVnetLink - ] -} diff --git a/dev-infrastructure/modules/keyvault/keyvault-secret-access.bicep b/dev-infrastructure/modules/keyvault/keyvault-secret-access.bicep index 2f532042d..0d8d581ba 100644 --- a/dev-infrastructure/modules/keyvault/keyvault-secret-access.bicep +++ b/dev-infrastructure/modules/keyvault/keyvault-secret-access.bicep @@ -8,6 +8,8 @@ param secretName string = '' @allowed([ 'Key Vault Secrets Officer' 'Key Vault Secrets User' + 'Key Vault Certificate User' + 'Key Vault Certificates Officer' ]) param roleName string @@ -25,6 +27,16 @@ var roleResourceIds = { 'Microsoft.Authorization/roleDefinitions/', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7' ) + // Read entire certificate contents including secret and key portion. + 'Key Vault Certificate User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions/', + 'db79e9a7-68ee-4b58-9aeb-b90e7c24fcba' + ) + // Perform any action on the certificates of a key vault, excluding reading the secret and key portions, and managing permissions. + 'Key Vault Certificates Officer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions/', + 'a4417e6f-fecd-4de8-b567-7b0420556985' + ) } resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { diff --git a/dev-infrastructure/modules/keyvault/keyvault.bicep b/dev-infrastructure/modules/keyvault/keyvault.bicep index 169996e73..360a4dc38 100644 --- a/dev-infrastructure/modules/keyvault/keyvault.bicep +++ b/dev-infrastructure/modules/keyvault/keyvault.bicep @@ -38,3 +38,5 @@ resource keyVault 'Microsoft.KeyVault/vaults@2024-04-01-preview' = { output kvId string = keyVault.id output kvName string = keyVault.name + +output kvUrl string = keyVault.properties.vaultUri diff --git a/dev-infrastructure/modules/maestro/maestro-access-cert.bicep b/dev-infrastructure/modules/maestro/maestro-access-cert.bicep new file mode 100644 index 000000000..6b8cd66cb --- /dev/null +++ b/dev-infrastructure/modules/maestro/maestro-access-cert.bicep @@ -0,0 +1,85 @@ +/* +Creates a certificate in Key Vault signed by the specified issuer. +For dev environments `Self` is used as issuer, for higher environments +OneCertV2 Private will be used. + +The specified managed identity `certificateAccessManagedIdentityPrincipalId` +is granted access to the certificate in Key Vault. This will be leveraged +with CSI secret store to access the certificate from the maestro pods. + +Execution scope: the resourcegroup of the Key Vault where the certificate will be stored +*/ + +@description('The Key Vault where the certificate for Event Grid access will be stored') +param keyVaultName string + +@description('The managed identity that will be used to manage the certificate in Key Vault') +param kvCertOfficerManagedIdentityResourceId string + +@description('The base domain name to be used for the certificates DNS name.') +param certDomain string + +@description('The name of the client that will be created in the EventGrid Namespace') +param clientName string + +@description('The name of the certificate in Key Vault.') +param keyVaultCertificateName string + +@description('The issuer of the certificate.') +param certificateIssuer string = 'Self' + +@description('Grant this managed identity access to the certificate in Key Vault.') +param certificateAccessManagedIdentityPrincipalId string + +// +// C E R T I F I C A T E C R E A T I O N +// + +var clientAuthenticationName = '${clientName}.${certDomain}' + +module clientCertificate '../keyvault/key-vault-cert.bicep' = { + name: '${clientName}-client-cert' + params: { + keyVaultName: keyVaultName + subjectName: 'CN=${clientName}' + certName: keyVaultCertificateName + keyVaultManagedIdentityId: kvCertOfficerManagedIdentityResourceId + dnsNames: [ + clientAuthenticationName + ] + issuerName: certificateIssuer + } +} + +// +// C E R T I F I C A T E A C C E S S P E R M I S S I O N +// + +var keyVaultSecretUserRoleId = subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions/', + '4633458b-17de-408a-b874-0445c86b69e6' +) + +resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { + name: keyVaultName +} + +// grant permissions on the secret that contains the certificate + +resource secret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' existing = { + parent: kv + name: keyVaultCertificateName +} + +resource secretAccessPermission 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: secret + name: guid(certificateAccessManagedIdentityPrincipalId, keyVaultSecretUserRoleId, kv.id, keyVaultCertificateName) + properties: { + roleDefinitionId: keyVaultSecretUserRoleId + principalId: certificateAccessManagedIdentityPrincipalId + principalType: 'ServicePrincipal' + } +} + +output certificateThumbprint string = clientCertificate.outputs.Thumbprint +output certificateSAN string = clientAuthenticationName diff --git a/dev-infrastructure/modules/maestro/maestro-consumer.bicep b/dev-infrastructure/modules/maestro/maestro-consumer.bicep index b7b1beeff..fb585eb9e 100644 --- a/dev-infrastructure/modules/maestro/maestro-consumer.bicep +++ b/dev-infrastructure/modules/maestro/maestro-consumer.bicep @@ -1,25 +1,41 @@ -param maestroServerManagedIdentityPrincipalId string +/* +This module is responsible for setting up EventGrid access for the maestro consumer by +- create a client certificate +- register the client in the EventGrid namespace + +Execution scope: the resourcegroup of the MC where the agent is deployed. +*/ + +param maestroAgentManagedIdentityPrincipalId string @minLength(1) param maestroConsumerName string param maestroInfraResourceGroup string param maestroEventGridNamespaceName string -param maestroKeyVaultName string -param maestroKeyVaultOfficerManagedIdentityName string -param maestroKeyVaultCertificateDomain string -param location string +param certKeyVaultName string +param keyVaultOfficerManagedIdentityName string +param maestroCertificateDomain string + +module eventGridClientCert 'maestro-access-cert.bicep' = { + name: '${deployment().name}-eg-crt-${uniqueString(maestroConsumerName)}' + params: { + keyVaultName: certKeyVaultName + kvCertOfficerManagedIdentityResourceId: keyVaultOfficerManagedIdentityName + certDomain: maestroCertificateDomain + clientName: maestroConsumerName + keyVaultCertificateName: maestroConsumerName + certificateAccessManagedIdentityPrincipalId: maestroAgentManagedIdentityPrincipalId + } +} -module evengGridAccess './maestro-eventgrid-access.bicep' = { - name: 'event-grid-access-${uniqueString(maestroConsumerName)}' +module evengGridAccess 'maestro-eventgrid-access.bicep' = { + name: '${deployment().name}-eg-access' scope: resourceGroup(maestroInfraResourceGroup) params: { eventGridNamespaceName: maestroEventGridNamespaceName - keyVaultName: maestroKeyVaultName - kvCertOfficerManagedIdentityName: maestroKeyVaultOfficerManagedIdentityName - certDomain: maestroKeyVaultCertificateDomain clientName: maestroConsumerName clientRole: 'consumer' - certificateAccessManagedIdentityPrincipalId: maestroServerManagedIdentityPrincipalId - location: location + certificateThumbprint: eventGridClientCert.outputs.certificateThumbprint + certificateSAN: eventGridClientCert.outputs.certificateSAN } } diff --git a/dev-infrastructure/modules/maestro/maestro-eventgrid-access.bicep b/dev-infrastructure/modules/maestro/maestro-eventgrid-access.bicep index c3b982f4c..3a8868011 100644 --- a/dev-infrastructure/modules/maestro/maestro-eventgrid-access.bicep +++ b/dev-infrastructure/modules/maestro/maestro-eventgrid-access.bicep @@ -2,33 +2,18 @@ This module manages access to EventGrid for a maestro client, which can be the server or a consumer. -- Creates a certificate in Key Vault signed by the specified issuer. - For dev environments `Self` is used as issuer, for higher environments - OneCertV2 Private will be used. - An MQTT client is registered within eventgrid. Depending on the certificate issuer, the certificate validation schema will be thumbprint based for self-signed certificates and DNS based for OneCertV2 Private certificates. - The MQTT client is placed into the right MQTT client group based on the client role. This defines the topic access permissions for the client. -- The specified managed identity `certificateAccessManagedIdentityPrincipalId` - is granted access to the certificate in Key Vault. This will be leveraged - with CSI secret store to access the certificate from the maestro pods. -Execution scope: the resourcegroup of the maestro infrastructure +Execution scope: the resourcegroup of the eventgrid namespace instance */ @description('The EventGrid Namespace name where access will be managed') param eventGridNamespaceName string -@description('The Key Vault name where the certificate for Event Grid access will be stored') -param keyVaultName string - -@description('The name of the managed identity that will be used to manage the certificate in Key Vault') -param kvCertOfficerManagedIdentityName string - -@description('The base domain name to be used for the certificates DNS name.') -param certDomain string - @description('The name of the client that will be created in the EventGrid Namespace') param clientName string @@ -39,42 +24,20 @@ param clientName string ]) param clientRole string -@description('Grant this managed identity access to the certificate in Key Vault.') -param certificateAccessManagedIdentityPrincipalId string - @description('The issuer of the certificate.') param certificateIssuer string = 'Self' -param location string +@description('The thumbprint of the certificate that should get access. Dont use in production') +param certificateThumbprint string -var clientAuthenticationName = '${clientName}.${certDomain}' +@description('The subject alternative name of the certificate') +param certificateSAN string resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' existing = { name: eventGridNamespaceName } -resource kvCertOfficerManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { - name: kvCertOfficerManagedIdentityName -} - -// certificate for MQTT authentication -module clientCertificate '../key-vault-cert.bicep' = { - name: '${deployment().name}-client-cert' - params: { - location: location - keyVaultName: keyVaultName - subjectName: 'CN=${clientName}' - certName: clientName - keyVaultManagedIdentityId: kvCertOfficerManagedIdentity.id - dnsNames: [ - clientAuthenticationName - ] - // todo - use Private OnceCertV2 in higher environments - issuerName: certificateIssuer - } -} - -// D O N ' T U S E T H I S I N P R O D U C T I O N +// D O N ' T U S E T H U M B P R I N T I N P R O D U C T I O N // eventgrid MQTT client trusting the certificate by thumbprint if // Key Vault self-signed certificates are used. trusting self-signed certificates // as CAs is not supported in EventGrid @@ -82,14 +45,14 @@ resource mqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' name: clientName parent: eventGridNamespace properties: { - authenticationName: clientAuthenticationName + authenticationName: certificateSAN attributes: { role: clientRole consumer_name: clientName } clientCertificateAuthentication: { allowedThumbprints: [ - clientCertificate.outputs.Thumbprint + certificateThumbprint ] validationScheme: 'ThumbprintMatch' } @@ -99,35 +62,3 @@ resource mqttClient 'Microsoft.EventGrid/namespaces/clients@2023-12-15-preview' // TODO - implement issuer CA registration with EventGrid + register the mqtt client with // the DnsMatchesAuthenticationName authentication validation scheme - -var keyVaultSecretUserRoleId = subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions/', - '4633458b-17de-408a-b874-0445c86b69e6' -) - -resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { - name: keyVaultName -} - -// grant permissions on the secret that contains the certificate - -resource secret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' existing = { - parent: kv - name: clientName -} - -resource secretAccessPermission 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: secret - name: guid(certificateAccessManagedIdentityPrincipalId, keyVaultSecretUserRoleId, kv.id) - properties: { - roleDefinitionId: keyVaultSecretUserRoleId - principalId: certificateAccessManagedIdentityPrincipalId - principalType: 'ServicePrincipal' - } -} - -// output - -output KeyVaultCertId string = clientCertificate.outputs.KeyVaultCertId -output KeyVaultCertName string = clientName -output EventGridHostname string = eventGridNamespace.properties.topicSpacesConfiguration.hostname diff --git a/dev-infrastructure/modules/maestro/maestro-infra.bicep b/dev-infrastructure/modules/maestro/maestro-infra.bicep index 24ae8cec2..e52dbc099 100644 --- a/dev-infrastructure/modules/maestro/maestro-infra.bicep +++ b/dev-infrastructure/modules/maestro/maestro-infra.bicep @@ -1,23 +1,11 @@ /* This module creates the infrastructure required by maestro to run. This includes: -- A KeyVault where the client certificates for EventGrid MQTT broker access - are generated and stored -- A managed identity to create and manage certificates in Key Vault. This is - used by the maestro-eventgrid-access bicep module deploymentscripts. - - Why is this needed? There are no bicep modules for KeyVault certificate management, - so we need deploymentscripts + a managed identity with Key Vault access to run them. - - Create an EventGrid namespaces instance with MQTT enabled. - Create EventGrid client groups for the server and consumers and define topic access permissions. Execution scope: the resourcegroup of the maestro infrastructure - -TODO: -- Key Vault network access restrictions (e.g. privatelink) -- EventGrid network access restrictions (e.g. privatelink) */ @description('The Maestro Event Grid Namespaces name') @@ -29,79 +17,12 @@ param location string @description('The maximum client sessions per authentication name for the EventGrid MQTT broker') param maxClientSessionsPerAuthName int -@description('The name for the Key Vault for Maestro certificates') -param maestroKeyVaultName string - -@description('The name for the Managed Identity that will be created for Key Vault Certificate management.') -param kvCertOfficerManagedIdentityName string - @description('Allow public network access to the EventGrid Namespace') @allowed([ 'Enabled' 'Disabled' ]) -param publicNetworkAccess string = 'Enabled' - -// -// K E Y V A U L T -// - -resource kv 'Microsoft.KeyVault/vaults@2023-07-01' = { - name: maestroKeyVaultName - location: location - tags: { - resourceGroup: resourceGroup().name - } - properties: { - accessPolicies: [] - enableRbacAuthorization: true - enabledForDeployment: false - enabledForDiskEncryption: false - enabledForTemplateDeployment: false - enableSoftDelete: false - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Allow' - ipRules: [ - { - // TODO: restrict in higher environments - value: '0.0.0.0/0' - } - ] - } - // TODO: disabled in higher environments - publicNetworkAccess: 'Enabled' - sku: { - family: 'A' - name: 'standard' - } - tenantId: subscription().tenantId - } -} - -// -// C E R T I F I C A T E O F F I C E R M S I -// - -resource kvCertOfficerManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: kvCertOfficerManagedIdentityName - location: location -} - -var keyVaultCertificateOfficerRoleId = subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions/', - 'a4417e6f-fecd-4de8-b567-7b0420556985' -) - -resource kvManagedIdentityRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: kv - name: guid(kvCertOfficerManagedIdentity.id, keyVaultCertificateOfficerRoleId, kv.id) - properties: { - roleDefinitionId: keyVaultCertificateOfficerRoleId - principalId: kvCertOfficerManagedIdentity.properties.principalId - principalType: 'ServicePrincipal' - } -} +param publicNetworkAccess string // // E V E N T G R I D @@ -116,7 +37,6 @@ resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2024-06-01-preview' capacity: 1 } properties: { - isZoneRedundant: true publicNetworkAccess: publicNetworkAccess topicSpacesConfiguration: { state: 'Enabled' @@ -253,6 +173,3 @@ resource maestroConsumersPublishTopicspacePermissionBinding 'Microsoft.EventGrid topicSpaceName: maestroConsumersPublishTopicspace.name } } - -output keyVaultName string = kv.name -output eventGridNamespaceName string = eventGridNamespace.name diff --git a/dev-infrastructure/modules/maestro/maestro-server.bicep b/dev-infrastructure/modules/maestro/maestro-server.bicep index 1cb940821..b83a5f8ac 100644 --- a/dev-infrastructure/modules/maestro/maestro-server.bicep +++ b/dev-infrastructure/modules/maestro/maestro-server.bicep @@ -1,20 +1,21 @@ /* This module is responsible for: + - setting up Postgres access for the maestro server - setting up EventGrid access for the maestro server Execution scope: the resourcegroup of the AKS cluster where the maestro server will be deployed. - -TODO: -- once Key Vault and EventGrid have network access restrictions enabled, - this module needs to be enhanced to manage access to both (e.g. privatelink) */ param maestroInfraResourceGroup string param maestroEventGridNamespaceName string -param maestroKeyVaultName string -param maestroKeyVaultOfficerManagedIdentityName string -param maestroKeyVaultCertificateDomain string +param certKeyVaultName string +param certKeyVaultResourceGroup string +param keyVaultOfficerManagedIdentityName string +param maestroCertificateDomain string + +@description('The name of the MQTT client that will be created in the EventGrid Namespace') +param mqttClientName string @description('Whether to deploy the Postgres server for Maestro') param deployPostgres bool @@ -22,6 +23,9 @@ param deployPostgres bool @description('The name of the Postgres server for Maestro') param postgresServerName string +@description('The version of the Postgres server for Maestro') +param postgresServerMinTLSVersion string + @description('The version of the Postgres server for Maestro') param postgresServerVersion string @@ -48,7 +52,7 @@ param privateEndpointSubnetId string = '' param privateEndpointVnetId string = '' @description('The name of the database to create for Maestro') -param maestroDatabaseName string = 'maestro' +param maestroDatabaseName string @description('The name of the Managed Identity for the Maestro cluster service') param maestroServerManagedIdentityName string @@ -56,27 +60,26 @@ param maestroServerManagedIdentityName string @description('The principal ID of the Managed Identity for the Maestro cluster service') param maestroServerManagedIdentityPrincipalId string -param location string +@description('The resource ID of the managed identity used to manage the Postgres server') +param postgresAdministrationManagedIdentityId string // // P O S T G R E S // -resource postgresAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: '${postgresServerName}-db-admin-msi' - location: location -} +import * as res from '../resource.bicep' module postgres '../postgres/postgres.bicep' = if (deployPostgres) { name: '${deployment().name}-postgres' params: { name: postgresServerName + minTLSVersion: postgresServerMinTLSVersion databaseAdministrators: [ // add the dedicated admin managed identity as administrator // this one is going to be used to manage DB access { - principalId: postgresAdminManagedIdentity.properties.principalId - principalName: postgresAdminManagedIdentity.name + principalId: reference(postgresAdministrationManagedIdentityId, '2023-01-31').principalId + principalName: res.msiRefFromId(postgresAdministrationManagedIdentityId).name principalType: 'ServicePrincipal' } ] @@ -116,7 +119,7 @@ module csManagedIdentityDatabaseAccess '../postgres/postgres-access.bicep' = if name: '${deployment().name}-maestro-db-access' params: { postgresServerName: postgresServerName - postgresAdminManagedIdentityName: postgresAdminManagedIdentity.name + postgresAdministrationManagedIdentityId: postgresAdministrationManagedIdentityId databaseName: maestroDatabaseName newUserName: maestroServerManagedIdentityName newUserPrincipalId: maestroServerManagedIdentityPrincipalId @@ -127,20 +130,30 @@ module csManagedIdentityDatabaseAccess '../postgres/postgres-access.bicep' = if } // -// E V E N T G R I D +// E V E N T G R I D A C C E S S // -module evengGridAccess './maestro-eventgrid-access.bicep' = { - name: '${deployment().name}-event-grid-access' +module eventGridClientCert 'maestro-access-cert.bicep' = { + name: '${deployment().name}-eg-crt-${uniqueString(mqttClientName)}' + scope: resourceGroup(certKeyVaultResourceGroup) + params: { + keyVaultName: certKeyVaultName + kvCertOfficerManagedIdentityResourceId: keyVaultOfficerManagedIdentityName + certDomain: maestroCertificateDomain + clientName: mqttClientName + keyVaultCertificateName: mqttClientName + certificateAccessManagedIdentityPrincipalId: maestroServerManagedIdentityPrincipalId + } +} + +module evengGridAccess 'maestro-eventgrid-access.bicep' = { + name: '${deployment().name}-eg-access' scope: resourceGroup(maestroInfraResourceGroup) params: { eventGridNamespaceName: maestroEventGridNamespaceName - keyVaultName: maestroKeyVaultName - kvCertOfficerManagedIdentityName: maestroKeyVaultOfficerManagedIdentityName - certDomain: maestroKeyVaultCertificateDomain - clientName: 'maestro-server' + clientName: mqttClientName clientRole: 'server' - certificateAccessManagedIdentityPrincipalId: maestroServerManagedIdentityPrincipalId - location: location + certificateThumbprint: eventGridClientCert.outputs.certificateThumbprint + certificateSAN: eventGridClientCert.outputs.certificateSAN } } diff --git a/dev-infrastructure/modules/metrics/datacollection.bicep b/dev-infrastructure/modules/metrics/datacollection.bicep new file mode 100644 index 000000000..922905544 --- /dev/null +++ b/dev-infrastructure/modules/metrics/datacollection.bicep @@ -0,0 +1,60 @@ +param azureMonitorWorkspaceName string +param azureMonitorWorkspaceLocation string +param aksClusterName string +param regionalResourceGroup string + +var dceName = take('MSProm-${azureMonitorWorkspaceLocation}-${aksClusterName}', 44) +var dcrName = take('MSProm-${azureMonitorWorkspaceLocation}-${aksClusterName}', 44) + +resource amw 'microsoft.monitor/accounts@2021-06-03-preview' existing = { + name: azureMonitorWorkspaceName + scope: resourceGroup(regionalResourceGroup) +} + +resource dce 'Microsoft.Insights/dataCollectionEndpoints@2022-06-01' = { + name: dceName + location: azureMonitorWorkspaceLocation + kind: 'Linux' + properties: {} +} + +resource dcr 'Microsoft.Insights/dataCollectionRules@2022-06-01' = { + name: dcrName + location: azureMonitorWorkspaceLocation + kind: 'Linux' + properties: { + dataCollectionEndpointId: dce.id + dataFlows: [ + { + destinations: [ + 'MonitoringAccount1' + ] + streams: [ + 'Microsoft-PrometheusMetrics' + ] + } + ] + dataSources: { + prometheusForwarder: [ + { + name: 'PrometheusDataSource' + streams: [ + 'Microsoft-PrometheusMetrics' + ] + labelIncludeFilter: {} + } + ] + } + description: 'DCR for Azure Monitor Metrics Profile (Managed Prometheus)' + destinations: { + monitoringAccounts: [ + { + accountResourceId: amw.id + name: 'MonitoringAccount1' + } + ] + } + } +} + +output dcrId string = dcr.id diff --git a/dev-infrastructure/modules/metrics/metrics.bicep b/dev-infrastructure/modules/metrics/metrics.bicep index a5dd65972..43a1c7899 100644 --- a/dev-infrastructure/modules/metrics/metrics.bicep +++ b/dev-infrastructure/modules/metrics/metrics.bicep @@ -11,24 +11,7 @@ param monitorName string @description('Metrics global Grafana name') param grafanaName string -@description('The admin group principal ID to manage Grafana') -param grafanaAdminGroupPrincipalId string - -var grafanaAdmin = { - principalId: grafanaAdminGroupPrincipalId - principalType: 'group' -} - -module grafana 'br:arointacr.azurecr.io/grafana.bicep:metrics.20240814.1' = { - name: 'grafana' - params: { - msiName: msiName - grafanaName: grafanaName - grafanaAdmin: grafanaAdmin - } -} - -module monitor 'br:arointacr.azurecr.io/monitor.bicep:monitor.20241004.1' = { +module monitor 'monitor.bicep' = { name: 'monitor' params: { globalResourceGroup: globalResourceGroup @@ -36,11 +19,7 @@ module monitor 'br:arointacr.azurecr.io/monitor.bicep:monitor.20241004.1' = { monitorName: monitorName grafanaName: grafanaName } - dependsOn: [ - grafana - ] } output msiId string = monitor.outputs.msiId -output grafanaId string = monitor.outputs.grafanaId output monitorId string = monitor.outputs.monitorId diff --git a/dev-infrastructure/modules/metrics/monitor.bicep b/dev-infrastructure/modules/metrics/monitor.bicep new file mode 100644 index 000000000..4e155b625 --- /dev/null +++ b/dev-infrastructure/modules/metrics/monitor.bicep @@ -0,0 +1,57 @@ +@description('Metrics global resource group name') +param globalResourceGroup string + +@description('Metrics global MSI name') +param msiName string + +@description('Metrics global Grafana name') +param grafanaName string + +@description('Metrics region monitor name') +param monitorName string = 'aro-hcp-monitor' + +resource monitor 'microsoft.monitor/accounts@2021-06-03-preview' = { + name: monitorName + location: resourceGroup().location +} + +module defaultRuleGroups 'rules/defaultRecordingRuleGroups.bicep' ={ + name: 'defaultRecordingRuleGroups' + params: { + azureMonitorWorkspaceLocation: resourceGroup().location + azureMonitorWorkspaceName: monitorName + regionalResourceGroup: resourceGroup().name + } +} +// Assign the Monitoring Data Reader role to the Azure Managed Grafana system-assigned managed identity at the workspace scope +var dataReader = 'b0d8363b-8ddd-447d-831f-62ca05bff136' + +resource msi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: msiName + scope: resourceGroup(globalResourceGroup) +} + +resource grafana 'Microsoft.Dashboard/grafana@2023-09-01' existing = { + name: grafanaName + scope: resourceGroup(globalResourceGroup) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(monitor.id, grafana.id, dataReader) + scope: monitor + properties: { + principalId: grafana.identity.principalId + principalType: 'ServicePrincipal' + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', dataReader) + } +} + +module prometheus 'rules/prometheusAlertingRules.bicep' = { + name: 'prometheusAlertingRules' + params: { + azureMonitoring: monitor.id + } +} + +output msiId string = msi.id +output monitorId string = monitor.id diff --git a/dev-infrastructure/modules/metrics/rules/defaultRecordingRuleGroups.bicep b/dev-infrastructure/modules/metrics/rules/defaultRecordingRuleGroups.bicep new file mode 100644 index 000000000..5578470df --- /dev/null +++ b/dev-infrastructure/modules/metrics/rules/defaultRecordingRuleGroups.bicep @@ -0,0 +1,168 @@ +param regionalResourceGroup string +param azureMonitorWorkspaceName string +param azureMonitorWorkspaceLocation string + +resource amw 'microsoft.monitor/accounts@2021-06-03-preview' existing = { + name: azureMonitorWorkspaceName + scope: resourceGroup(regionalResourceGroup) +} + +// default recording rules from https://github.com/Azure/prometheus-collector/blob/main/AddonBicepTemplate/FullAzureMonitorMetricsProfile.bicep +resource kubernetesRecordingRuleGroup 'Microsoft.AlertsManagement/prometheusRuleGroups@2023-03-01' = { + name: 'all-clusters-defaultK8sRecordingRules' + location: azureMonitorWorkspaceLocation + properties: { + description: 'default kubernetes recording rules' + scopes: [amw.id] + enabled: true + interval: 'PT1M' + rules: [ + { + record: 'node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate' + expression: 'sum by (cluster, namespace, pod, container) ( irate(container_cpu_usage_seconds_total{job="cadvisor", image!=""}[5m])) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) ( 1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}))' + } + { + record: 'node_namespace_pod_container:container_memory_working_set_bytes' + expression: 'container_memory_working_set_bytes{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' + } + { + record: 'node_namespace_pod_container:container_memory_rss' + expression: 'container_memory_rss{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' + } + { + record: 'node_namespace_pod_container:container_memory_cache' + expression: 'container_memory_cache{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' + } + { + record: 'node_namespace_pod_container:container_memory_swap' + expression: 'container_memory_swap{job="cadvisor", image!=""}* on (namespace, pod) group_left(node) topk by(namespace, pod) (1, max by(namespace, pod, node) (kube_pod_info{node!=""}))' + } + { + record: 'cluster:namespace:pod_memory:active:kube_pod_container_resource_requests' + expression: 'kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' + } + { + record: 'namespace_memory:kube_pod_container_resource_requests:sum' + expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' + } + { + record: 'cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests' + expression: 'kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' + } + { + record: 'namespace_cpu:kube_pod_container_resource_requests:sum' + expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_requests{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' + } + { + record: 'cluster:namespace:pod_memory:active:kube_pod_container_resource_limits' + expression: 'kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1))' + } + { + record: 'namespace_memory:kube_pod_container_resource_limits:sum' + expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="memory",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' + } + { + record: 'cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits' + expression: 'kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} * on (namespace, pod, cluster)group_left() max by (namespace, pod, cluster) ( (kube_pod_status_phase{phase=~"Pending|Running"} == 1) )' + } + { + record: 'namespace_cpu:kube_pod_container_resource_limits:sum' + expression: 'sum by (namespace, cluster) ( sum by (namespace, pod, cluster) ( max by (namespace, pod, container, cluster) ( kube_pod_container_resource_limits{resource="cpu",job="kube-state-metrics"} ) * on(namespace, pod, cluster) group_left() max by (namespace, pod, cluster) ( kube_pod_status_phase{phase=~"Pending|Running"} == 1 ) ))' + } + { + record: 'namespace_workload_pod:kube_pod_owner:relabel' + expression: 'max by (cluster, namespace, workload, pod) ( label_replace( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, "replicaset", "$1", "owner_name", "(.*)" ) * on(replicaset, namespace) group_left(owner_name) topk by(replicaset, namespace) ( 1, max by (replicaset, namespace, owner_name) ( kube_replicaset_owner{job="kube-state-metrics"} ) ), "workload", "$1", "owner_name", "(.*)" ))' + labels: { + workload_type: 'deployment' + } + } + { + record: 'namespace_workload_pod:kube_pod_owner:relabel' + expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="DaemonSet"}, "workload", "$1", "owner_name", "(.*)" ))' + labels: { + workload_type: 'daemonset' + } + } + { + record: 'namespace_workload_pod:kube_pod_owner:relabel' + expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="StatefulSet"}, "workload", "$1", "owner_name", "(.*)" ))' + labels: { + workload_type: 'statefulset' + } + } + { + record: 'namespace_workload_pod:kube_pod_owner:relabel' + expression: 'max by (cluster, namespace, workload, pod) ( label_replace( kube_pod_owner{job="kube-state-metrics", owner_kind="Job"}, "workload", "$1", "owner_name", "(.*)" ))' + labels: { + workload_type: 'job' + } + } + { + record: ':node_memory_MemAvailable_bytes:sum' + expression: 'sum( node_memory_MemAvailable_bytes{job="node"} or ( node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"} )) by (cluster)' + } + { + record: 'cluster:node_cpu:ratio_rate5m' + expression: 'sum(rate(node_cpu_seconds_total{job="node",mode!="idle",mode!="iowait",mode!="steal"}[5m])) by (cluster) /count(sum(node_cpu_seconds_total{job="node"}) by (cluster, instance, cpu)) by (cluster)' + } + ] + } +} +// default recording rules from https://github.com/Azure/prometheus-collector/blob/main/AddonBicepTemplate/FullAzureMonitorMetricsProfile.bicep +resource nodeRecordingRuleGroup 'Microsoft.AlertsManagement/prometheusRuleGroups@2023-03-01' = { + name: 'all-clusters-defaultNodeRecordingRules' + + location: azureMonitorWorkspaceLocation + properties: { + description: 'default node recording rules' + scopes: [amw.id] + enabled: true + interval: 'PT1M' + rules: [ + { + record: 'instance:node_num_cpu:sum' + expression: 'count without (cpu, mode) ( node_cpu_seconds_total{job="node",mode="idle"})' + } + { + record: 'instance:node_cpu_utilisation:rate5m' + expression: '1 - avg without (cpu) ( sum without (mode) (rate(node_cpu_seconds_total{job="node", mode=~"idle|iowait|steal"}[5m])))' + } + { + record: 'instance:node_load1_per_cpu:ratio' + expression: '( node_load1{job="node"}/ instance:node_num_cpu:sum{job="node"})' + } + { + record: 'instance:node_memory_utilisation:ratio' + expression: '1 - ( ( node_memory_MemAvailable_bytes{job="node"} or ( node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"} ) )/ node_memory_MemTotal_bytes{job="node"})' + } + { + record: 'instance:node_vmstat_pgmajfault:rate5m' + expression: 'rate(node_vmstat_pgmajfault{job="node"}[5m])' + } + { + record: 'instance_device:node_disk_io_time_seconds:rate5m' + expression: 'rate(node_disk_io_time_seconds_total{job="node", device!=""}[5m])' + } + { + record: 'instance_device:node_disk_io_time_weighted_seconds:rate5m' + expression: 'rate(node_disk_io_time_weighted_seconds_total{job="node", device!=""}[5m])' + } + { + record: 'instance:node_network_receive_bytes_excluding_lo:rate5m' + expression: 'sum without (device) ( rate(node_network_receive_bytes_total{job="node", device!="lo"}[5m]))' + } + { + record: 'instance:node_network_transmit_bytes_excluding_lo:rate5m' + expression: 'sum without (device) ( rate(node_network_transmit_bytes_total{job="node", device!="lo"}[5m]))' + } + { + record: 'instance:node_network_receive_drop_excluding_lo:rate5m' + expression: 'sum without (device) ( rate(node_network_receive_drop_total{job="node", device!="lo"}[5m]))' + } + { + record: 'instance:node_network_transmit_drop_excluding_lo:rate5m' + expression: 'sum without (device) ( rate(node_network_transmit_drop_total{job="node", device!="lo"}[5m]))' + } + ] + } +} diff --git a/dev-infrastructure/modules/metrics/rules/prometheusAlertingRules.bicep b/dev-infrastructure/modules/metrics/rules/prometheusAlertingRules.bicep new file mode 100644 index 000000000..8f63e54c8 --- /dev/null +++ b/dev-infrastructure/modules/metrics/rules/prometheusAlertingRules.bicep @@ -0,0 +1,25 @@ +param azureMonitoring string + +resource prometheusRuleGroups 'Microsoft.AlertsManagement/prometheusRuleGroups@2023-03-01' = { + name: 'hcp-prometheus-rules' + location: resourceGroup().location + properties: { + rules: [ + { + // Copy from https://github.com/Azure/prometheus-collector/blob/main/AddonBicepTemplate/recommendedMetricAlerts.bicep + alert: 'KubePodImagePull' + expression: 'max_over_time(kube_pod_container_status_waiting_reason{reason="ImagePullBackOff", job="kube-state-metrics"}[5m]) >= 1' + for: 'PT15M' + enabled: true + severity: 4 + resolveConfiguration: { + autoResolved: true + timeToResolve: 'PT10M' + } + } + ] + scopes: [ + azureMonitoring + ] + } +} diff --git a/dev-infrastructure/modules/network/publicipaddress.bicep b/dev-infrastructure/modules/network/publicipaddress.bicep new file mode 100644 index 000000000..56624f6de --- /dev/null +++ b/dev-infrastructure/modules/network/publicipaddress.bicep @@ -0,0 +1,43 @@ +@minLength(5) +@maxLength(80) +@description('Name of the Azure Public IP address') +param name string + +@description('Location of the Public IP address') +param location string + +@description('List of Availability Zones for the Public IP address') +param zones array = [] + +@description('IPTags for the Public IP address') +param ipTags array = [] + +@description('Tags to set on the Public IP address') +param tags object = {} + +@description('The Public IP address\'s role assignment properties') +param roleAssignmentProperties object = {} + +resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2024-05-01' = { + name: name + location: location + tags: tags + properties: { + ipTags: ipTags + publicIPAddressVersion: 'IPv4' + publicIPAllocationMethod: 'Static' + } + sku: { + name: 'Standard' + tier: 'Regional' + } + zones: zones +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (roleAssignmentProperties != {}) { + name: guid(publicIPAddress.id, roleAssignmentProperties.principalId, roleAssignmentProperties.roleDefinitionId) + properties: roleAssignmentProperties + scope: publicIPAddress +} + +output ipAddress string = publicIPAddress.properties.ipAddress diff --git a/dev-infrastructure/modules/oidc/main.bicep b/dev-infrastructure/modules/oidc/main.bicep index 5ea8e054d..290e691f8 100644 --- a/dev-infrastructure/modules/oidc/main.bicep +++ b/dev-infrastructure/modules/oidc/main.bicep @@ -4,7 +4,7 @@ param location string param storageAccountName string param rpMsiName string param skuName string -param aroDevopsMsiId string +param msiId string param deploymentScriptLocation string param enabledAFD bool = false @@ -18,9 +18,9 @@ module storageAccount 'storage.bicep' = { location: location principalId: reference(rpMsiResourceURI, '2023-01-31').principalId skuName: skuName - aroDevopsMsiId: aroDevopsMsiId + msiId: msiId deploymentScriptLocation: deploymentScriptLocation - publicBlobAccess: !enabledAFD + isDevEnv: !enabledAFD } } diff --git a/dev-infrastructure/modules/oidc/storage.bicep b/dev-infrastructure/modules/oidc/storage.bicep index 5ff87cf87..4768bf689 100644 --- a/dev-infrastructure/modules/oidc/storage.bicep +++ b/dev-infrastructure/modules/oidc/storage.bicep @@ -16,22 +16,25 @@ param location string ]) param skuName string = 'Standard_ZRS' -@description('Whether or not the Blobs in the Storage Account should be publicly accessible.') -param publicBlobAccess bool - @description('The service principal ID to be added to Azure Storage account.') param principalId string = '' @description('Id of the MSI that will be used to run the deploymentScript') -param aroDevopsMsiId string +param msiId string // Since deployment script is limted to specific regions, we run deployment script from the same location as the private link. // The location where deployment script run doesn't matter as it will be removed once the script is completed to enable static website on storage account. param deploymentScriptLocation string +param isDevEnv bool = false + +// Storage Account Contributor: Lets you manage storage accounts, including accessing storage account keys which provide full access to storage account data. +// https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-account-contributor +var storageAccountContributorRole = '17d1049b-9a84-46fb-8f53-869881c3d3ab' + // https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#storage-blob-data-contributor // Storage Blob Data Contributor: Grants access to Read, write, and delete Azure Storage containers and blobs -var roleDefinitionId = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' +var storageBlobDataContributorRole = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' var scriptToRun = '../../scripts/storage.sh' @@ -45,20 +48,30 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { properties: { accessTier: 'Hot' supportsHttpsTrafficOnly: true - allowBlobPublicAccess: publicBlobAccess + allowBlobPublicAccess: isDevEnv minimumTlsVersion: 'TLS1_2' allowSharedKeyAccess: false - publicNetworkAccess: 'Enabled' // we can switch to private endpoint later + publicNetworkAccess: 'Enabled' } } resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (principalId != '') { - name: guid(storageAccount.id, principalId, roleDefinitionId) + name: guid(storageAccount.id, principalId, storageBlobDataContributorRole) scope: storageAccount properties: { principalId: principalId principalType: 'ServicePrincipal' - roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId) + roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataContributorRole) + } +} + +resource storageAccountContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, msiId, storageAccountContributorRole) + scope: storageAccount + properties: { + principalId: reference(msiId, '2023-01-31').principalId + principalType: 'ServicePrincipal' + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageAccountContributorRole) } } @@ -69,7 +82,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { identity: { type: 'UserAssigned' userAssignedIdentities: { - '${aroDevopsMsiId}': {} + '${msiId}': {} } } properties: { @@ -85,6 +98,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { } dependsOn: [ storageAccount + storageAccountContributor ] } diff --git a/dev-infrastructure/modules/postgres/postgres-access.bicep b/dev-infrastructure/modules/postgres/postgres-access.bicep index 617bff66d..1f06c93b4 100644 --- a/dev-infrastructure/modules/postgres/postgres-access.bicep +++ b/dev-infrastructure/modules/postgres/postgres-access.bicep @@ -6,8 +6,8 @@ The user will also be enabled for entra authentication. @description('The name of the postgres server that will be managed') param postgresServerName string -@description('The name of the managed identity that will be used to manage access in the database') -param postgresAdminManagedIdentityName string +@description('The resource ID of the managed identity that will be used to manage access in the database') +param postgresAdministrationManagedIdentityId string @description('The principal ID / object ID of the managed identity that will be granted access to') param newUserPrincipalId string @@ -34,15 +34,21 @@ var sqlScriptLines = [ ';' 'SECURITY LABEL for "pgaadauth" on role "${newUserName}" is \'aadauth,oid=${newUserPrincipalId},type=service\';' 'GRANT ALL PRIVILEGES ON DATABASE ${databaseName} TO "${newUserName}";' - 'GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "${newUserName}";' + 'GRANT ALL ON SCHEMA public TO "${newUserName}";' + 'GRANT USAGE ON SCHEMA public TO "${newUserName}";' + 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "${newUserName}";' + '\\c ${databaseName};' + 'GRANT ALL ON SCHEMA public TO "${newUserName}";' + 'GRANT USAGE ON SCHEMA public TO "${newUserName}";' + 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "${newUserName}";' ] -module csManagedIdentityDatabaseAccess 'postgres-sql.bicep' = { +module managedIdentityDatabaseAccess 'postgres-sql.bicep' = { name: '${deployment().name}-db-access' params: { postgresServerName: postgres.properties.fullyQualifiedDomainName databaseName: 'postgres' // access configuration is managed in the postgres DB - postgresAdminManagedIdentityName: postgresAdminManagedIdentityName + postgresAdministrationManagedIdentityId: postgresAdministrationManagedIdentityId sqlScript: string(join(sqlScriptLines, '\n')) } } diff --git a/dev-infrastructure/modules/postgres/postgres-sql.bicep b/dev-infrastructure/modules/postgres/postgres-sql.bicep index 9744f8cdf..7935948d8 100644 --- a/dev-infrastructure/modules/postgres/postgres-sql.bicep +++ b/dev-infrastructure/modules/postgres/postgres-sql.bicep @@ -8,17 +8,15 @@ param postgresServerName string @description('The database name where an SQL script will be executed') param databaseName string -@description('The name of the user-assigned managed identity that will be used to execute the SQL script') -param postgresAdminManagedIdentityName string +@description('The resource ID of the user-assigned managed identity that will be used to execute the SQL script') +param postgresAdministrationManagedIdentityId string @description('The SQL script to execute on the PostgreSQL server') param sqlScript string -param forceUpdateTag string = guid('${sqlScript}/${postgresServerName}/${databaseName}+${postgresAdminManagedIdentityName}') +param forceUpdateTag string = guid('${sqlScript}/${postgresServerName}/${databaseName}/${postgresAdministrationManagedIdentityId}') -resource postgresAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { - name: postgresAdminManagedIdentityName -} +import * as res from '../resource.bicep' resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { name: deployment().name @@ -27,7 +25,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { identity: { type: 'UserAssigned' userAssignedIdentities: { - '${postgresAdminManagedIdentity.id}': {} + '${postgresAdministrationManagedIdentityId}': {} } } @@ -58,7 +56,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { } { name: 'PGUSER' - value: postgresAdminManagedIdentity.name + value: res.msiRefFromId(postgresAdministrationManagedIdentityId).name } ] timeout: 'PT30M' diff --git a/dev-infrastructure/modules/postgres/postgres.bicep b/dev-infrastructure/modules/postgres/postgres.bicep index 0b9766e4d..d62d2ed22 100644 --- a/dev-infrastructure/modules/postgres/postgres.bicep +++ b/dev-infrastructure/modules/postgres/postgres.bicep @@ -9,6 +9,7 @@ param location string = resourceGroup().location param sku string = 'Standard_D2s_v3' param tier string = 'GeneralPurpose' +param minTLSVersion string type DatabaseAdministrators = { principalId: string @@ -109,6 +110,15 @@ resource postgres 'Microsoft.DBforPostgreSQL/flexibleServers@2023-12-01-preview' } } +resource postgres_allow_public_access 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-12-01-preview' = if (!private) { + name: 'AllowPublicAccess' + parent: postgres + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '255.255.255.255' + } +} + resource postgres_allow_azure_firewall 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-12-01-preview' = { name: 'AllowAllAzureServicesAndResourcesWithinAzureIps' parent: postgres @@ -116,6 +126,7 @@ resource postgres_allow_azure_firewall 'Microsoft.DBforPostgreSQL/flexibleServer startIpAddress: '0.0.0.0' endIpAddress: '0.0.0.0' } + dependsOn: [postgres_allow_public_access] } @batchSize(1) @@ -145,6 +156,16 @@ resource postgres_config 'Microsoft.DBforPostgreSQL/flexibleServers/configuratio } ] +resource postgres_min_tls 'Microsoft.DBforPostgreSQL/flexibleServers/configurations@2023-12-01-preview' = { + name: 'ssl_min_protocol_version' + parent: postgres + properties: { + source: 'user-override' + value: minTLSVersion + } + dependsOn: [postgres_config] +} + @batchSize(1) resource postgres_database 'Microsoft.DBforPostgreSQL/flexibleServers/databases@2023-12-01-preview' = [ for database in databases: { @@ -154,7 +175,7 @@ resource postgres_database 'Microsoft.DBforPostgreSQL/flexibleServers/databases@ charset: database.charset collation: database.collation } - dependsOn: [postgres_config] + dependsOn: [postgres_min_tls] } ] @@ -165,67 +186,17 @@ output port int = 5432 // P R I V A T E E N D P O I N T // -var privateDnsZoneName = 'privatelink.postgres.database.azure.com' - -resource postgresPrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-01-01' = if (managedPrivateEndpoint) { - name: '${name}-pe' - location: location - properties: { - privateLinkServiceConnections: [ - { - name: '${name}-pe' - properties: { - groupIds: [ - 'postgresqlServer' - ] - privateLinkServiceId: postgres.id - } - } - ] - subnet: { - id: subnetId - } +module servicePostgresPrivateEndpoint '../private-endpoint.bicep' = if (managedPrivateEndpoint) { + name: '${deployment().name}-svcs-kv-pe' + params: { + location: location + subnetIds: [subnetId] + vnetId: vnetId + privateLinkServiceId: postgres.id + serviceType: 'postgres' + groupId: 'postgresqlServer' } dependsOn: [ postgres_database ] } - -resource postgresPrivateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = if (managedPrivateEndpoint) { - name: privateDnsZoneName - location: 'global' - properties: {} - dependsOn: [ - postgresPrivateEndpoint - ] -} - -resource postgresPrivateDnsZoneVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (managedPrivateEndpoint) { - parent: postgresPrivateEndpointDnsZone - name: 'postgres' - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: vnetId - } - } -} - -resource privateEndpointDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-09-01' = if (managedPrivateEndpoint) { - parent: postgresPrivateEndpoint - name: '${name}-dns-group' - properties: { - privateDnsZoneConfigs: [ - { - name: 'config1' - properties: { - privateDnsZoneId: postgresPrivateEndpointDnsZone.id - } - } - ] - } - dependsOn: [ - postgresPrivateDnsZoneVnetLink - ] -} diff --git a/dev-infrastructure/modules/private-endpoint.bicep b/dev-infrastructure/modules/private-endpoint.bicep index 84acff45e..0b73ea88c 100644 --- a/dev-infrastructure/modules/private-endpoint.bicep +++ b/dev-infrastructure/modules/private-endpoint.bicep @@ -3,12 +3,18 @@ param location string @description('The service type the private endpoint is created for') @allowed([ 'eventgrid' + 'keyvault' + 'cosmosdb' + 'postgres' ]) param serviceType string @description('The group id of the private endpoint service') @allowed([ 'topicspace' + 'vault' + 'Sql' + 'postgresqlServer' ]) param groupId string @@ -25,17 +31,29 @@ var endpointConfig = { eventgrid: { topicspace: 'privatelink.ts.eventgrid.azure.net' } + keyvault: { + vault: 'privatelink.vaultcore.azure.net' + } + cosmosdb: { + Sql: 'privatelink.documents.azure.com' + } + postgres: { + postgresqlServer: 'privatelink.postgres.database.azure.com' + } } -resource eventGridPrivateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { +resource privateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { name: endpointConfig[serviceType][groupId] location: 'global' properties: {} + dependsOn: [ + privatEndpoint + ] } resource privatEndpoint 'Microsoft.Network/privateEndpoints@2023-09-01' = [ for aksNodeSubnetId in subnetIds: { - name: '${serviceType}-${uniqueString(aksNodeSubnetId)}' + name: '${serviceType}-${uniqueString(aksNodeSubnetId, privateLinkServiceId)}' location: location properties: { privateLinkServiceConnections: [ @@ -63,17 +81,20 @@ resource privateEndpointDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZ { name: 'config1' properties: { - privateDnsZoneId: eventGridPrivateEndpointDnsZone.id + privateDnsZoneId: privateEndpointDnsZone.id } } ] } + dependsOn: [ + privateDnsZoneVnetLink + ] } ] -resource eventGridPrivateDnsZoneVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { +resource privateDnsZoneVnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { name: uniqueString('eventgrid-${uniqueString(vnetId)}') - parent: eventGridPrivateEndpointDnsZone + parent: privateEndpointDnsZone location: 'global' properties: { registrationEnabled: false diff --git a/dev-infrastructure/modules/resource.bicep b/dev-infrastructure/modules/resource.bicep new file mode 100644 index 000000000..38879bbb4 --- /dev/null +++ b/dev-infrastructure/modules/resource.bicep @@ -0,0 +1,25 @@ +// bicep func to extract subscription, resourcegroup from a resource id + +@export() +type resourceGroupReference = { + subscriptionId: string + name: string +} + +@export() +type msiRef = { + resourceGroup: resourceGroupReference + name: string +} + +@export() +func resourceGroupFromResourceId(resourceId string) resourceGroupReference => { + subscriptionId: split(resourceId, '/')[2] + name: split(resourceId, '/')[4] +} + +@export() +func msiRefFromId(msiResourceId string) msiRef => { + resourceGroup: resourceGroupFromResourceId(msiResourceId) + name: last(split(msiResourceId, '/')) +} diff --git a/dev-infrastructure/modules/rp-cosmos.bicep b/dev-infrastructure/modules/rp-cosmos.bicep index 9695aff95..035eac335 100644 --- a/dev-infrastructure/modules/rp-cosmos.bicep +++ b/dev-infrastructure/modules/rp-cosmos.bicep @@ -8,6 +8,7 @@ param location string param aksNodeSubnetId string param vnetId string param userAssignedMIs array +param private bool // Local Params var containers = [ @@ -62,7 +63,7 @@ resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2023-11-15' = { locationName: location } ] - publicNetworkAccess: 'Disabled' + publicNetworkAccess: private ? 'Disabled' : 'Enabled' enableAutomaticFailover: false enableMultipleWriteLocations: false isVirtualNetworkFilterEnabled: false @@ -82,59 +83,15 @@ resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2023-11-15' = { } } -resource cosmosDbPrivateEndpoint 'Microsoft.Network/privateEndpoints@2023-09-01' = { - name: '${name}-private-endpoint' - location: location - properties: { - privateLinkServiceConnections: [ - { - name: '${name}-private-endpoint' - properties: { - privateLinkServiceId: cosmosDbAccount.id - groupIds: [ - 'Sql' - ] - } - } - ] - subnet: { - id: aksNodeSubnetId - } - } -} - -resource cosmosPrivateEndpointDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { - // https://github.com/Azure/bicep/issues/12482 - // There is no environments().suffixes constant for this - name: 'privatelink.documents.azure.com' - location: 'global' - properties: {} -} - -resource cosmosPrivateEndpointDnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { - parent: cosmosPrivateEndpointDnsZone - name: 'link' - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: vnetId - } - } -} - -resource cosmosPrivateEndpointDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-09-01' = { - parent: cosmosDbPrivateEndpoint - name: '${name}-dns-group' - properties: { - privateDnsZoneConfigs: [ - { - name: 'config1' - properties: { - privateDnsZoneId: cosmosPrivateEndpointDnsZone.id - } - } - ] +module serviceCosmosdbPrivateEndpoint '../modules/private-endpoint.bicep' = { + name: '${deployment().name}-svcs-kv-pe' + params: { + location: location + subnetIds: [aksNodeSubnetId] + vnetId: vnetId + privateLinkServiceId: cosmosDbAccount.id + serviceType: 'cosmosdb' + groupId: 'Sql' } } diff --git a/dev-infrastructure/region-pipeline.yaml b/dev-infrastructure/region-pipeline.yaml new file mode 100644 index 000000000..3d2cf09c3 --- /dev/null +++ b/dev-infrastructure/region-pipeline.yaml @@ -0,0 +1,19 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Region +rolloutName: Region Rollout +resourceGroups: +- name: {{ .regionRG }} + subscription: {{ .svc.subscription }} + steps: + - name: region + action: ARM + template: templates/region.bicep + parameters: configurations/region.tmpl.bicepparam + deploymentLevel: ResourceGroup + - name: metrics-infra + action: ARM + template: modules/metrics/metrics.bicep + parameters: configurations/metrics.tmpl.bicepparam + deploymentLevel: ResourceGroup + dependsOn: + - region diff --git a/dev-infrastructure/scripts/add-grafana-datasource.sh b/dev-infrastructure/scripts/add-grafana-datasource.sh new file mode 100755 index 000000000..306aa5d41 --- /dev/null +++ b/dev-infrastructure/scripts/add-grafana-datasource.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# This script integrates an existing Azure Monitoring Workspace with the global Azure Managed Grafana Instance. +set -e + +GRAFANA_NAME=$1 +GRAFANA_RG=$2 +MONITOR_NAME=$3 +MONITOR_RG=$4 + +MONITOR_DATA_SOURCE=Managed_Prometheus_${MONITOR_NAME} + +DATA_SOURCE_URL=$(az grafana data-source list --name ${GRAFANA_NAME} \ + --resource-group ${GRAFANA_RG} \ + --query "[?contains(name, '${MONITOR_DATA_SOURCE}')].url | [0]" -o tsv) + +MONITOR_JSON=$(az monitor account list \ + --query "[?contains(name, '${MONITOR_NAME}')].{id:id, name: name, promUrl: metrics.prometheusQueryEndpoint}"[0]) + +PROM_QUERY_URL=$(echo $MONITOR_JSON | jq '.promUrl' -r ) + +MONITOR_ID=$(echo $MONITOR_JSON | jq '.id' ) + +# In dev resource groups are purged which causes data sources to become out of sync in the Azure Grafana Instance. +# If prometheus urls don't match then delete the integration to cleanup the data source. +if [[ -n "${DATA_SOURCE_URL}" && ${DATA_SOURCE_URL} != ${PROM_QUERY_URL} ]]; +then + echo "Removing ${MONITOR_NAME} integration from ${GRAFANA_NAME}" + az grafana integrations monitor delete \ + --name ${GRAFANA_NAME} \ + --resource-group ${GRAFANA_RG} \ + --monitor-name ${MONITOR_NAME} \ + --monitor-resource-group-name ${MONITOR_RG} \ + --skip-role-assignment true + + az resource wait --updated --ids $(az grafana show --name ${GRAFANA_NAME} --resource-group ${GRAFANA_RG} --query 'id' -o tsv) +fi + +MONITORS=$(az grafana integrations monitor list \ + --name ${GRAFANA_NAME} \ + --resource-group ${GRAFANA_RG}) + +IS_INTEGRATED=$(echo ${MONITORS} | jq "contains([${MONITOR_ID}])") + +if [[ ${IS_INTEGRATED} == "false" ]]; +then + echo "Adding monitor account ${MONITOR_NAME} as a data source to ${GRAFANA_NAME}" + az grafana integrations monitor add \ + --name ${GRAFANA_NAME} \ + --resource-group ${GRAFANA_RG} \ + --monitor-name ${MONITOR_NAME} \ + --monitor-resource-group-name ${MONITOR_RG} \ + --skip-role-assignments true + + az resource wait --updated --ids $(az grafana show --name ${GRAFANA_NAME} --resource-group ${GRAFANA_RG} --query 'id' -o tsv) +fi \ No newline at end of file diff --git a/dev-infrastructure/scripts/istio.sh b/dev-infrastructure/scripts/istio.sh new file mode 100755 index 000000000..3f4a8467c --- /dev/null +++ b/dev-infrastructure/scripts/istio.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +set -euo pipefail +ISTIO_NAMESPACE="aks-istio-system" +echo "********** Check istio is up and running **************" +ISTIO_PODS_COUNT=$(kubectl get pods -n ${ISTIO_NAMESPACE} -l istio.io/rev="${TARGET_VERSION}" --field-selector=status.phase=Running --no-headers | wc -l) +if [[ $ISTIO_PODS_COUNT -lt 2 ]]; then + echo "Istio pods are not running, Please check the istio pods" + exit 1 +fi + +echo "********** Download istioctl **************" +# Determines the operating system. +OS="${TARGET_OS:-$(uname)}" +if [ "${OS}" = "Darwin" ] ; then + OSEXT="osx" +else + OSEXT="linux" +fi +# Determine arch +LOCAL_ARCH=$(uname -m) +case "${LOCAL_ARCH}" in + x86_64|amd64) + ISTIO_ARCH=amd64 + ;; + armv8*|aarch64*|arm64) + ISTIO_ARCH=arm64 + ;; + armv*) + ISTIO_ARCH=armv7 + ;; + *) + echo "This system's architecture, ${LOCAL_ARCH}, isn't supported" + exit 1 + ;; +esac + + +ISTIO_URL="https://github.com/istio/istio/releases/download/${ISTIOCTL_VERSION}/istio-${ISTIOCTL_VERSION}-${OSEXT}-${ISTIO_ARCH}.tar.gz" +SHA256_URL="https://github.com/istio/istio/releases/download/${ISTIOCTL_VERSION}/istio-${ISTIOCTL_VERSION}-${OSEXT}-${ISTIO_ARCH}.tar.gz.sha256" +# Download the Istioctl binary +curl -sL "$ISTIO_URL" -o istio-"${ISTIOCTL_VERSION}"-${OSEXT}-${ISTIO_ARCH}.tar.gz + +# Download the SHA-256 checksum file +curl -sL "$SHA256_URL" -o istio-"${ISTIOCTL_VERSION}"-${OSEXT}-${ISTIO_ARCH}.tar.gz.sha256 + +# Verify the downloaded file +sha256sum -c istio-"${ISTIOCTL_VERSION}"-${OSEXT}-${ISTIO_ARCH}.tar.gz.sha256 + +# Check the result of the verification +if sha256sum -c istio-"${ISTIOCTL_VERSION}"-${OSEXT}-${ISTIO_ARCH}.tar.gz.sha256; then + echo "Verification successful: The file is intact." +else + echo "Verification failed: The file is corrupted." + exit 1 +fi + +tar -xzf istio-"${ISTIOCTL_VERSION}"-${OSEXT}-${ISTIO_ARCH}.tar.gz +cd istio-"${ISTIOCTL_VERSION}" +export PATH=$PWD/bin:$PATH +echo "==========================================================================" + +echo "********** ISTIO IngressGateway IP Address assignment **************" +ISTIO_IG_ANNOTATIONS=" + service.beta.kubernetes.io/azure-load-balancer-resource-group=${SVC_RESOURCEGROUP} + service.beta.kubernetes.io/azure-pip-name=${ISTIO_INGRESS_GATEWAY_IP_ADDRESS_NAME} +" +for annotation in $ISTIO_IG_ANNOTATIONS; do + kubectl annotate svc aks-istio-ingressgateway-external \ + "$annotation" \ + -n aks-istio-ingress +done + +echo "********** ISTIO Upgrade **************" +# Followed this guide for istio upgrade https://learn.microsoft.com/en-us/azure/aks/istio-upgrade +# To upgrade or rollback, change the targetVersion to the desire version, and version to the current version. +if [[ -z "$TARGET_VERSION" ]]; then + echo "Target version is not set, Please set the target version" + exit 1 +fi + +NEWVERSION="$TARGET_VERSION" +echo "********** Istio Upgrade Started with version ${NEWVERSION} **************" + +istioctl tag set "$TAG" --revision "${NEWVERSION}" --istioNamespace ${ISTIO_NAMESPACE} --overwrite +for namespace in $(kubectl get namespaces --selector=istio.io/rev="$TAG" -o jsonpath='{.items[*].metadata.name}'); do + echo "in namespace $namespace" + # bare pods + for pod in $(kubectl get pods --namespace "${namespace}" -o json | jq -r --arg NEWVERSION "${NEWVERSION}" '.items[] | select(.metadata.annotations["sidecar.istio.io/status"] | fromjson.revision != $NEWVERSION) | select(.metadata.ownerReferences | length == 0) | .metadata.name'); do + echo "recycle pod $pod" + kubectl delete pod "$pod" -n "$namespace" + done + # pods with owners + currentDeloyment="" + for owner in $(kubectl get pods --namespace "${namespace}" -o json | jq -r --arg NEWVERSION "${NEWVERSION}" '.items[] | select(.metadata.annotations["sidecar.istio.io/status"] | fromjson.revision != $NEWVERSION) | select(.metadata.ownerReferences) | "\(.metadata.ownerReferences[0].kind)/\(.metadata.ownerReferences[0].name)"' | sort | uniq); do + echo "process pod owner ${owner}" + case "$owner" in + "ReplicaSet"*) + deployment=$(kubectl get "${owner}" -n "$namespace" -o jsonpath='{.metadata.ownerReferences[0].name}') + if [[ -n "$deployment" ]] && [[ "$currentDeloyment" != "$deployment" ]]; then + currentDeloyment="$deployment" + echo "in ReplicaSet restart deployment $deployment" + kubectl rollout restart deployment "$deployment" -n "$namespace" + kubectl rollout status deployment "${deployment}" -n "$namespace" + else + echo "in ReplicaSet delete pod $owner" + kubectl delete pod "$owner" -n "$namespace" + fi + ;; + "StatefulSet"*) + echo "restart statefulset $owner" + kubectl rollout restart "${owner}" -n "$namespace" + kubectl rollout status "${owner}" -n "$namespace" + ;; + *) + # Don't do anything for (Cron)Job, or no owner pod for now. + ;; + esac + # etc + done +done + +echo "********** ISTIO Upgrade Finished**************" diff --git a/dev-infrastructure/scripts/kv-add-secret.sh b/dev-infrastructure/scripts/kv-add-secret.sh index 5303d7533..436b6697e 100755 --- a/dev-infrastructure/scripts/kv-add-secret.sh +++ b/dev-infrastructure/scripts/kv-add-secret.sh @@ -17,7 +17,7 @@ secret_name=$3 secret_value=$4 function officer_count() { - az role assignment list --scope ${kv_id} --assignee ${currentuser_client_id} --role "Key Vault Secrets Officer" | jq -r '.[].id'| wc -l + az role assignment list --scope ${kv_id} --assignee ${currentuser_client_id} --role "Key Vault Secrets Officer" --output json | jq -r '.[].id'| wc -l } # Check and grant permissions diff --git a/dev-infrastructure/scripts/kv-permissions.sh b/dev-infrastructure/scripts/kv-permissions.sh new file mode 100755 index 000000000..4bd324fb4 --- /dev/null +++ b/dev-infrastructure/scripts/kv-permissions.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +PRINCIPAL_ID=$1 +RG_NAME=$2 +KV_NAME=$3 + +KV_RESOURCE_ID=$(az keyvault show --name ${KV_NAME} --resource-group ${RG_NAME} --query id -o tsv 2>/dev/null) + +if [ "$(az account show -o json | jq -r '.user.type')" != "user" ]; then + # service principals can't assign themselves permissions + exit 0 +fi +if [ -z "${KV_RESOURCE_ID}" ]; then + echo "Error: Key Vault resource ID for ${KV_NAME} in ${RG_NAME} could not be retrieved." + exit 0 +fi + +az role assignment create \ + --role "Key Vault Secrets Officer" \ + --assignee ${PRINCIPAL_ID} \ + --scope ${KV_RESOURCE_ID} \ + --only-show-errors + +az role assignment create \ + --role "Key Vault Certificates Officer" \ + --assignee ${PRINCIPAL_ID} \ + --scope ${KV_RESOURCE_ID} \ + --only-show-errors + +az role assignment create \ + --role "Key Vault Certificate User" \ + --assignee ${PRINCIPAL_ID} \ + --scope ${KV_RESOURCE_ID} \ + --only-show-errors diff --git a/dev-infrastructure/svc-pipeline.yaml b/dev-infrastructure/svc-pipeline.yaml new file mode 100644 index 000000000..7ad56bb81 --- /dev/null +++ b/dev-infrastructure/svc-pipeline.yaml @@ -0,0 +1,79 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Service.Infra +rolloutName: Service Cluster Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + steps: + # Create SVC KV + - name: svc-infra + action: ARM + template: templates/svc-infra.bicep + parameters: configurations/svc-infra.tmpl.bicepparam + deploymentLevel: ResourceGroup + # Configure certificate issuers for the SVC KV + - name: svc-oncert-private-kv-issuer + action: SetCertificateIssuer + dependsOn: + - svc-infra + vaultBaseUrl: + input: + name: svcKeyVaultUrl + step: svc-infra + provider: + name: provider + value: OneCertV2-PrivateCA + - name: svc-oncert-public-kv-issuer + action: SetCertificateIssuer + dependsOn: + - svc-infra + vaultBaseUrl: + input: + name: svcKeyVaultUrl + step: svc-infra + provider: + name: provider + value: OneCertV2-PublicCA + # Create SVC cluster + - name: svc + action: ARM + template: templates/svc-cluster.bicep + parameters: configurations/svc-cluster.tmpl.bicepparam + deploymentLevel: ResourceGroup + dependsOn: + - svc-oncert-private-kv-issuer + - svc-oncert-public-kv-issuer +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + # Configure istio and drive upgrades + - name: istio + action: Shell + command: scripts/istio.sh + variables: + - name: TARGET_VERSION + configRef: svc.istio.targetVersion + - name: ISTIOCTL_VERSION + configRef: svc.istio.istioctlVersion + - name: ISTIO_INGRESS_GATEWAY_IP_ADDRESS_NAME + configRef: svc.istio.ingressGatewayIPAddressName + - name: TAG + configRef: svc.istio.tag + - name: SVC_RESOURCEGROUP + configRef: svc.rg + dependsOn: + - svc + # Install ACRpull + - name: acrpull + action: Shell + command: make -C ../acrpull deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ACRPULL_DIGEST + configRef: acrPullImageDigest + dependsOn: + - svc diff --git a/dev-infrastructure/templates/cs-integration-msi.bicep b/dev-infrastructure/templates/cs-integration-msi.bicep index 809dc85c6..984faafd1 100644 --- a/dev-infrastructure/templates/cs-integration-msi.bicep +++ b/dev-infrastructure/templates/cs-integration-msi.bicep @@ -7,6 +7,9 @@ param clusterServiceManagedIdentityName string @description('The name of the cluster to integrate with') param clusterName string +@description('The name of the CS service account') +param clusterServiceServiceAccountName string + resource uami 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { name: clusterServiceManagedIdentityName } @@ -25,7 +28,7 @@ resource uami_fedcred 'Microsoft.ManagedIdentity/userAssignedIdentities/federate 'api://AzureADTokenExchange' ] issuer: aksCluster.properties.oidcIssuerProfile.issuerURL - subject: 'system:serviceaccount:${format(namespaceFormatString, i)}:clusters-service' + subject: 'system:serviceaccount:${format(namespaceFormatString, i)}:${clusterServiceServiceAccountName}' } } ] diff --git a/dev-infrastructure/templates/dev-acr.bicep b/dev-infrastructure/templates/dev-acr.bicep index 6b6d7e24c..f505e8751 100644 --- a/dev-infrastructure/templates/dev-acr.bicep +++ b/dev-infrastructure/templates/dev-acr.bicep @@ -1,14 +1,14 @@ +/* +Setup caching rules and purge jobs for Azure Container Registry. +Used in DEV environment only. +Depends on ACRs being provisioned beforehands by the global-acr.bicep template. +*/ + @minLength(5) @maxLength(40) @description('Globally unique name of the Azure Container Registry') param acrName string -@description('Location of the registry.') -param location string = resourceGroup().location - -@description('Service tier of the Azure Container Registry.') -param acrSku string - @description('List of quay repositories to cache in the Azure Container Registry.') param quayRepositoriesToCache array = [] @@ -18,28 +18,18 @@ param purgeJobs array = [] @description('Name of the global key vault.') param keyVaultName string = '' +param location string = resourceGroup().location + resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: keyVaultName } -module acr '../modules/acr/acr.bicep' = { - name: '${deployment().name}-acrName' - params: { - acrName: acrName - location: location - acrSku: acrSku - } -} - resource acrResource 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' existing = { name: acrName } resource pullCredential 'Microsoft.ContainerRegistry/registries/credentialSets@2023-01-01-preview' = [ for repo in quayRepositoriesToCache: { - dependsOn: [ - acr - ] name: repo.ruleName parent: acrResource identity: { @@ -60,9 +50,6 @@ resource pullCredential 'Microsoft.ContainerRegistry/registries/credentialSets@2 resource cacheRule 'Microsoft.ContainerRegistry/registries/cacheRules@2023-01-01-preview' = [ for (repo, i) in quayRepositoriesToCache: { - dependsOn: [ - acr - ] name: repo.ruleName parent: acrResource properties: { @@ -75,9 +62,6 @@ resource cacheRule 'Microsoft.ContainerRegistry/registries/cacheRules@2023-01-01 resource secretAccessPermission 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ for (repo, i) in quayRepositoriesToCache: { - dependsOn: [ - acr - ] scope: keyVault name: guid(keyVault.id, 'quayPullSecrets', 'read', repo.ruleName, acrName) properties: { @@ -93,9 +77,6 @@ resource secretAccessPermission 'Microsoft.Authorization/roleAssignments@2022-04 resource purgeCached 'Microsoft.ContainerRegistry/registries/tasks@2019-04-01' = [ for purgeJob in purgeJobs: { - dependsOn: [ - acr - ] name: '${purgeJob.name}' location: location parent: acrResource diff --git a/dev-infrastructure/templates/dev-operator-roles.bicep b/dev-infrastructure/templates/dev-operator-roles.bicep new file mode 100644 index 000000000..870006737 --- /dev/null +++ b/dev-infrastructure/templates/dev-operator-roles.bicep @@ -0,0 +1,28 @@ +// CustomRoles for Platform Workload Identities for development environment + +targetScope = 'subscription' + +@description('Array of roles for platform workload identity') +param roles array = [] + +resource roleDef 'Microsoft.Authorization/roleDefinitions@2022-04-01' = [ + for role in roles: { + name: guid(role.roleName) + properties: { + roleName: role.roleName + description: role.roleDescription + type: 'CustomRole' + permissions: [ + { + actions: role.actions + notActions: role.notActions + dataActions: role.dataActions + notDataActions: role.notDataActions + } + ] + assignableScopes: [ + subscription().id + ] + } + } +] diff --git a/dev-infrastructure/templates/feature-registration.bicep b/dev-infrastructure/templates/feature-registration.bicep index c3b240ad0..27207423e 100644 --- a/dev-infrastructure/templates/feature-registration.bicep +++ b/dev-infrastructure/templates/feature-registration.bicep @@ -9,6 +9,7 @@ param features array = [ 'Microsoft.ContainerService/DisableSSHPreview' 'Microsoft.ContainerService/IstioNativeSidecarModePreview' 'Microsoft.Compute/EncryptionAtHost' + 'Microsoft.Network/AllowBringYourOwnPublicIpAddress' ] resource featureReg 'Microsoft.Features/featureProviders/subscriptionFeatureRegistrations@2021-07-01' = [ diff --git a/dev-infrastructure/templates/global-acr.bicep b/dev-infrastructure/templates/global-acr.bicep new file mode 100644 index 000000000..3c9a0bc05 --- /dev/null +++ b/dev-infrastructure/templates/global-acr.bicep @@ -0,0 +1,29 @@ +/* +Sets up the global ACRs for SVC and OCP images. +*/ + +param ocpAcrName string +param ocpAcrSku string + +param svcAcrName string +param svcAcrSku string + +param location string + +module ocpAcr '../modules/acr/acr.bicep' = { + name: ocpAcrName + params: { + acrName: ocpAcrName + acrSku: ocpAcrSku + location: location + } +} + +module svcAcr '../modules/acr/acr.bicep' = { + name: svcAcrSku + params: { + acrName: svcAcrName + acrSku: svcAcrSku + location: location + } +} diff --git a/dev-infrastructure/templates/global-infra.bicep b/dev-infrastructure/templates/global-infra.bicep new file mode 100644 index 000000000..bf3d4a26d --- /dev/null +++ b/dev-infrastructure/templates/global-infra.bicep @@ -0,0 +1,48 @@ +@description('The global msi name') +param globalMSIName string + +@description('The cxParentZone Domain') +param cxParentZoneName string + +@description('The svcParentZone Domain') +param svcParentZoneName string + +@description('Metrics global Grafana name') +param grafanaName string + +@description('Metrics global MSI name') +param msiName string + +@description('The admin group principal ID to manage Grafana') +param grafanaAdminGroupPrincipalId string + +resource ev2MSI 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: globalMSIName + location: resourceGroup().location +} + +resource cxParentZone 'Microsoft.Network/dnsZones@2018-05-01' = { + name: cxParentZoneName + location: 'global' +} + +resource svcParentZone 'Microsoft.Network/dnsZones@2018-05-01' = { + name: svcParentZoneName + location: 'global' +} + +var grafanaAdmin = { + principalId: grafanaAdminGroupPrincipalId + principalType: 'group' +} + +module grafana 'br:arointacr.azurecr.io/grafana.bicep:metrics.20240814.1' = { + name: 'grafana' + params: { + msiName: msiName + grafanaName: grafanaName + grafanaAdmin: grafanaAdmin + } +} + +output grafanaId string = grafana.outputs.grafanaId diff --git a/dev-infrastructure/templates/image-sync.bicep b/dev-infrastructure/templates/image-sync.bicep index d540d0ad1..37650fa0a 100644 --- a/dev-infrastructure/templates/image-sync.bicep +++ b/dev-infrastructure/templates/image-sync.bicep @@ -22,18 +22,21 @@ param ocpAcrName string @description('Name of the keyvault where the pull secret is stored') param keyVaultName string -@description('Name of the KeyVault RG') -param keyVaultResourceGroup string +@description('Resource group of the keyvault') +param keyVaultPrivate bool + +@description('Defines if the keyvault should have soft delete enabled') +param keyVaultSoftDelete bool @description('The name of the pull secret for the component sync job') param componentSyncPullSecretName string -@description('The name of the Quay API bearer token secret') -param bearerSecretName string - @description('The image to use for the component sync job') param componentSyncImage string +@description('Defines if the component sync job should be enabled') +param componentSyncEnabed bool + @description('A CSV of the repositories to sync') param repositoriesToSync string @@ -43,13 +46,53 @@ param numberOfTags int = 10 @description('The image to use for the oc-mirror job') param ocMirrorImage string +@description('Defines if the oc-mirror job should be enabled') +param ocMirrorEnabled bool + @description('The name of the pull secret for the oc-mirror job') param ocpPullSecretName string +@description('Secret configuration to pass into component sync') +#disable-next-line secure-secrets-in-params // Doesn't contain a secret +param componentSyncSecrets string + +var csSecrets = [ + for secret in split(componentSyncSecrets, ','): { + registry: split(secret, ':')[0] + secret: split(secret, ':')[1] + } +] + +var bearerSecrets = [for css in csSecrets: '${css.secret}'] + +var secretsFolder = '/etc/containers' + +var secretWithFolderPrefix = [ + for css in csSecrets: { + registry: css.registry + secretFile: '/auth/${css.secret}' + } +] + +var secretVar = { + secrets: secretWithFolderPrefix +} + // // Container App Infra // +module kv '../modules/keyvault/keyvault.bicep' = { + name: 'imagesync-kv' + params: { + location: location + keyVaultName: keyVaultName + private: keyVaultPrivate + enableSoftDelete: keyVaultSoftDelete + purpose: 'imagesync' + } +} + resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-06-01' = { name: containerAppLogAnalyticsName location: location @@ -83,7 +126,7 @@ resource uami 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { // ACRs can be in different RGs or even subscriptions. ideally we should // be able to deal with ACR resource IDs as input instead of RG and ACR names -module acrContributorRole '../modules/acr-permissions.bicep' = { +module acrContributorRole '../modules/acr/acr-permissions.bicep' = { name: guid(imageSyncManagedIdentity, location, 'acr', 'readwrite') scope: resourceGroup(acrResourceGroup) params: { @@ -93,7 +136,7 @@ module acrContributorRole '../modules/acr-permissions.bicep' = { } } -module acrPullRole '../modules/acr-permissions.bicep' = { +module acrPullRole '../modules/acr/acr-permissions.bicep' = { name: guid(imageSyncManagedIdentity, location, 'acr', 'pull') scope: resourceGroup(acrResourceGroup) params: { @@ -103,15 +146,17 @@ module acrPullRole '../modules/acr-permissions.bicep' = { } module pullSecretPermission '../modules/keyvault/keyvault-secret-access.bicep' = [ - for secretName in [componentSyncPullSecretName, bearerSecretName, ocpPullSecretName]: { + for secretName in union([componentSyncPullSecretName, ocpPullSecretName], bearerSecrets): { name: guid(imageSyncManagedIdentity, location, keyVaultName, secretName, 'secret-user') - scope: resourceGroup(keyVaultResourceGroup) params: { keyVaultName: keyVaultName secretName: secretName roleName: 'Key Vault Secrets User' managedIdentityPrincipalId: uami.properties.principalId } + dependsOn: [ + kv + ] } ] @@ -120,9 +165,33 @@ module pullSecretPermission '../modules/keyvault/keyvault-secret-access.bicep' = // var componentSyncJobName = 'component-sync' -var pullSecretFile = 'quayio-auth.json' -resource componentSyncJob 'Microsoft.App/jobs@2024-03-01' = { +var componentSecretsArray = [ + for bearerSecretName in bearerSecrets: { + name: bearerSecretName + keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${bearerSecretName}' + identity: uami.id + } +] + +var componentSecretVolumesArray = [ + for bearerSecretName in bearerSecrets: { + name: bearerSecretName + storageType: 'Secret' + secrets: [ + { secretRef: bearerSecretName } + ] + } +] + +var componentSecretVolumeMountsArray = [ + for bearerSecretName in bearerSecrets: { + volumeName: bearerSecretName + mountPath: '/tmp/secrets/${bearerSecretName}' + } +] + +resource componentSyncJob 'Microsoft.App/jobs@2024-03-01' = if (componentSyncEnabed) { name: componentSyncJobName location: location @@ -149,18 +218,16 @@ resource componentSyncJob 'Microsoft.App/jobs@2024-03-01' = { server: '${svcAcrName}${environment().suffixes.acrLoginServer}' } ] - secrets: [ - { - name: 'pull-secrets' - keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${componentSyncPullSecretName}' - identity: uami.id - } - { - name: 'bearer-secret' - keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${bearerSecretName}' - identity: uami.id - } - ] + secrets: union( + [ + { + name: 'pull-secrets' + keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${componentSyncPullSecretName}' + identity: uami.id + } + ], + componentSecretsArray + ) } template: { containers: [ @@ -173,11 +240,11 @@ resource componentSyncJob 'Microsoft.App/jobs@2024-03-01' = { env: [ { name: 'NUMBER_OF_TAGS', value: '${numberOfTags}' } { name: 'REPOSITORIES', value: repositoriesToSync } - { name: 'QUAY_SECRET_FILE', value: '/auth/${pullSecretFile}' } - { name: 'ACR_REGISTRY', value: '${svcAcrName}${environment().suffixes.acrLoginServer}' } + { name: 'ACR_TARGET_REGISTRY', value: '${svcAcrName}${environment().suffixes.acrLoginServer}' } { name: 'TENANT_ID', value: tenant().tenantId } { name: 'DOCKER_CONFIG', value: '/auth' } { name: 'MANAGED_IDENTITY_CLIENT_ID', value: uami.properties.clientId } + { name: 'SECRETS', value: string(secretVar) } ] } ] @@ -190,44 +257,43 @@ resource componentSyncJob 'Microsoft.App/jobs@2024-03-01' = { ] args: [ '-c' - 'cat /tmp/secret-orig/pull-secrets |base64 -d > /etc/containers/config.json && cat /tmp/bearer-secret/bearer-secret | base64 -d > /etc/containers/${pullSecretFile}' - ] - volumeMounts: [ - { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } - { volumeName: 'pull-secrets', mountPath: '/tmp/secret-orig' } - { volumeName: 'bearer-secret', mountPath: '/tmp/bearer-secret' } - ] - } - ] - volumes: [ - { - name: 'pull-secrets-updated' - storageType: 'EmptyDir' - } - { - name: 'pull-secrets' - storageType: 'Secret' - secrets: [ - { secretRef: 'pull-secrets' } - ] - } - { - name: 'bearer-secret' - storageType: 'Secret' - secrets: [ - { secretRef: 'bearer-secret' } + 'cat /tmp/secret-orig/pull-secrets |base64 -d > /etc/containers/config.json && cd /tmp/secrets; for file in $(find . -type f); do export fn=$(basename $file); cat $file | base64 -d > ${secretsFolder}/$fn; done;' ] + volumeMounts: union( + [ + { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } + { volumeName: 'pull-secrets', mountPath: '/tmp/secret-orig' } + ], + componentSecretVolumeMountsArray + ) } ] + volumes: union( + [ + { + name: 'pull-secrets-updated' + storageType: 'EmptyDir' + } + { + name: 'pull-secrets' + storageType: 'Secret' + secrets: [ + { secretRef: 'pull-secrets' } + ] + } + ], + componentSecretVolumesArray + ) } } + dependsOn: [ + kv + ] } -// oc-mirror job - -var ocMirrorJobName = 'oc-mirror' +// oc-mirror jobs -var ocMirrorConfig = { +var ocpMirrorConfig = { kind: 'ImageSetConfiguration' apiVersion: 'mirror.openshift.io/v1alpha2' storageConfig: { @@ -247,6 +313,12 @@ var ocMirrorConfig = { minVersion: '4.17.0' maxVersion: '4.17.0' } + { + name: 'candidate-4.18' + type: 'ocp' + full: true + minVersion: '4.18.0-rc.6' + } ] graph: true } @@ -259,102 +331,162 @@ var ocMirrorConfig = { { name: 'registry.redhat.io/redhat/certified-operator-index:v4.17' } { name: 'registry.redhat.io/redhat/community-operator-index:v4.17' } { name: 'registry.redhat.io/redhat/redhat-marketplace-index:v4.17' } + { name: 'registry.redhat.io/redhat/redhat-operator-index:v4.18' } + { name: 'registry.redhat.io/redhat/certified-operator-index:v4.18' } + { name: 'registry.redhat.io/redhat/community-operator-index:v4.18' } + { name: 'registry.redhat.io/redhat/redhat-marketplace-index:v4.18' } ] } } -resource ocMirrorJob 'Microsoft.App/jobs@2024-03-01' = { - name: ocMirrorJobName - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${uami.id}': {} - } +var acmMirrorConfig = { + kind: 'ImageSetConfiguration' + apiVersion: 'mirror.openshift.io/v2alpha1' + mirror: { + operators: [ + { + catalog: 'registry.redhat.io/redhat/redhat-operator-index:v4.16' + packages: [ + { + name: 'multicluster-engine' + bundles: [ + { + name: 'multicluster-engine.v2.7.0' + } + ] + } + { + name: 'advanced-cluster-management' + bundles: [ + { + name: 'advanced-cluster-management.v2.12.0' + } + ] + } + ] + } + ] } +} - properties: { - environmentId: containerAppEnvironment.id - configuration: { - eventTriggerConfig: {} - triggerType: 'Schedule' - manualTriggerConfig: { - parallelism: 1 +var ocMirrorJobConfiguration = ocMirrorEnabled + ? [ + { + name: 'oc-mirror' + cron: '0 * * * *' + timeout: 4 * 60 * 60 + targetRegistry: ocpAcrName + imageSetConfig: ocpMirrorConfig } - scheduleTriggerConfig: { - cronExpression: '0 * * * *' - parallelism: 1 + { + name: 'acm-mirror' + cron: '0 10 * * *' + timeout: 4 * 60 * 60 + targetRegistry: svcAcrName + imageSetConfig: acmMirrorConfig } - replicaTimeout: 4 * 60 * 60 - registries: [ - { - identity: uami.id - server: '${svcAcrName}${environment().suffixes.acrLoginServer}' + ] + : [] + +resource ocMirrorJobs 'Microsoft.App/jobs@2024-03-01' = [ + for i in range(0, length(ocMirrorJobConfiguration)): { + name: ocMirrorJobConfiguration[i].name + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${uami.id}': {} + } + } + properties: { + environmentId: containerAppEnvironment.id + configuration: { + eventTriggerConfig: {} + triggerType: 'Schedule' + manualTriggerConfig: { + parallelism: 1 } - ] - secrets: [ - { - name: 'pull-secrets' - keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${ocpPullSecretName}' - identity: uami.id + scheduleTriggerConfig: { + cronExpression: ocMirrorJobConfiguration[i].cron + parallelism: 1 } - ] - } - template: { - containers: [ - { - name: ocMirrorJobName - image: ocMirrorImage - volumeMounts: [ - { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } - ] - env: [ - { name: 'IMAGE_SET_CONFIG', value: base64(string(ocMirrorConfig)) } - { name: 'REGISTRY', value: ocpAcrName } - { name: 'REGISTRY_URL', value: '${ocpAcrName}${environment().suffixes.acrLoginServer}' } - { name: 'XDG_RUNTIME_DIR', value: '/etc' } - { name: 'AZURE_CLIENT_ID', value: uami.properties.clientId } - { - name: 'APPSETTING_WEBSITE_SITE_NAME' - value: 'workaround - https://github.com/microsoft/azure-container-apps/issues/502' + replicaTimeout: ocMirrorJobConfiguration[i].timeout + registries: [ + { + identity: uami.id + server: '${svcAcrName}${environment().suffixes.acrLoginServer}' + } + ] + secrets: [ + { + name: 'pull-secrets' + keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/${ocpPullSecretName}' + identity: uami.id + } + ] + } + template: { + containers: [ + { + name: 'oc-mirror' + image: ocMirrorImage + volumeMounts: [ + { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } + ] + env: [ + { name: 'IMAGE_SET_CONFIG', value: base64(string(ocMirrorJobConfiguration[i].imageSetConfig)) } + { name: 'REGISTRY', value: ocMirrorJobConfiguration[i].targetRegistry } + { + name: 'REGISTRY_URL' + value: '${ocMirrorJobConfiguration[i].targetRegistry}${environment().suffixes.acrLoginServer}' + } + { name: 'XDG_RUNTIME_DIR', value: '/etc' } + { name: 'AZURE_CLIENT_ID', value: uami.properties.clientId } + { + name: 'APPSETTING_WEBSITE_SITE_NAME' + value: 'workaround - https://github.com/microsoft/azure-container-apps/issues/502' + } + ] + resources: { + cpu: 2 + memory: '4Gi' } - ] - resources: { - cpu: 2 - memory: '4Gi' } - } - ] - initContainers: [ - { - name: 'decodesecrets' - image: 'mcr.microsoft.com/azure-cli:cbl-mariner2.0' - command: [ - '/bin/sh' - ] - args: [ - '-c' - 'cat /tmp/secret-orig/pull-secrets | base64 -d > /etc/containers/auth.json' - ] - volumeMounts: [ - { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } - { volumeName: 'pull-secrets', mountPath: '/tmp/secret-orig' } - ] - } - ] - volumes: [ - { - name: 'pull-secrets-updated' - storageType: 'EmptyDir' - } - { - name: 'pull-secrets' - storageType: 'Secret' - secrets: [ - { secretRef: 'pull-secrets' } - ] - } - ] + ] + initContainers: [ + { + name: 'decodesecrets' + image: 'mcr.microsoft.com/azure-cli:cbl-mariner2.0' + command: [ + '/bin/sh' + ] + args: [ + '-c' + 'cat /tmp/secret-orig/pull-secrets | base64 -d > /etc/containers/auth.json' + ] + volumeMounts: [ + { volumeName: 'pull-secrets-updated', mountPath: '/etc/containers' } + { volumeName: 'pull-secrets', mountPath: '/tmp/secret-orig' } + ] + } + ] + volumes: [ + { + name: 'pull-secrets-updated' + storageType: 'EmptyDir' + } + { + name: 'pull-secrets' + storageType: 'Secret' + secrets: [ + { secretRef: 'pull-secrets' } + ] + } + ] + } } + dependsOn: [ + kv + ] } -} +] diff --git a/dev-infrastructure/templates/mgmt-cluster.bicep b/dev-infrastructure/templates/mgmt-cluster.bicep index d86e24938..855c7900e 100644 --- a/dev-infrastructure/templates/mgmt-cluster.bicep +++ b/dev-infrastructure/templates/mgmt-cluster.bicep @@ -59,67 +59,38 @@ param aksKeyVaultName string @description('Manage soft delete setting for AKS etcd key-value store') param aksEtcdKVEnableSoftDelete bool = true +@description('IPTags to be set on the cluster outbound IP address in the format of ipTagType:tag,ipTagType:tag') +param aksClusterOutboundIPAddressIPTags string = '' + @description('The name of the maestro consumer.') param maestroConsumerName string @description('The domain to use to use for the maestro certificate. Relevant only for environments where OneCert can be used.') param maestroCertDomain string -@description('The name of the keyvault for Maestro Eventgrid namespace certificates.') -param maestroKeyVaultName string - -@description('The name of the managed identity that will manage certificates in maestros keyvault.') -param maestroKeyVaultCertOfficerMSIName string = '${maestroKeyVaultName}-cert-officer-msi' - @description('The name of the eventgrid namespace for Maestro.') param maestroEventGridNamespacesName string -@description('This is a regional DNS zone') -param regionalDNSZoneName string - @description('The resource group that hosts the regional zone') param regionalResourceGroup string @description('The name of the CX KeyVault') param cxKeyVaultName string -@description('Defines if the CX KeyVault is private') -param cxKeyVaultPrivate bool - -@description('Defines if the CX KeyVault has soft delete enabled') -param cxKeyVaultSoftDelete bool - @description('The name of the MSI KeyVault') param msiKeyVaultName string -@description('Defines if the MSI KeyVault is private') -param msiKeyVaultPrivate bool - -@description('Defines if the MSI KeyVault has soft delete enabled') -param msiKeyVaultSoftDelete bool - @description('The name of the MGMT KeyVault') param mgmtKeyVaultName string -@description('Defines if the MGMT KeyVault is private') -param mgmtKeyVaultPrivate bool +@description('MSI that will be used to run deploymentScripts') +param aroDevopsMsiId string -@description('Defines if the MGMT KeyVault has soft delete enabled') -param mgmtKeyVaultSoftDelete bool - -// Tags the resource group -resource subscriptionTags 'Microsoft.Resources/tags@2024-03-01' = { - name: 'default' - scope: resourceGroup() - properties: { - tags: { - persist: toLower(string(persist)) - } - } -} +@description('The name of the Azure Monitor Workspace (stores prometheus metrics)') +param azureMonitorWorkspaceName string module mgmtCluster '../modules/aks-cluster-base.bicep' = { - name: 'mgmt-cluster' + name: 'cluster' scope: resourceGroup() params: { location: location @@ -127,6 +98,7 @@ module mgmtCluster '../modules/aks-cluster-base.bicep' = { aksClusterName: aksClusterName aksNodeResourceGroupName: aksNodeResourceGroupName aksEtcdKVEnableSoftDelete: aksEtcdKVEnableSoftDelete + aksClusterOutboundIPAddressIPTags: aksClusterOutboundIPAddressIPTags deployIstio: false kubernetesVersion: kubernetesVersion vnetAddressPrefix: vnetAddressPrefix @@ -139,11 +111,6 @@ module mgmtCluster '../modules/aks-cluster-base.bicep' = { namespace: 'maestro' serviceAccountName: 'maestro' } - external_dns_wi: { - uamiName: 'external-dns' - namespace: 'hypershift' - serviceAccountName: 'external-dns' - } }) aksKeyVaultName: aksKeyVaultName acrPullResourceGroups: acrPullResourceGroups @@ -156,88 +123,89 @@ module mgmtCluster '../modules/aks-cluster-base.bicep' = { systemAgentVMSize: systemAgentVMSize systemOsDiskSizeGB: aksSystemOsDiskSizeGB userOsDiskSizeGB: aksUserOsDiskSizeGB + aroDevopsMsiId: aroDevopsMsiId + dcrId: dataCollection.outputs.dcrId } } output aksClusterName string = mgmtCluster.outputs.aksClusterName // -// M A E S T R O +// M E T R I C S // -module maestroConsumer '../modules/maestro/maestro-consumer.bicep' = { - name: 'maestro-consumer' +module dataCollection '../modules/metrics/datacollection.bicep' = { + name: '${resourceGroup().name}-aksClusterName' params: { - maestroServerManagedIdentityPrincipalId: filter( - mgmtCluster.outputs.userAssignedIdentities, - id => id.uamiName == 'maestro-consumer' - )[0].uamiPrincipalID - maestroInfraResourceGroup: regionalResourceGroup - maestroConsumerName: maestroConsumerName - maestroEventGridNamespaceName: maestroEventGridNamespacesName - maestroKeyVaultName: maestroKeyVaultName - maestroKeyVaultOfficerManagedIdentityName: maestroKeyVaultCertOfficerMSIName - maestroKeyVaultCertificateDomain: maestroCertDomain - location: location + azureMonitorWorkspaceLocation: location + azureMonitorWorkspaceName: azureMonitorWorkspaceName + regionalResourceGroup: regionalResourceGroup + aksClusterName: aksClusterName } } // -// E X T E R N A L D N S +// K E Y V A U L T S // -var externalDnsManagedIdentityPrincipalId = filter( - mgmtCluster.outputs.userAssignedIdentities, - id => id.uamiName == 'external-dns' -)[0].uamiPrincipalID - -module dnsZoneContributor '../modules/dns/zone-contributor.bicep' = { - name: guid(regionalDNSZoneName, mgmtCluster.name, 'external-dns') - scope: resourceGroup(regionalResourceGroup) - params: { - zoneName: regionalDNSZoneName - zoneContributerManagedIdentityPrincipalId: externalDnsManagedIdentityPrincipalId +module cxCSIKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = [ + for role in [ + 'Key Vault Secrets Officer' + 'Key Vault Certificate User' + 'Key Vault Certificates Officer' + ]: { + name: guid(cxKeyVaultName, 'aks-kv-csi-mi', role) + params: { + keyVaultName: cxKeyVaultName + roleName: role + managedIdentityPrincipalId: mgmtCluster.outputs.aksClusterKeyVaultSecretsProviderPrincipalId + } + } +] + +module msiCSIKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = [ + for role in [ + 'Key Vault Secrets Officer' + 'Key Vault Certificate User' + 'Key Vault Certificates Officer' + ]: { + name: guid(msiKeyVaultName, 'aks-kv-csi-mi', role) + params: { + keyVaultName: msiKeyVaultName + roleName: role + managedIdentityPrincipalId: mgmtCluster.outputs.aksClusterKeyVaultSecretsProviderPrincipalId + } } +] + +resource mgmtKeyVault 'Microsoft.KeyVault/vaults@2024-04-01-preview' existing = { + name: mgmtKeyVaultName } // -// K E Y V A U L T S +// M A E S T R O // -module cxKeyVault '../modules/keyvault/keyvault.bicep' = { - name: '${deployment().name}-cx-kv' - params: { - location: location - keyVaultName: cxKeyVaultName - private: cxKeyVaultPrivate - enableSoftDelete: cxKeyVaultSoftDelete - purpose: 'cx' - } -} - -module msiKeyVault '../modules/keyvault/keyvault.bicep' = { - name: '${deployment().name}-msi-kv' - params: { - location: location - keyVaultName: msiKeyVaultName - private: msiKeyVaultPrivate - enableSoftDelete: msiKeyVaultSoftDelete - purpose: 'msi' - } -} - -module mgmtKeyVault '../modules/keyvault/keyvault.bicep' = { - name: '${deployment().name}-mgmt-kv' +module maestroConsumer '../modules/maestro/maestro-consumer.bicep' = { + name: 'maestro-consumer' params: { - location: location - keyVaultName: mgmtKeyVaultName - private: mgmtKeyVaultPrivate - enableSoftDelete: mgmtKeyVaultSoftDelete - purpose: 'mgmt' + maestroAgentManagedIdentityPrincipalId: filter( + mgmtCluster.outputs.userAssignedIdentities, + id => id.uamiName == 'maestro-consumer' + )[0].uamiPrincipalID + maestroInfraResourceGroup: regionalResourceGroup + maestroConsumerName: maestroConsumerName + maestroEventGridNamespaceName: maestroEventGridNamespacesName + certKeyVaultName: mgmtKeyVaultName + keyVaultOfficerManagedIdentityName: aroDevopsMsiId + maestroCertificateDomain: maestroCertDomain } + dependsOn: [ + mgmtKeyVault + ] } -// +// // E V E N T G R I D P R I V A T E E N D P O I N T C O N N E C T I O N // diff --git a/dev-infrastructure/templates/mgmt-infra.bicep b/dev-infrastructure/templates/mgmt-infra.bicep new file mode 100644 index 000000000..6b9c5ad5e --- /dev/null +++ b/dev-infrastructure/templates/mgmt-infra.bicep @@ -0,0 +1,130 @@ +@description('Azure Region Location') +param location string = resourceGroup().location + +@description('Set to true to prevent resources from being pruned after 48 hours') +param persist bool = false + +@description('The name of the CX KeyVault') +param cxKeyVaultName string + +@description('Defines if the CX KeyVault is private') +param cxKeyVaultPrivate bool + +@description('Defines if the CX KeyVault has soft delete enabled') +param cxKeyVaultSoftDelete bool + +@description('The name of the MSI KeyVault') +param msiKeyVaultName string + +@description('Defines if the MSI KeyVault is private') +param msiKeyVaultPrivate bool + +@description('Defines if the MSI KeyVault has soft delete enabled') +param msiKeyVaultSoftDelete bool + +@description('The name of the MGMT KeyVault') +param mgmtKeyVaultName string + +@description('Defines if the MGMT KeyVault is private') +param mgmtKeyVaultPrivate bool + +@description('Defines if the MGMT KeyVault has soft delete enabled') +param mgmtKeyVaultSoftDelete bool + +@description('Cluster user assigned identity resource id, used to grant KeyVault access') +param clusterServiceMIResourceId string + +resource resourcegroupTags 'Microsoft.Resources/tags@2024-03-01' = { + name: 'default' + scope: resourceGroup() + properties: { + tags: { + persist: toLower(string(persist)) + } + } +} + +// +// K E Y V A U L T S +// + +module cxKeyVault '../modules/keyvault/keyvault.bicep' = { + name: '${deployment().name}-cx-kv' + params: { + location: location + keyVaultName: cxKeyVaultName + private: cxKeyVaultPrivate + enableSoftDelete: cxKeyVaultSoftDelete + purpose: 'cx' + } +} + +module msiKeyVault '../modules/keyvault/keyvault.bicep' = { + name: '${deployment().name}-msi-kv' + params: { + location: location + keyVaultName: msiKeyVaultName + private: msiKeyVaultPrivate + enableSoftDelete: msiKeyVaultSoftDelete + purpose: 'msi' + } +} + +module mgmtKeyVault '../modules/keyvault/keyvault.bicep' = { + name: '${deployment().name}-mgmt-kv' + params: { + location: location + keyVaultName: mgmtKeyVaultName + private: mgmtKeyVaultPrivate + enableSoftDelete: mgmtKeyVaultSoftDelete + purpose: 'mgmt' + } +} + +// +// C L U S T E R S E R V I C E K V A C C E S S +// + +import * as res from '../modules/resource.bicep' +var clusterServiceMIRef = res.msiRefFromId(clusterServiceMIResourceId) + +resource clusterServiceMI 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + scope: resourceGroup(clusterServiceMIRef.resourceGroup.name) + name: clusterServiceMIRef.name +} + +module cxClusterServiceKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = [ + for role in [ + 'Key Vault Secrets Officer' + 'Key Vault Certificate User' + 'Key Vault Certificates Officer' + ]: { + name: guid(cxKeyVaultName, clusterServiceMIResourceId, role) + params: { + keyVaultName: cxKeyVaultName + roleName: role + managedIdentityPrincipalId: clusterServiceMI.properties.principalId + } + dependsOn: [ + cxKeyVault + ] + } +] + +module msiClusterServiceKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = [ + for role in [ + 'Key Vault Secrets Officer' + 'Key Vault Certificate User' + 'Key Vault Certificates Officer' + ]: { + name: guid(msiKeyVaultName, clusterServiceMIResourceId, role) + params: { + keyVaultName: msiKeyVaultName + roleName: role + managedIdentityPrincipalId: clusterServiceMI.properties.principalId + } + dependsOn: [ + msiKeyVault + ] + } +] diff --git a/dev-infrastructure/templates/mock-identities.bicep b/dev-infrastructure/templates/mock-identities.bicep index 84642508c..a3ac8ab06 100644 --- a/dev-infrastructure/templates/mock-identities.bicep +++ b/dev-infrastructure/templates/mock-identities.bicep @@ -1,8 +1,8 @@ @description('Azure Region Location') param location string = resourceGroup().location -@description('Name of the Key Vault Certificate Officer Managed Identity') -param kvCertOfficerManagedIdentityName string +@description('The resource ID of the managed identity that will be used for Key Vault operations') +param aroDevopsMsiId string @description('The name of the key vault') param keyVaultName string @@ -10,33 +10,21 @@ param keyVaultName string @description('Global resource group name') param globalResourceGroupName string = 'global' -module scriptMsi '../modules/keyvault/identity-script-msi.bicep' = { - name: 'script-msi' - params: { - location: location - kvCertOfficerManagedIdentityName: kvCertOfficerManagedIdentityName - keyVaultName: keyVaultName - } -} - // // F I R S T P A R T Y I D E N T I T Y // -module firstPartyIdentity '../modules/key-vault-cert.bicep' = { +module firstPartyIdentity '../modules/keyvault/key-vault-cert.bicep' = { name: 'first-party-identity' params: { location: location - keyVaultManagedIdentityId: scriptMsi.outputs.kvCertOfficerManagedIdentityId + keyVaultManagedIdentityId: aroDevopsMsiId keyVaultName: keyVaultName certName: 'firstPartyCert' subjectName: 'CN=firstparty.hcp.osadev.cloud' issuerName: 'Self' dnsNames: ['firstparty.hcp.osadev.cloud'] } - dependsOn: [ - scriptMsi - ] } resource customRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = { @@ -66,11 +54,11 @@ resource customRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = { // A R M H E L P E R I D E N T I T Y // -module armHelperIdentity '../modules/key-vault-cert.bicep' = { +module armHelperIdentity '../modules/keyvault/key-vault-cert.bicep' = { name: 'arm-helper-identity' params: { location: location - keyVaultManagedIdentityId: scriptMsi.outputs.kvCertOfficerManagedIdentityId + keyVaultManagedIdentityId: aroDevopsMsiId keyVaultName: keyVaultName certName: 'armHelperCert' subjectName: 'CN=armhelper.hcp.osadev.cloud' @@ -78,20 +66,17 @@ module armHelperIdentity '../modules/key-vault-cert.bicep' = { issuerName: 'Self' validityInMonths: 1000 } - dependsOn: [ - scriptMsi - ] } // // M S I R P M O CK I D E N T I T Y // -module msiRPMockIdentity '../modules/key-vault-cert.bicep' = { +module msiRPMockIdentity '../modules/keyvault/key-vault-cert.bicep' = { name: 'msi-mock-identity' params: { location: location - keyVaultManagedIdentityId: scriptMsi.outputs.kvCertOfficerManagedIdentityId + keyVaultManagedIdentityId: aroDevopsMsiId keyVaultName: keyVaultName certName: 'msiMockCert' subjectName: 'CN=msimock.hcp.osadev.cloud' @@ -99,7 +84,28 @@ module msiRPMockIdentity '../modules/key-vault-cert.bicep' = { issuerName: 'Self' validityInMonths: 1000 } - dependsOn: [ - scriptMsi - ] +} + +resource msiCustomRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = { + name: guid(subscription().id, 'dev-msi-mock') + properties: { + roleName: 'dev-msi-mock' + description: 'ARO HCP Dev Role for MSI mock principal' + type: 'CustomRole' + permissions: [ + { + actions: [ + 'Microsoft.ManagedIdentity/userAssignedIdentities/read' + 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/read' + 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write' + 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/delete' + ] + notActions: [] + } + ] + assignableScopes: [ + subscription().id + subscriptionResourceId('Microsoft.Resources/resourceGroups/', globalResourceGroupName) + ] + } } diff --git a/dev-infrastructure/templates/output-global.bicep b/dev-infrastructure/templates/output-global.bicep new file mode 100644 index 000000000..9e505296d --- /dev/null +++ b/dev-infrastructure/templates/output-global.bicep @@ -0,0 +1,54 @@ +@description('The name of the OCP ACR') +param ocpAcrName string + +@description('The name of the SVC ACR') +param svcAcrName string + +@description('The CX parent DNS zone name') +param cxParentZoneName string + +@description('The SVC parent DNS zone name') +param svcParentZoneName string + +@description('Metrics global Grafana name') +param grafanaName string + +// +// A C R +// + +resource ocpAcr 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' existing = { + name: ocpAcrName +} + +resource svcAcr 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' existing = { + name: svcAcrName +} + +output ocpAcrResourceId string = ocpAcr.id +output svcAcrResourceId string = svcAcr.id + +// +// D N S +// + +resource cxParentZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { + name: cxParentZoneName +} + +resource svcParentZone 'Microsoft.Network/dnsZones@2018-05-01' existing = { + name: svcParentZoneName +} + +output cxParentZoneResourceId string = cxParentZone.id +output svcParentZoneResourceId string = svcParentZone.id + +// +// G R A F A N A +// + +resource grafana 'Microsoft.Dashboard/grafana@2023-09-01' existing = { + name: grafanaName +} + +output grafanaResourceId string = grafana.id diff --git a/dev-infrastructure/templates/output-region.bicep b/dev-infrastructure/templates/output-region.bicep new file mode 100644 index 000000000..2250cf5ee --- /dev/null +++ b/dev-infrastructure/templates/output-region.bicep @@ -0,0 +1,16 @@ +@description('The name of the Azure Monitor Workspace (stores prometheus metrics)') +param azureMonitorWorkspaceName string + +@description('The name of the eventgrid namespace for Maestro.') +param maestroEventGridNamespacesName string + +resource monitor 'microsoft.monitor/accounts@2021-06-03-preview' existing = { + name: azureMonitorWorkspaceName +} + +resource maestroEventGridNamespace 'Microsoft.EventGrid/namespaces@2024-06-01-preview' existing = { + name: maestroEventGridNamespacesName +} + +output azureMonitoringWorkspaceId string = monitor.id +output maestroEventGridNamespaceId string = maestroEventGridNamespace.id diff --git a/dev-infrastructure/templates/output-svc.bicep b/dev-infrastructure/templates/output-svc.bicep new file mode 100644 index 000000000..682e3cd05 --- /dev/null +++ b/dev-infrastructure/templates/output-svc.bicep @@ -0,0 +1,8 @@ +@description('The name of the CS managed identity') +param csMIName string + +resource csMSI 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: csMIName +} + +output cs string = csMSI.id diff --git a/dev-infrastructure/templates/region.bicep b/dev-infrastructure/templates/region.bicep index ae4b8d8ef..1e6259ef2 100644 --- a/dev-infrastructure/templates/region.bicep +++ b/dev-infrastructure/templates/region.bicep @@ -1,29 +1,41 @@ @description('Azure Region Location') param location string = resourceGroup().location -@description('The name of the keyvault for Maestro Eventgrid namespace certificates.') -param maestroKeyVaultName string - -@description('The name of the managed identity that will manage certificates in maestros keyvault.') -param maestroKeyVaultCertOfficerMSIName string = '${maestroKeyVaultName}-cert-officer-msi' - @description('The name of the eventgrid namespace for Maestro.') param maestroEventGridNamespacesName string @description('The maximum client sessions per authentication name for the EventGrid MQTT broker') param maestroEventGridMaxClientSessionsPerAuthName int +@description('Allow/deny public network access to the Maestro EventGrid Namespace') +param maestroEventGridPrivate bool + @description('Set to true to prevent resources from being pruned after 48 hours') param persist bool = false -@description('This is a global DNS zone name that will be the parent of regional DNS zones to host ARO HCP customer cluster DNS records') -param baseDNSZoneName string +@description(''' + This is the global parent DNS zone for ARO HCP customer cluster DNS. + It is prefixed with regionalDNSSubdomain to form the actual regional DNS zone name + ''') +param cxBaseDNSZoneName string + +@description(''' + This is the global parent DNS zone for ARO HCP service DNS records. + It is prefixed with regionalDNSSubdomain to form the actual regional DNS zone name + ''') +param svcBaseDNSZoneName string @description('The resource group to deploy the base DNS zone to') param baseDNSZoneResourceGroup string = 'global' param regionalDNSSubdomain string +param globalRegion string +param regionalRegion string +param globalResourceGroup string +param ocpAcrName string +param svcAcrName string + // Tags the resource group resource subscriptionTags 'Microsoft.Resources/tags@2024-03-01' = { name: 'default' @@ -36,21 +48,66 @@ resource subscriptionTags 'Microsoft.Resources/tags@2024-03-01' = { } // -// R E G I O N A L D N S Z O N E +// R E G I O N A L C X D N S Z O N E +// + +resource regionalCxZone 'Microsoft.Network/dnsZones@2018-05-01' = { + name: '${regionalDNSSubdomain}.${cxBaseDNSZoneName}' + location: 'global' +} + +module regionalCxZoneDelegation '../modules/dns/zone-delegation.bicep' = { + name: '${regionalDNSSubdomain}-cx-zone-deleg' + scope: resourceGroup(baseDNSZoneResourceGroup) + params: { + childZoneName: regionalDNSSubdomain + childZoneNameservers: regionalCxZone.properties.nameServers + parentZoneName: cxBaseDNSZoneName + } +} + +// +// R E G I O N A L S V C D N S Z O N E // -resource regionalZone 'Microsoft.Network/dnsZones@2018-05-01' = { - name: '${regionalDNSSubdomain}.${baseDNSZoneName}' +resource regionalSvcZone 'Microsoft.Network/dnsZones@2018-05-01' = { + name: '${regionalDNSSubdomain}.${svcBaseDNSZoneName}' location: 'global' } -module regionalZoneDelegation '../modules/dns/zone-delegation.bicep' = { - name: '${deployment().name}-zone-deleg' +module regionalSvcZoneDelegation '../modules/dns/zone-delegation.bicep' = { + name: '${regionalDNSSubdomain}-svc-zone-deleg' scope: resourceGroup(baseDNSZoneResourceGroup) params: { childZoneName: regionalDNSSubdomain - childZoneNameservers: regionalZone.properties.nameServers - parentZoneName: baseDNSZoneName + childZoneNameservers: regionalSvcZone.properties.nameServers + parentZoneName: svcBaseDNSZoneName + } +} + +// +// R E G I O N A L A C R R E P L I C A T I O N +// + +var ocpAcrReplicationName = '${ocpAcrName}${location}replica' +module ocpAcrReplication '../modules/acr/acr-replication.bicep' = if (globalRegion != regionalRegion) { + name: ocpAcrReplicationName + scope: resourceGroup(globalResourceGroup) + params: { + acrReplicationLocation: location + acrReplicationParentAcrName: ocpAcrName + acrReplicationReplicaName: ocpAcrReplicationName + } +} + +var svcAcrReplicationName = '${svcAcrName}${location}replica' +module svcAcrReplication '../modules/acr/acr-replication.bicep' = if (globalRegion != regionalRegion) { + name: svcAcrReplicationName + scope: resourceGroup(globalResourceGroup) + params: { + acrReplicationLocation: location + acrReplicationParentAcrName: svcAcrName + acrReplicationReplicaName: svcAcrReplicationName } } @@ -64,8 +121,6 @@ module maestroInfra '../modules/maestro/maestro-infra.bicep' = { eventGridNamespaceName: maestroEventGridNamespacesName location: location maxClientSessionsPerAuthName: maestroEventGridMaxClientSessionsPerAuthName - maestroKeyVaultName: maestroKeyVaultName - kvCertOfficerManagedIdentityName: maestroKeyVaultCertOfficerMSIName - publicNetworkAccess: 'Enabled' + publicNetworkAccess: maestroEventGridPrivate ? 'Disabled' : 'Enabled' } } diff --git a/dev-infrastructure/templates/svc-cluster.bicep b/dev-infrastructure/templates/svc-cluster.bicep index 7f34a0f51..588d826e9 100644 --- a/dev-infrastructure/templates/svc-cluster.bicep +++ b/dev-infrastructure/templates/svc-cluster.bicep @@ -7,11 +7,32 @@ param persist bool = false @description('AKS cluster name') param aksClusterName string +@description('Minimum node count for system agent pool') +param systemAgentMinCount int + +@description('Maximum node count for system agent pool') +param systemAgentMaxCount int + +@description('VM instance type for the system nodes') +param systemAgentVMSize string + @description('Disk size for the AKS system nodes') -param aksSystemOsDiskSizeGB int = 32 +param aksSystemOsDiskSizeGB int @description('Disk size for the AKS user nodes') -param aksUserOsDiskSizeGB int = 32 +param aksUserOsDiskSizeGB int + +@description('Min replicas for the worker nodes') +param userAgentMinCount int + +@description('Max replicas for the worker nodes') +param userAgentMaxCount int + +@description('VM instance type for the worker nodes') +param userAgentVMSize string + +@description('Number of availability zones to use for the AKS clusters user agent pool') +param userAgentPoolAZCount int @description('Names of additional resource group contains ACRs the AKS cluster will get pull permissions on') param acrPullResourceGroups array = [] @@ -28,11 +49,11 @@ param subnetPrefix string @description('Specifies the address prefix of the subnet hosting the pods of the AKS cluster.') param podSubnetPrefix string -@description('Kuberentes version to use with AKS') +@description('Kubernetes version to use with AKS') param kubernetesVersion string -@description('Istio control plane version to use with AKS') -param istioVersion array +@description('Istio control plane versions to use with AKS. CSV format') +param istioVersions string @description('The name of the keyvault for AKS.') @maxLength(24) @@ -41,6 +62,15 @@ param aksKeyVaultName string @description('Manage soft delete setting for AKS etcd key-value store') param aksEtcdKVEnableSoftDelete bool = true +@description('IPTags to be set on the cluster outbound IP address in the format of ipTagType:tag,ipTagType:tag') +param aksClusterOutboundIPAddressIPTags string = '' + +@description('The name of the Istio Ingress Gateway IP address resource') +param istioIngressGatewayIPAddressName string = '' + +@description('IPTags to be set on the Istio Ingress Gateway IP address in the format of ipTagType:tag,ipTagType:tag') +param istioIngressGatewayIPAddressIPTags string = '' + // TODO: When the work around workload identity for the RP is finalized, change this to true @description('disableLocalAuth for the ARO HCP RP CosmosDB') param disableLocalAuth bool @@ -51,6 +81,9 @@ param deployFrontendCosmos bool @description('The name of the Cosmos DB for the RP') param rpCosmosDbName string +@description('If true, make the Cosmos DB instance private') +param rpCosmosDbPrivate bool + @description('The resourcegroup for regional infrastructure') param regionalResourceGroup string @@ -60,19 +93,16 @@ param maestroCertDomain string @description('The name of the eventgrid namespace for Maestro.') param maestroEventGridNamespacesName string -@description('The name of the keyvault for Maestro Eventgrid namespace certificates.') -param maestroKeyVaultName string - -@description('The name of the managed identity that will manage certificates in maestros keyvault.') -param maestroKeyVaultCertOfficerMSIName string = '${maestroKeyVaultName}-cert-officer-msi' - -@description('Deploy ARO HCP CS Infrastructure if true') -param deployCsInfra bool +@description('Deploy CS Postgres if true') +param csPostgresDeploy bool @description('The name of the Postgres server for CS') @maxLength(60) param csPostgresServerName string +@description('The minimum TLS version for the Postgres server for CS') +param csPostgresServerMinTLSVersion string + @description('If true, make the CS Postgres instance private') param clusterServicePostgresPrivate bool = true @@ -89,26 +119,32 @@ param maestroPostgresServerName string @description('The version of the Postgres server for Maestro') param maestroPostgresServerVersion string +@description('The minimum TLS version for the Postgres server for Maestro') +param maestroPostgresServerMinTLSVersion string + @description('The size of the Postgres server for Maestro') param maestroPostgresServerStorageSizeGB int -@description('The name of the service keyvault') -param serviceKeyVaultName string +@description('The name of the Maestro Postgres database') +param maestroPostgresDatabaseName string -@description('The name of the resourcegroup for the service keyvault') -param serviceKeyVaultResourceGroup string = resourceGroup().name +@description('The name of Maestro Server MQTT client') +param maestroServerMqttClientName string + +@description('The name of the maestro managed identity') +param maestroMIName string -@description('The location of the resourcegroup for the service keyvault') -param serviceKeyVaultLocation string = resourceGroup().location +@description('The namespace of the maestro managed identity') +param maestroNamespace string -@description('Soft delete setting for service keyvault') -param serviceKeyVaultSoftDelete bool = true +@description('The service account name of the maestro managed identity') +param maestroServiceAccountName string -@description('If true, make the service keyvault private and only accessible by the svc cluster via private link.') -param serviceKeyVaultPrivate bool = true +@description('The name of the service keyvault') +param serviceKeyVaultName string -@description('Image sync ACR RG name') -param imageSyncAcrResourceGroupNames array = [] +@description('The name of the resourcegroup for the service keyvault') +param serviceKeyVaultResourceGroup string = resourceGroup().name @description('OIDC Storage Account name') param oidcStorageAccountName string @@ -122,24 +158,40 @@ param clustersServiceAcrResourceGroupNames array = [] @description('MSI that will be used to run the deploymentScript') param aroDevopsMsiId string -@description('This is a regional DNS zone') -param regionalDNSZoneName string +@description('The regional DNS zone to hold ARO HCP customer cluster DNS records') +param regionalCXDNSZoneName string -var clusterServiceMIName = 'clusters-service' +@description('This is a regional DNS zone name to hold records for ARO HCP service components, e.g. the RP') +param regionalSvcDNSZoneName string -// Tags the resource group -resource subscriptionTags 'Microsoft.Resources/tags@2024-03-01' = { - name: 'default' - scope: resourceGroup() - properties: { - tags: { - persist: toLower(string(persist)) - } - } +@description('Frontend Ingress Certificate Name') +param frontendIngressCertName string + +@description('Frontend Ingress Certificate Issuer') +param frontendIngressCertIssuer string + +@description('The name of the Azure Monitor Workspace (stores prometheus metrics)') +param azureMonitorWorkspaceName string + +@description('The name of the CS managed identity') +param csMIName string + +@description('The namespace of the CS managed identity') +param csNamespace string + +@description('The service account name of the CS managed identity') +param csServiceAccountName string + +resource serviceKeyVault 'Microsoft.KeyVault/vaults@2024-04-01-preview' existing = { + name: serviceKeyVaultName + scope: resourceGroup(serviceKeyVaultResourceGroup) } +@description('The name of the Azure DNS zone for the service') +param dnsRecordSetName string = 'frontend.${regionalSvcDNSZoneName}' + module svcCluster '../modules/aks-cluster-base.bicep' = { - name: 'svc-cluster' + name: 'cluster' scope: resourceGroup() params: { location: location @@ -147,15 +199,25 @@ module svcCluster '../modules/aks-cluster-base.bicep' = { aksClusterName: aksClusterName aksNodeResourceGroupName: aksNodeResourceGroupName aksEtcdKVEnableSoftDelete: aksEtcdKVEnableSoftDelete + aksClusterOutboundIPAddressIPTags: aksClusterOutboundIPAddressIPTags kubernetesVersion: kubernetesVersion deployIstio: true - istioVersion: istioVersion + istioVersions: split(istioVersions, ',') + istioIngressGatewayIPAddressName: istioIngressGatewayIPAddressName + istioIngressGatewayIPAddressIPTags: istioIngressGatewayIPAddressIPTags vnetAddressPrefix: vnetAddressPrefix subnetPrefix: subnetPrefix podSubnetPrefix: podSubnetPrefix clusterType: 'svc-cluster' systemOsDiskSizeGB: aksSystemOsDiskSizeGB userOsDiskSizeGB: aksUserOsDiskSizeGB + userAgentMinCount: userAgentMinCount + userAgentMaxCount: userAgentMaxCount + userAgentVMSize: userAgentVMSize + userAgentPoolAZCount: userAgentPoolAZCount + systemAgentMinCount: systemAgentMinCount + systemAgentMaxCount: systemAgentMaxCount + systemAgentVMSize: systemAgentVMSize workloadIdentities: items({ frontend_wi: { uamiName: 'frontend' @@ -168,14 +230,14 @@ module svcCluster '../modules/aks-cluster-base.bicep' = { serviceAccountName: 'backend' } maestro_wi: { - uamiName: 'maestro-server' - namespace: 'maestro' - serviceAccountName: 'maestro' + uamiName: maestroMIName + namespace: maestroNamespace + serviceAccountName: maestroServiceAccountName } cs_wi: { - uamiName: clusterServiceMIName - namespace: 'cluster-service' - serviceAccountName: 'clusters-service' + uamiName: csMIName + namespace: csNamespace + serviceAccountName: csServiceAccountName } image_sync_wi: { uamiName: 'image-sync' @@ -185,10 +247,27 @@ module svcCluster '../modules/aks-cluster-base.bicep' = { }) aksKeyVaultName: aksKeyVaultName acrPullResourceGroups: acrPullResourceGroups + aroDevopsMsiId: aroDevopsMsiId + dcrId: dataCollection.outputs.dcrId } } output aksClusterName string = svcCluster.outputs.aksClusterName + +// +// M E T R I C S +// + +module dataCollection '../modules/metrics/datacollection.bicep' = { + name: '${resourceGroup().name}-${aksClusterName}' + params: { + azureMonitorWorkspaceLocation: location + azureMonitorWorkspaceName: azureMonitorWorkspaceName + regionalResourceGroup: regionalResourceGroup + aksClusterName: aksClusterName + } +} + var frontendMI = filter(svcCluster.outputs.userAssignedIdentities, id => id.uamiName == 'frontend')[0] var backendMI = filter(svcCluster.outputs.userAssignedIdentities, id => id.uamiName == 'backend')[0] @@ -202,6 +281,7 @@ module rpCosmosDb '../modules/rp-cosmos.bicep' = if (deployFrontendCosmos) { vnetId: svcCluster.outputs.aksVnetId disableLocalAuth: disableLocalAuth userAssignedMIs: [frontendMI, backendMI] + private: rpCosmosDbPrivate } } @@ -217,54 +297,45 @@ module maestroServer '../modules/maestro/maestro-server.bicep' = { params: { maestroInfraResourceGroup: regionalResourceGroup maestroEventGridNamespaceName: maestroEventGridNamespacesName - maestroKeyVaultName: maestroKeyVaultName - maestroKeyVaultOfficerManagedIdentityName: maestroKeyVaultCertOfficerMSIName - maestroKeyVaultCertificateDomain: maestroCertDomain + mqttClientName: maestroServerMqttClientName + certKeyVaultName: serviceKeyVaultName + certKeyVaultResourceGroup: serviceKeyVaultResourceGroup + keyVaultOfficerManagedIdentityName: aroDevopsMsiId + maestroCertificateDomain: maestroCertDomain deployPostgres: deployMaestroPostgres postgresServerName: maestroPostgresServerName postgresServerVersion: maestroPostgresServerVersion + postgresServerMinTLSVersion: maestroPostgresServerMinTLSVersion postgresServerStorageSizeGB: maestroPostgresServerStorageSizeGB privateEndpointSubnetId: svcCluster.outputs.aksNodeSubnetId privateEndpointVnetId: svcCluster.outputs.aksVnetId + maestroDatabaseName: maestroPostgresDatabaseName postgresServerPrivate: maestroPostgresPrivate + postgresAdministrationManagedIdentityId: aroDevopsMsiId maestroServerManagedIdentityPrincipalId: filter( svcCluster.outputs.userAssignedIdentities, - id => id.uamiName == 'maestro-server' + id => id.uamiName == maestroMIName )[0].uamiPrincipalID - maestroServerManagedIdentityName: filter( - svcCluster.outputs.userAssignedIdentities, - id => id.uamiName == 'maestro-server' - )[0].uamiName - location: location + maestroServerManagedIdentityName: maestroMIName } + dependsOn: [ + serviceKeyVault + ] } // // K E Y V A U L T S // -module serviceKeyVault '../modules/keyvault/keyvault.bicep' = { - name: '${deployment().name}-svcs-kv' - scope: resourceGroup(serviceKeyVaultResourceGroup) - params: { - location: serviceKeyVaultLocation - keyVaultName: serviceKeyVaultName - private: serviceKeyVaultPrivate - enableSoftDelete: serviceKeyVaultSoftDelete - purpose: 'service' - } -} - -output svcKeyVaultName string = serviceKeyVault.outputs.kvName - -module serviceKeyVaultPrivateEndpoint '../modules/keyvault/keyvault-private-endpoint.bicep' = { +module serviceKeyVaultPrivateEndpoint '../modules/private-endpoint.bicep' = { name: '${deployment().name}-svcs-kv-pe' params: { location: location - keyVaultName: serviceKeyVaultName - subnetId: svcCluster.outputs.aksNodeSubnetId + subnetIds: [svcCluster.outputs.aksNodeSubnetId] vnetId: svcCluster.outputs.aksVnetId - keyVaultId: serviceKeyVault.outputs.kvId + privateLinkServiceId: serviceKeyVault.id + serviceType: 'keyvault' + groupId: 'vault' } } @@ -272,122 +343,41 @@ module serviceKeyVaultPrivateEndpoint '../modules/keyvault/keyvault-private-endp // C L U S T E R S E R V I C E // -var csManagedIdentityPrincipalId = filter( - svcCluster.outputs.userAssignedIdentities, - id => id.uamiName == clusterServiceMIName -)[0].uamiPrincipalID +var csManagedIdentityPrincipalId = filter(svcCluster.outputs.userAssignedIdentities, id => id.uamiName == csMIName)[0].uamiPrincipalID -module cs '../modules/cluster-service.bicep' = if (deployCsInfra) { +module cs '../modules/cluster-service.bicep' = { name: 'cluster-service' params: { - location: location postgresServerName: csPostgresServerName + postgresServerMinTLSVersion: csPostgresServerMinTLSVersion privateEndpointSubnetId: svcCluster.outputs.aksNodeSubnetId privateEndpointVnetId: svcCluster.outputs.aksVnetId + deployPostgres: csPostgresDeploy postgresServerPrivate: clusterServicePostgresPrivate clusterServiceManagedIdentityPrincipalId: csManagedIdentityPrincipalId - clusterServiceManagedIdentityName: clusterServiceMIName + clusterServiceManagedIdentityName: csMIName + serviceKeyVaultName: serviceKeyVault.name + serviceKeyVaultResourceGroup: serviceKeyVaultResourceGroup + regionalCXDNSZoneName: regionalCXDNSZoneName + regionalResourceGroup: regionalResourceGroup + acrResourceGroupNames: clustersServiceAcrResourceGroupNames + postgresAdministrationManagedIdentityId: aroDevopsMsiId } dependsOn: [ maestroServer - svcCluster ] } -module csServiceKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = { - name: guid(serviceKeyVaultName, 'cs', 'read') - scope: resourceGroup(serviceKeyVaultResourceGroup) - params: { - keyVaultName: serviceKeyVaultName - roleName: 'Key Vault Secrets User' - managedIdentityPrincipalId: csManagedIdentityPrincipalId - } - dependsOn: [ - serviceKeyVault - svcCluster - ] -} - -module csDnsZoneContributor '../modules/dns/zone-contributor.bicep' = { - name: guid(regionalDNSZoneName, svcCluster.name, 'cs') - scope: resourceGroup(regionalResourceGroup) - params: { - zoneName: regionalDNSZoneName - zoneContributerManagedIdentityPrincipalId: csManagedIdentityPrincipalId - } -} - -// -// I M A G E S Y N C -// - -var imageSyncManagedIdentityPrincipalId = filter( - svcCluster.outputs.userAssignedIdentities, - id => id.uamiName == 'image-sync' -)[0].uamiPrincipalID - -module imageServiceKeyVaultAccess '../modules/keyvault/keyvault-secret-access.bicep' = { - name: guid(serviceKeyVaultName, 'imagesync', 'read') - scope: resourceGroup(serviceKeyVaultResourceGroup) - params: { - keyVaultName: serviceKeyVaultName - roleName: 'Key Vault Secrets User' - managedIdentityPrincipalId: imageSyncManagedIdentityPrincipalId - } - dependsOn: [ - serviceKeyVault - svcCluster - ] -} - -resource imageSyncAcrResourceGroups 'Microsoft.Resources/resourceGroups@2023-07-01' existing = [ - for rg in imageSyncAcrResourceGroupNames: { - name: rg - scope: subscription() - } -] - -module acrPushRole '../modules/acr-permissions.bicep' = [ - for (_, i) in imageSyncAcrResourceGroupNames: { - name: guid(imageSyncAcrResourceGroups[i].id, resourceGroup().name, 'image-sync', 'push') - scope: imageSyncAcrResourceGroups[i] - params: { - principalId: imageSyncManagedIdentityPrincipalId - grantPushAccess: true - acrResourceGroupid: imageSyncAcrResourceGroups[i].id - } - } -] - -resource clustersServiceAcrResourceGroups 'Microsoft.Resources/resourceGroups@2023-07-01' existing = [ - for rg in clustersServiceAcrResourceGroupNames: { - name: rg - scope: subscription() - } -] - -module acrContributorRole '../modules/acr-permissions.bicep' = [ - for (_, i) in clustersServiceAcrResourceGroupNames: { - name: guid(clustersServiceAcrResourceGroups[i].id, resourceGroup().name, 'clusters-service', 'contributor') - scope: clustersServiceAcrResourceGroups[i] - params: { - principalId: csManagedIdentityPrincipalId - grantContributorAccess: true - acrResourceGroupid: clustersServiceAcrResourceGroups[i].id - } - } -] - -// oidc +// O I D C module oidc '../modules/oidc/main.bicep' = { name: '${deployment().name}-oidc' params: { location: location storageAccountName: oidcStorageAccountName - rpMsiName: clusterServiceMIName + rpMsiName: csMIName skuName: oidcStorageAccountSku - aroDevopsMsiId: aroDevopsMsiId + msiId: aroDevopsMsiId deploymentScriptLocation: location } dependsOn: [ @@ -404,6 +394,7 @@ resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2024-06-01-preview' scope: resourceGroup(regionalResourceGroup) } +// todo manage only if maestro.eventgrid is not set to private module eventGrindPrivateEndpoint '../modules/private-endpoint.bicep' = { name: 'eventGridPrivateEndpoint' params: { @@ -415,3 +406,52 @@ module eventGrindPrivateEndpoint '../modules/private-endpoint.bicep' = { vnetId: svcCluster.outputs.aksVnetId } } + +// +// F R O N T E N D C E R T I F I C A T E +// + +module frontendIngressCert '../modules/keyvault/key-vault-cert.bicep' = { + name: 'frontend-cert-${uniqueString(resourceGroup().name)}' + scope: resourceGroup(serviceKeyVaultResourceGroup) + params: { + keyVaultName: serviceKeyVaultName + subjectName: 'CN=frontend.${regionalSvcDNSZoneName}' + certName: frontendIngressCertName + keyVaultManagedIdentityId: aroDevopsMsiId + dnsNames: [ + 'frontend.${regionalSvcDNSZoneName}' + ] + issuerName: frontendIngressCertIssuer + } +} + +module frontendIngressCertCSIAccess '../modules/keyvault/keyvault-secret-access.bicep' = { + name: 'aksClusterKeyVaultSecretsProviderMI-${frontendIngressCertName}' + scope: resourceGroup(serviceKeyVaultResourceGroup) + params: { + keyVaultName: serviceKeyVaultName + roleName: 'Key Vault Secrets User' + managedIdentityPrincipalId: svcCluster.outputs.aksClusterKeyVaultSecretsProviderPrincipalId + secretName: frontendIngressCertName + } +} + +// FRONTEND DNS + +resource dnsZone 'Microsoft.Network/dnsZones@2022-09-01' existing = { + name: regionalSvcDNSZoneName +} + +resource dnsRecord 'Microsoft.Network/dnsZones/A@2022-09-01' = { + name: dnsRecordSetName + parent: dnsZone + properties: { + TTL: 300 + ARecords: [ + { + ipv4Address: svcCluster.outputs.istioIngressGatewayIPAddress + } + ] + } +} diff --git a/dev-infrastructure/templates/svc-infra.bicep b/dev-infrastructure/templates/svc-infra.bicep new file mode 100644 index 000000000..f70acee09 --- /dev/null +++ b/dev-infrastructure/templates/svc-infra.bicep @@ -0,0 +1,63 @@ +@description('The name of the service keyvault') +param serviceKeyVaultName string + +@description('The name of the resourcegroup for the service keyvault') +param serviceKeyVaultResourceGroup string = resourceGroup().name + +@description('The location of the resourcegroup for the service keyvault') +param serviceKeyVaultLocation string = resourceGroup().location + +@description('Soft delete setting for service keyvault') +param serviceKeyVaultSoftDelete bool = true + +@description('If true, make the service keyvault private and only accessible by the svc cluster via private link.') +param serviceKeyVaultPrivate bool = true + +@description('SVC KV certificate officer principal ID') +param svcKvCertOfficerPrincipalId string + +@description('Set to true to prevent resources from being pruned after 48 hours') +param persist bool = false + +// Tags the resource group +resource resourcegroupTags 'Microsoft.Resources/tags@2024-03-01' = { + name: 'default' + scope: resourceGroup() + properties: { + tags: { + persist: toLower(string(persist)) + } + } +} + +// +// K E Y V A U L T S +// + +module serviceKeyVault '../modules/keyvault/keyvault.bicep' = { + name: 'svc-kv' + scope: resourceGroup(serviceKeyVaultResourceGroup) + params: { + location: serviceKeyVaultLocation + keyVaultName: serviceKeyVaultName + private: serviceKeyVaultPrivate + enableSoftDelete: serviceKeyVaultSoftDelete + purpose: 'service' + } +} + +module serviceKeyVaultDevopsCertOfficer '../modules/keyvault/keyvault-secret-access.bicep' = { + name: 'svc-kv-cert-officer' + scope: resourceGroup(serviceKeyVaultResourceGroup) + params: { + keyVaultName: serviceKeyVaultName + roleName: 'Key Vault Certificates Officer' + managedIdentityPrincipalId: svcKvCertOfficerPrincipalId + } + dependsOn: [ + serviceKeyVault + ] +} + +output svcKeyVaultName string = serviceKeyVault.outputs.kvName +output svcKeyVaultUrl string = serviceKeyVault.outputs.kvUrl diff --git a/frontend/.gitignore b/frontend/.gitignore index aee2e4ce1..e69de29bb 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1 +0,0 @@ -config.mk diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 37d1882d3..f2f9a71a4 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,5 +1,5 @@ # Base and builder image will need to be replaced by Fips compliant one -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:6c1b07df15c152fb6a7f4eeece5f50824d83b8bf672709cc951aaa0d5c29887f as builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:97d76864911dfbaf6b3387b6e0583abe5af74d7b744773c4facbaf02389e654f as builder WORKDIR /app ADD archive.tar.gz . @@ -7,7 +7,7 @@ ADD archive.tar.gz . ENV CGO_ENABLED=1 GOFLAGS='-tags=requirefips' RUN cd frontend && make frontend -FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:acb1ab4d2162ecebbe67888bf679f26dcaef29c153954a09396e020e9639862d +FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:ce44fc29db88c9aba8041a50c1abcd19a54f997c2b99a8c513e8ec113261374a WORKDIR / COPY --from=builder /app/frontend/aro-hcp-frontend . ENTRYPOINT ["/aro-hcp-frontend"] diff --git a/frontend/Makefile b/frontend/Makefile index b8145fc93..4e83fb918 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -1,24 +1,34 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install -COMMIT = $(shell git rev-parse --short=7 HEAD) -ARO_HCP_BASE_IMAGE ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io -ARO_HCP_FRONTEND_IMAGE ?= $(ARO_HCP_BASE_IMAGE)/arohcpfrontend:$(COMMIT) +ifndef COMMIT +COMMIT := $(shell git rev-parse --short=7 HEAD) +endif +ARO_HCP_IMAGE_REGISTRY ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io +ARO_HCP_IMAGE_REPOSITORY ?= arohcpfrontend +ARO_HCP_FRONTEND_IMAGE ?= $(ARO_HCP_IMAGE_REGISTRY)/$(ARO_HCP_IMAGE_REPOSITORY):$(COMMIT) + +.DEFAULT_GOAL := frontend frontend: go build -o aro-hcp-frontend . +info: + @echo "ARO_HCP_FRONTEND_IMAGE: ${ARO_HCP_FRONTEND_IMAGE}" + @echo "COMMIT: ${COMMIT}" + run: - ./aro-hcp-frontend --use-cache --location ${LOCATION} \ + DB_URL=$$(az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ + ./aro-hcp-frontend --location ${LOCATION} \ --clusters-service-url http://localhost:8000 \ - --cluster-service-provision-shard 1 \ - --cluster-service-noop-provision \ - --cluster-service-noop-deprovision + --cosmos-name ${DB_NAME} \ + --cosmos-url $${DB_URL} +.PHONY: run clean: rm -f aro-hcp-frontend +.PHONY: clean build-push: image push @@ -26,35 +36,63 @@ image: pushd .. && git archive --output frontend/archive.tar.gz HEAD && popd docker build -f "./Dockerfile" -t ${ARO_HCP_FRONTEND_IMAGE} . rm -f archive.tar.gz +.PHONY: image push: image az acr login --name ${ARO_HCP_IMAGE_ACR} docker push ${ARO_HCP_FRONTEND_IMAGE} deploy: - FRONTEND_MI_CLIENT_ID=$(shell az identity show \ + FRONTEND_MI_CLIENT_ID=$$(az identity show \ + -g ${RESOURCEGROUP} \ + -n frontend \ + --query clientId -o tsv) && \ + FRONTEND_MI_TENANT_ID=$$(az identity show \ -g ${RESOURCEGROUP} \ -n frontend \ - --query clientId);\ - ISTO_VERSION=$(shell az aks show -n ${AKS_NAME} -g ${RESOURCEGROUP} --query serviceMeshProfile.istio.revisions[-1] -o tsv) && \ - DB_URL=$(shell az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ + --query tenantId -o tsv) &&\ + IMAGE_PULLER_MI_CLIENT_ID=$$(az identity show \ + -g ${RESOURCEGROUP} \ + -n image-puller \ + --query clientId -o tsv) && \ + IMAGE_PULLER_MI_TENANT_ID=$$(az identity show \ + -g ${RESOURCEGROUP} \ + -n image-puller \ + --query tenantId -o tsv) && \ + SECRET_STORE_MI_CLIENT_ID=$$(az aks show --resource-group ${RESOURCEGROUP} \ + --name ${AKS_NAME} \ + --query addonProfiles.azureKeyvaultSecretsProvider.identity.clientId \ + --output tsv) && \ + TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ + DB_URL=$$(az cosmosdb show -n ${DB_NAME} -g ${RESOURCEGROUP} --query documentEndpoint -o tsv) && \ kubectl create namespace aro-hcp --dry-run=client -o json | kubectl apply -f - && \ - kubectl label namespace aro-hcp "istio.io/rev=$${ISTO_VERSION}" --overwrite=true && \ - helm upgrade --install aro-hcp-frontend-dev \ + kubectl label namespace aro-hcp "istio.io/rev=${ISTO_TAG}" --overwrite=true && \ + ${HELM_CMD} aro-hcp-frontend-dev \ deploy/helm/frontend/ \ + --set azure.clientId=$${SECRET_STORE_MI_CLIENT_ID} \ + --set azure.tenantId=$${TENANT_ID} \ --set configMap.databaseName=${DB_NAME} \ --set configMap.databaseUrl="$${DB_URL}" \ --set configMap.frontendMiClientId="$${FRONTEND_MI_CLIENT_ID}" \ + --set credsKeyVault.name=${SERVICE_KEY_VAULT} \ + --set credsKeyVault.secret=${CERTIFICATE_NAME} \ --set serviceAccount.workloadIdentityClientId="$${FRONTEND_MI_CLIENT_ID}" \ + --set serviceAccount.workloadIdentityTenantId="$${FRONTEND_MI_TENANT_ID}" \ + --set pullBinding.workloadIdentityClientId="$${IMAGE_PULLER_MI_CLIENT_ID}" \ + --set pullBinding.workloadIdentityTenantId="$${IMAGE_PULLER_MI_TENANT_ID}" \ --set configMap.currentVersion=${ARO_HCP_FRONTEND_IMAGE} \ --set configMap.location=${LOCATION} \ --set deployment.imageName=${ARO_HCP_FRONTEND_IMAGE} \ + --set pullBinding.registry=${ARO_HCP_IMAGE_REGISTRY} \ + --set pullBinding.scope=repository:${ARO_HCP_IMAGE_REPOSITORY}:pull \ + --set clusterService.namespace=${CS_NAMESPACE} \ + --set clusterService.serviceAccount=${CS_SERVICE_ACCOUNT_NAME} \ --namespace aro-hcp +.PHONY: deploy undeploy: helm uninstall aro-hcp-frontend-dev --namespace aro-hcp +.PHONY: undeploy smoke-tests: go test -v -count 1 ./utils/frontend_smoke_test.go - -.PHONY: frontend clean image deploy undeploy diff --git a/frontend/README.md b/frontend/README.md index 8130b3a46..abbf55653 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -5,23 +5,18 @@ make frontend ``` -## Run the frontend binary locally (requires a local running CS to fully function) -``` -make run -``` - ## Build the frontend container ```bash # Note: for testing changes, please use your own registry # versus pushing images to the DEV ACR -export ARO_HCP_BASE_IMAGE="quay.io/QUAY_USERNAME" +export ARO_HCP_IMAGE_REGISTRY="quay.io/QUAY_USERNAME" make image # Push the image to a container registry make push # all in one option -export ARO_HCP_BASE_IMAGE="quay.io/QUAY_USERNAME" +export ARO_HCP_IMAGE_REGISTRY="quay.io/QUAY_USERNAME" make build-push ``` @@ -77,12 +72,17 @@ curl -X GET "localhost:8443/subscriptions/00000000-0000-0000-0000-000000000000/r ``` Create or Update a HcpOpenShiftClusterResource + ```bash curl -X PUT "localhost:8443/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/dev-test-rg/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/dev-test-cluster?api-version=2024-06-10-preview" \ -H "X-Ms-Arm-Resource-System-Data: {\"createdBy\": \"aro-hcp-local-testing\", \"createdByType\": \"User\", \"createdAt\": \"2024-06-06T19:26:56+00:00\"}" \ + -H "X-Ms-Identity-Url": https://dummyhost.identity.azure.net" \ --json @cluster.json ``` +You will notice that the request contains a `X-Ms-Identity-Url` with the value `https://dummyhost.identity.azure.net`. Setting the `X-Ms-Identity-Url` HTTP header when interacting directly +with the Frontend is required. However, for the environments where a real managed identities data plane does not exist the value can be any arbitrary/dummy HTTPS URL that ends in `identity.azure.net`. + Delete a HcpOpenShiftClusterResource ```bash curl -X DELETE "localhost:8443/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/dev-test-rg/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/dev-test-cluster?api-version=2024-06-10-preview" diff --git a/frontend/cmd/cmd.go b/frontend/cmd/cmd.go index 2b72589ea..20c3df1bb 100644 --- a/frontend/cmd/cmd.go +++ b/frontend/cmd/cmd.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net" + "net/http" "os" "os/signal" "runtime/debug" @@ -12,14 +13,16 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" sdk "github.com/openshift-online/ocm-sdk-go" + "github.com/prometheus/client_golang/prometheus" "github.com/spf13/cobra" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/frontend/pkg/frontend" "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" "github.com/Azure/ARO-HCP/internal/ocm" ) @@ -35,7 +38,6 @@ type FrontendOpts struct { metricsPort int port int - useCache bool cosmosName string cosmosURL string } @@ -60,9 +62,8 @@ func NewRootCmd() *cobra.Command { }, } - rootCmd.Flags().BoolVar(&opts.useCache, "use-cache", false, "leverage a local cache instead of reaching out to a database") rootCmd.Flags().StringVar(&opts.cosmosName, "cosmos-name", os.Getenv("DB_NAME"), "Cosmos database name") - rootCmd.Flags().StringVar(&opts.cosmosURL, "cosmos-url", os.Getenv("DB_URL"), "Cosmos database url") + rootCmd.Flags().StringVar(&opts.cosmosURL, "cosmos-url", os.Getenv("DB_URL"), "Cosmos database URL") rootCmd.Flags().StringVar(&opts.location, "location", os.Getenv("LOCATION"), "Azure location") rootCmd.Flags().IntVar(&opts.port, "port", 8443, "port to listen on") rootCmd.Flags().IntVar(&opts.metricsPort, "metrics-port", 8081, "port to serve metrics on") @@ -73,55 +74,58 @@ func NewRootCmd() *cobra.Command { rootCmd.Flags().BoolVar(&opts.clusterServiceNoopProvision, "cluster-service-noop-provision", false, "Skip cluster service provisioning steps for development purposes") rootCmd.Flags().BoolVar(&opts.clusterServiceNoopDeprovision, "cluster-service-noop-deprovision", false, "Skip cluster service deprovisioning steps for development purposes") - rootCmd.MarkFlagsMutuallyExclusive("use-cache", "cosmos-name") - rootCmd.MarkFlagsMutuallyExclusive("use-cache", "cosmos-url") rootCmd.MarkFlagsRequiredTogether("cosmos-name", "cosmos-url") return rootCmd } -func (opts *FrontendOpts) Run() error { - logger := config.DefaultLogger() - logger.Info(fmt.Sprintf("%s (%s) started", frontend.ProgramName, version())) +type policyFunc func(*policy.Request) (*http.Response, error) - // Init prometheus emitter - prometheusEmitter := frontend.NewPrometheusEmitter() +func (pf policyFunc) Do(req *policy.Request) (*http.Response, error) { + return pf(req) +} - // Configure database configuration and client - dbClient := database.NewCache() - if !opts.useCache { - var err error +// Verify that policyFunc implements the policy.Policy interface. +var _ policy.Policy = policyFunc(nil) + +// correlationIDPolicy adds the ARM correlation request ID to the request's +// HTTP headers if the ID is found in the context. +func correlationIDPolicy(req *policy.Request) (*http.Response, error) { + cd, err := frontend.CorrelationDataFromContext(req.Raw().Context()) + // The incoming request may not contain a correlation request ID (e.g. + // requests to /healthz). + if err == nil && cd.CorrelationRequestID != "" { + req.Raw().Header.Set(arm.HeaderNameCorrelationRequestID, cd.CorrelationRequestID) + } - azcoreClientOptions := azcore.ClientOptions{ - // FIXME Cloud should be determined by other means. - Cloud: cloud.AzurePublic, - } + return req.Next() +} - credential, err := azidentity.NewDefaultAzureCredential( - &azidentity.DefaultAzureCredentialOptions{ - ClientOptions: azcoreClientOptions, - }) - if err != nil { - return err - } +func (opts *FrontendOpts) Run() error { + logger := config.DefaultLogger() + logger.Info(fmt.Sprintf("%s (%s) started", frontend.ProgramName, version())) - cosmosClient, err := azcosmos.NewClient(opts.cosmosURL, credential, - &azcosmos.ClientOptions{ - ClientOptions: azcoreClientOptions, - }) - if err != nil { - return err - } + // Init the Prometheus emitter. + prometheusEmitter := frontend.NewPrometheusEmitter(prometheus.DefaultRegisterer) - cosmosDatabaseClient, err := cosmosClient.NewDatabase(opts.cosmosName) - if err != nil { - return err - } + // Create the database client. + ctx := context.Background() + cosmosDatabaseClient, err := database.NewCosmosDatabaseClient( + opts.cosmosURL, + opts.cosmosName, + azcore.ClientOptions{ + // FIXME Cloud should be determined by other means. + Cloud: cloud.AzurePublic, + PerCallPolicies: []policy.Policy{policyFunc(correlationIDPolicy)}, + }, + ) + if err != nil { + return fmt.Errorf("failed to create the CosmosDB client: %w", err) + } - dbClient, err = database.NewCosmosDBClient(context.Background(), cosmosDatabaseClient) - if err != nil { - return fmt.Errorf("creating the database client failed: %v", err) - } + dbClient, err := database.NewDBClient(ctx, cosmosDatabaseClient) + if err != nil { + return fmt.Errorf("failed to create the database client: %w", err) } listener, err := net.Listen("tcp4", fmt.Sprintf(":%d", opts.port)) @@ -136,6 +140,9 @@ func (opts *FrontendOpts) Run() error { // Initialize Clusters Service Client conn, err := sdk.NewUnauthenticatedConnectionBuilder(). + TransportWrapper(func(r http.RoundTripper) http.RoundTripper { + return otelhttp.NewTransport(r) + }). URL(opts.clustersServiceURL). Insecure(opts.insecure). Build() @@ -163,7 +170,7 @@ func (opts *FrontendOpts) Run() error { stop := make(chan struct{}) signalChannel := make(chan os.Signal, 1) signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM) - go f.Run(context.Background(), stop) + go f.Run(ctx, stop) sig := <-signalChannel logger.Info(fmt.Sprintf("caught %s signal", sig)) diff --git a/frontend/config.tmpl.mk b/frontend/config.tmpl.mk deleted file mode 100644 index 5488940ea..000000000 --- a/frontend/config.tmpl.mk +++ /dev/null @@ -1,5 +0,0 @@ -ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} -LOCATION ?= {{ .region }} -RESOURCEGROUP ?= {{ .serviceClusterRG }} -AKS_NAME ?= {{ .aksName }} -DB_NAME ?= {{ .frontendCosmosDBName }} diff --git a/frontend/deploy/helm/frontend/templates/acrpullbinding.yaml b/frontend/deploy/helm/frontend/templates/acrpullbinding.yaml new file mode 100644 index 000000000..6c509b939 --- /dev/null +++ b/frontend/deploy/helm/frontend/templates/acrpullbinding.yaml @@ -0,0 +1,15 @@ +apiVersion: acrpull.microsoft.com/v1beta2 +kind: AcrPullBinding +metadata: + name: pull-binding +spec: + acr: + environment: PublicCloud + server: {{ .Values.pullBinding.registry }} + scope: {{ .Values.pullBinding.scope }} + auth: + workloadIdentity: + serviceAccountRef: frontend + clientID: {{ .Values.pullBinding.workloadIdentityClientId }} + tenantID: {{ .Values.pullBinding.workloadIdentityTenantId }} + serviceAccountName: frontend diff --git a/frontend/deploy/helm/frontend/templates/allow-ingress.authorizationpolicy.yaml b/frontend/deploy/helm/frontend/templates/allow-ingress.authorizationpolicy.yaml new file mode 100644 index 000000000..d3cf0c7ee --- /dev/null +++ b/frontend/deploy/helm/frontend/templates/allow-ingress.authorizationpolicy.yaml @@ -0,0 +1,16 @@ +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: allow-istio-ingress + namespace: aro-hcp +spec: + action: ALLOW + rules: + - from: + - source: + namespaces: ["aks-istio-ingress"] + to: + - operation: + methods: ["GET"] + ports: + - "8443" diff --git a/frontend/deploy/helm/frontend/templates/frontend.deployment.yaml b/frontend/deploy/helm/frontend/templates/frontend.deployment.yaml index e9c63c458..3eba3803c 100644 --- a/frontend/deploy/helm/frontend/templates/frontend.deployment.yaml +++ b/frontend/deploy/helm/frontend/templates/frontend.deployment.yaml @@ -27,7 +27,7 @@ spec: - name: aro-hcp-frontend image: '{{ .Values.deployment.imageName }}' imagePullPolicy: Always - args: ["--clusters-service-url", "http://clusters-service.cluster-service.svc.cluster.local:8000"] + args: ["--clusters-service-url", "http://clusters-service.{{ .Values.clusterService.namespace }}.svc.cluster.local:8000"] env: - name: DB_NAME valueFrom: diff --git a/frontend/deploy/helm/frontend/templates/frontend.gateway.yaml b/frontend/deploy/helm/frontend/templates/frontend.gateway.yaml index ec68d02ec..a1d2ef4c0 100644 --- a/frontend/deploy/helm/frontend/templates/frontend.gateway.yaml +++ b/frontend/deploy/helm/frontend/templates/frontend.gateway.yaml @@ -2,13 +2,17 @@ apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: aro-hcp-gateway-external + namespace: aks-istio-ingress spec: selector: istio: aks-istio-ingressgateway-external servers: - - port: - number: 80 - name: http - protocol: HTTP - hosts: - - "*" + - port: + number: 443 + name: https + protocol: HTTPS + tls: + mode: SIMPLE + credentialName: frontend-credential + hosts: + - "*" diff --git a/frontend/deploy/helm/frontend/templates/frontend.secret-refresher.yaml b/frontend/deploy/helm/frontend/templates/frontend.secret-refresher.yaml new file mode 100644 index 000000000..8fbb13328 --- /dev/null +++ b/frontend/deploy/helm/frontend/templates/frontend.secret-refresher.yaml @@ -0,0 +1,41 @@ +################################ +# +# This keeps the certificate secret fresh because the secret is mounted from the keyVault (via the SecretProviderClass) and +# it's if the certificate changes in the keyvault this will trigger the refreshing of the kubernetes secret. +# +# Note: the istio plugin doesn't support using the SecretProviderClass directly. When it does this can be removed. +# +################################ + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend-certificate-refresher + namespace: aks-istio-ingress +spec: + replicas: 1 + selector: + matchLabels: + app: frontend-certificate-refresher + template: + metadata: + labels: + app: frontend-certificate-refresher + spec: + containers: + - command: + - "/bin/sleep" + - "infinity" + image: mcr.microsoft.com/cbl-mariner/busybox:1.35 + name: init-container-msg-container-init + volumeMounts: + - name: secrets-store01-inline + mountPath: "/mnt/secrets-store" + readOnly: true + volumes: + - name: secrets-store01-inline + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: "frontend-scp" diff --git a/frontend/deploy/helm/frontend/templates/frontend.secretproviderclass.yaml b/frontend/deploy/helm/frontend/templates/frontend.secretproviderclass.yaml new file mode 100644 index 000000000..07aadd2b9 --- /dev/null +++ b/frontend/deploy/helm/frontend/templates/frontend.secretproviderclass.yaml @@ -0,0 +1,34 @@ +################################ +# +# The addition of the secretObjects is to facilitate the istio plugin as it can't yet consume the SecretProviderClass directly. +# When it does this can be simplified and the secret.refresher removed. +# +################################ + +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: frontend-scp + namespace: aks-istio-ingress +spec: + parameters: + usePodIdentity: "false" + useVMManagedIdentity: "true" + userAssignedIdentityID: {{ .Values.azure.clientId}} + keyvaultName: {{ .Values.credsKeyVault.name }} + objects: |- + array: + - | + objectName: {{ .Values.credsKeyVault.secret }} + objectType: secret + objectAlias: frontend-cert + tenantId: {{ .Values.azure.tenantId }} + provider: azure + secretObjects: + - secretName: frontend-credential + type: kubernetes.io/tls + data: + - objectName: frontend-cert + key: tls.crt + - objectName: frontend-cert + key: tls.key diff --git a/frontend/deploy/helm/frontend/templates/frontend.virtualservice.yaml b/frontend/deploy/helm/frontend/templates/frontend.virtualservice.yaml index e79caff25..5a3290147 100644 --- a/frontend/deploy/helm/frontend/templates/frontend.virtualservice.yaml +++ b/frontend/deploy/helm/frontend/templates/frontend.virtualservice.yaml @@ -2,14 +2,16 @@ apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: aro-hcp-vs-frontend + namespace: {{ .Release.Namespace }} spec: hosts: - "*" gateways: - - aro-hcp-gateway-external + - aks-istio-ingress/aro-hcp-gateway-external http: - match: - - port: 80 + - uri: + regex: '.+' route: - destination: host: aro-hcp-frontend diff --git a/frontend/deploy/helm/frontend/templates/serviceaccount.yaml b/frontend/deploy/helm/frontend/templates/serviceaccount.yaml index 770aea829..0e44510db 100644 --- a/frontend/deploy/helm/frontend/templates/serviceaccount.yaml +++ b/frontend/deploy/helm/frontend/templates/serviceaccount.yaml @@ -3,4 +3,5 @@ kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: '{{ .Values.serviceAccount.workloadIdentityClientId }}' + azure.workload.identity/tenant-id: '{{ .Values.serviceAccount.workloadIdentityTenantId }}' name: frontend diff --git a/frontend/deploy/helm/frontend/values.yaml b/frontend/deploy/helm/frontend/values.yaml index 8f71f75d5..2c17154c1 100644 --- a/frontend/deploy/helm/frontend/values.yaml +++ b/frontend/deploy/helm/frontend/values.yaml @@ -1,10 +1,25 @@ +azure: + clientId: "" + tenantId: "" configMap: databaseUrl: "" frontendMiClientId: "" currentVersion: "" databaseName: "" location: "" +credsKeyVault: + name: "" + secret: "" deployment: imageName: "" serviceAccount: workloadIdentityClientId: "" + workloadIdentityTenantId: "" +pullBinding: + registry: "" + scope: "" + workloadIdentityClientId: "" + workloadIdentityTenantId: "" +clusterService: + namespace: cluster-service + serviceAccount: clusters-service diff --git a/frontend/go.mod b/frontend/go.mod index c43276384..73fd18ee3 100644 --- a/frontend/go.mod +++ b/frontend/go.mod @@ -6,38 +6,75 @@ require ( github.com/Azure/ARO-HCP/internal v0.0.0-00010101000000-000000000000 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 - github.com/openshift-online/ocm-sdk-go v0.1.447 + github.com/openshift-online/ocm-sdk-go v0.1.456 github.com/prometheus/client_golang v1.20.5 github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.10.0 + go.opentelemetry.io/contrib/exporters/autoexport v0.59.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 + go.opentelemetry.io/otel v1.34.0 + go.opentelemetry.io/otel/sdk v1.34.0 + go.opentelemetry.io/otel/trace v1.34.0 + go.uber.org/mock v0.5.0 golang.org/x/exp v0.0.0-20240707233637-46b078467d37 - golang.org/x/sync v0.8.0 + golang.org/x/sync v0.10.0 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/objx v0.5.2 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/bridges/prometheus v0.59.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.56.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 // indirect + go.opentelemetry.io/otel/log v0.10.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.10.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/grpc v1.69.4 // indirect ) require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 - github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/go-playground/validator/v10 v10.24.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect @@ -47,16 +84,16 @@ require ( github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.22.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/protobuf v1.36.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/frontend/go.sum b/frontend/go.sum index bfecd2ce6..be4e20e34 100644 --- a/frontend/go.sum +++ b/frontend/go.sum @@ -2,20 +2,20 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 h1:c726lgbwpwFBuj+Fyrwuh/vUilqFo+hUAOUNjsKj5DI= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0/go.mod h1:WzFGxuepAtZIZtQbz8/WviJycLMKJHpaEAqcXONxlag= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 h1:1y5G4XTBTEt0nKNFtM7j6CxqkY5fxSuJb/mD8Zf0gPc= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0/go.mod h1:1Dp+C8Sly0hnhX8k5zDuw72Z2ehd9Lv+pkLFn8dgXMA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -34,24 +34,29 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg= +github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= @@ -70,6 +75,8 @@ 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/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/itchyny/gojq v0.12.7 h1:hYPTpeWfrJ1OT+2j6cvBScbhl0TkdwGM4bc66onUSOQ= @@ -98,8 +105,8 @@ github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKu github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -121,8 +128,8 @@ github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/openshift-online/ocm-sdk-go v0.1.447 h1:PLau6NVgTpwL+L5OcKrBZm+HbET34tjHbENd2GsFhRw= -github.com/openshift-online/ocm-sdk-go v0.1.447/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= +github.com/openshift-online/ocm-sdk-go v0.1.456 h1:N9AmVv8H+FSlld88iCsafy+8Lhykz/1XUrmVhww/BYM= +github.com/openshift-online/ocm-sdk-go v0.1.456/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784 h1:SmOZFMxuAH4d1Cj7dOftVyo4Wg/mEC4pwz6QIJJsAkc= github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -136,14 +143,14 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= @@ -152,16 +159,68 @@ github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3k 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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/bridges/prometheus v0.59.0 h1:HY2hJ7yn3KuEBBBsKxvF3ViSmzLwsgeNvD+0utRMgzc= +go.opentelemetry.io/contrib/bridges/prometheus v0.59.0/go.mod h1:H4H7vs8766kwFnOZVEGMJFVF+phpBSmTckvvNRdJeDI= +go.opentelemetry.io/contrib/exporters/autoexport v0.59.0 h1:dKhAFwh7SSoOw+gwMtSv+XLkUGTFAwAGMT3X3XSE4FA= +go.opentelemetry.io/contrib/exporters/autoexport v0.59.0/go.mod h1:fPl+qlrhRdRntIpPs9JoQ0iBKAsnH5VkgppU1f9kyF4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0 h1:q/heq5Zh8xV1+7GoMGJpTxM2Lhq5+bFxB29tshuRuw0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.10.0/go.mod h1:leO2CSTg0Y+LyvmR7Wm4pUxE8KAmaM2GCVx7O+RATLA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 h1:opwv08VbCZ8iecIWs+McMdHRcAXzjAeda3uG2kI/hcA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0/go.mod h1:oOP3ABpW7vFHulLpE8aYtNBodrHhMTrvfxUXGvqm7Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0 h1:GnCIi0QyG0yy2MrJLzVrIM7laaJstj//flf1zEJCG+E= +go.opentelemetry.io/otel/exporters/prometheus v0.56.0/go.mod h1:JQcVZtbIIPM+7SWBB+T6FK+xunlyidwLp++fN0sUaOk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0 h1:GKCEAZLEpEf78cUvudQdTg0aET2ObOZRB2HtXA0qPAI= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.10.0/go.mod h1:9/zqSWLCmHT/9Jo6fYeUDRRogOLL60ABLsHWS99lF8s= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0 h1:czJDQwFrMbOr9Kk+BPo1y8WZIIFIK58SA1kykuVeiOU= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.34.0/go.mod h1:lT7bmsxOe58Tq+JIOkTQMCGXdu47oA+VJKLZHbaBKbs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU= +go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= +go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +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/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 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.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -170,25 +229,25 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn 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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 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= @@ -199,8 +258,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/frontend/pipeline.yaml b/frontend/pipeline.yaml new file mode 100644 index 000000000..a954cd622 --- /dev/null +++ b/frontend/pipeline.yaml @@ -0,0 +1,38 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.Frontend +rolloutName: RP Frontend Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ARO_HCP_IMAGE_ACR + configRef: svcAcrName + - name: LOCATION + configRef: region + - name: RESOURCEGROUP + configRef: svc.rg + - name: AKS_NAME + configRef: aksName + - name: DB_NAME + configRef: frontend.cosmosDB.name + - name: COMMIT + configRef: frontend.imageTag + - name: SERVICE_KEY_VAULT + configRef: serviceKeyVault.name + - name: CERTIFICATE_NAME + configRef: frontend.cert.name + - name: ISTO_TAG + configRef: svc.istio.tag + - name: CS_NAMESPACE + configRef: clusterService.k8s.namespace + - name: CS_SERVICE_ACCOUNT_NAME + configRef: clusterService.k8s.serviceAccountName diff --git a/frontend/pkg/frontend/context.go b/frontend/pkg/frontend/context.go index c8ad72d19..4c871b3bd 100644 --- a/frontend/pkg/frontend/context.go +++ b/frontend/pkg/frontend/context.go @@ -5,6 +5,9 @@ import ( "fmt" "log/slog" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" @@ -69,15 +72,18 @@ func ContextWithLogger(ctx context.Context, logger *slog.Logger) context.Context return context.WithValue(ctx, contextKeyLogger, logger) } -func LoggerFromContext(ctx context.Context) (*slog.Logger, error) { +func LoggerFromContext(ctx context.Context) *slog.Logger { logger, ok := ctx.Value(contextKeyLogger).(*slog.Logger) if !ok { err := &ContextError{ got: logger, } - return logger, err + // Return the default logger as a fail-safe, but log + // the failure to obtain the logger from the context. + logger = config.DefaultLogger() + logger.Error(err.Error()) } - return logger, nil + return logger } func ContextWithVersion(ctx context.Context, version api.Version) context.Context { @@ -110,12 +116,12 @@ func DBClientFromContext(ctx context.Context) (database.DBClient, error) { return dbClient, nil } -func ContextWithResourceID(ctx context.Context, resourceID *arm.ResourceID) context.Context { +func ContextWithResourceID(ctx context.Context, resourceID *azcorearm.ResourceID) context.Context { return context.WithValue(ctx, contextKeyResourceID, resourceID) } -func ResourceIDFromContext(ctx context.Context) (*arm.ResourceID, error) { - resourceID, ok := ctx.Value(contextKeyResourceID).(*arm.ResourceID) +func ResourceIDFromContext(ctx context.Context) (*azcorearm.ResourceID, error) { + resourceID, ok := ctx.Value(contextKeyResourceID).(*azcorearm.ResourceID) if !ok { err := &ContextError{ got: resourceID, diff --git a/frontend/pkg/frontend/frontend.go b/frontend/pkg/frontend/frontend.go index 1d01a4ae8..c19b386a8 100644 --- a/frontend/pkg/frontend/frontend.go +++ b/frontend/pkg/frontend/frontend.go @@ -13,11 +13,13 @@ import ( "net" "net/http" "os" + "path" "strconv" "strings" "sync/atomic" - cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" "golang.org/x/sync/errgroup" "github.com/Azure/ARO-HCP/internal/api" @@ -28,7 +30,6 @@ import ( type Frontend struct { clusterServiceClient ocm.ClusterServiceClientSpec - logger *slog.Logger listener net.Listener metricsListener net.Listener server http.Server @@ -43,7 +44,6 @@ type Frontend struct { func NewFrontend(logger *slog.Logger, listener net.Listener, metricsListener net.Listener, emitter Emitter, dbClient database.DBClient, location string, csClient ocm.ClusterServiceClientSpec) *Frontend { f := &Frontend{ clusterServiceClient: csClient, - logger: logger, listener: listener, metricsListener: metricsListener, metrics: emitter, @@ -74,17 +74,27 @@ func NewFrontend(logger *slog.Logger, listener net.Listener, metricsListener net } func (f *Frontend) Run(ctx context.Context, stop <-chan struct{}) { + // This just digs up the logger passed to NewFrontend. + logger := LoggerFromContext(f.server.BaseContext(f.listener)) + + otelShutdown, err := InstallOpenTelemetryTracer(ctx, logger) + if err != nil { + logger.Error("could not initialize opentelemetry sdk", "error", err) + os.Exit(1) + } + if stop != nil { go func() { <-stop f.ready.Store(false) _ = f.server.Shutdown(ctx) _ = f.metricsServer.Shutdown(ctx) + _ = otelShutdown(ctx) }() } - f.logger.Info(fmt.Sprintf("listening on %s", f.listener.Addr().String())) - f.logger.Info(fmt.Sprintf("metrics listening on %s", f.metricsListener.Addr().String())) + logger.Info(fmt.Sprintf("listening on %s", f.listener.Addr().String())) + logger.Info(fmt.Sprintf("metrics listening on %s", f.metricsListener.Addr().String())) f.ready.Store(true) errs, ctx := errgroup.WithContext(ctx) @@ -96,7 +106,7 @@ func (f *Frontend) Run(ctx context.Context, stop <-chan struct{}) { }) if err := errs.Wait(); !errors.Is(err, http.ErrServerClosed) { - f.logger.Error(err.Error()) + logger.Error(err.Error()) os.Exit(1) } @@ -108,12 +118,14 @@ func (f *Frontend) Join() { } func (f *Frontend) CheckReady(ctx context.Context) bool { + logger := LoggerFromContext(ctx) + // Verify the DB is available and accessible if err := f.dbClient.DBConnectionTest(ctx); err != nil { - f.logger.Error(fmt.Sprintf("Database test failed: %v", err)) + logger.Error(fmt.Sprintf("Database test failed: %v", err)) return false } - f.logger.Debug("Database check completed") + logger.Debug("Database check completed") return f.ready.Load().(bool) } @@ -143,16 +155,15 @@ func (f *Frontend) Healthz(writer http.ResponseWriter, request *http.Request) { func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() + logger := LoggerFromContext(ctx) versionedInterface, err := VersionFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: ArmResourceList", versionedInterface)) - var pageSizeHint int32 = 20 var continuationToken *string var pagedResponse arm.PagedResponse @@ -175,6 +186,8 @@ func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Req subscriptionID := request.PathValue(PathSegmentSubscriptionID) resourceGroupName := request.PathValue(PathSegmentResourceGroupName) + resourceName := request.PathValue(PathSegmentResourceName) + resourceTypeName := path.Base(request.URL.Path) // Even though the bulk of the list content comes from Cluster Service, // we start by querying Cosmos DB because its continuation token meets @@ -185,24 +198,45 @@ func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Req if resourceGroupName != "" { prefixString += "/resourceGroups/" + resourceGroupName } - prefix, err := arm.ParseResourceID(prefixString) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return + if resourceName != "" { + // This is a nested resource request. Build a resource ID for + // the parent cluster. We use this below to get the cluster's + // ResourceDocument from Cosmos DB. + prefixString += "/providers/" + api.ProviderNamespace + prefixString += "/" + api.ClusterResourceTypeName + "/" + resourceName } - - documentList, continuationToken, err := f.dbClient.ListResourceDocs(ctx, prefix, &api.ClusterResourceType, pageSizeHint, continuationToken) + prefix, err := azcorearm.ParseResourceID(prefixString) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } + dbIterator := f.dbClient.ListResourceDocs(prefix, pageSizeHint, continuationToken) + // Build a map of cluster documents by Cluster Service cluster ID. documentMap := make(map[string]*database.ResourceDocument) - for _, doc := range documentList { - documentMap[doc.InternalID.ID()] = doc + for item := range dbIterator.Items(ctx) { + var doc database.ResourceDocument + + err = json.Unmarshal(item, &doc) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } + + // FIXME This filtering could be made part of the query expression. It would + // require some reworking (or elimination) of the DBClient interface. + if strings.HasSuffix(strings.ToLower(doc.ResourceId.ResourceType.Type), resourceTypeName) { + documentMap[doc.InternalID.ID()] = &doc + } + } + + err = dbIterator.GetError() + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) } // Build a Cluster Service query that looks for @@ -212,53 +246,72 @@ func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Req queryIDs = append(queryIDs, "'"+key+"'") } query := fmt.Sprintf("id in (%s)", strings.Join(queryIDs, ", ")) - f.logger.Info(fmt.Sprintf("Searching Cluster Service for %q", query)) + logger.Info(fmt.Sprintf("Searching Cluster Service for %q", query)) + + switch resourceTypeName { + case strings.ToLower(api.ClusterResourceTypeName): + csIterator := f.clusterServiceClient.ListCSClusters(query) + + for csCluster := range csIterator.Items(ctx) { + if doc, ok := documentMap[csCluster.ID()]; ok { + value, err := marshalCSCluster(csCluster, doc, versionedInterface) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } + pagedResponse.AddValue(value) + } + } + err = csIterator.GetError() - listRequest := f.clusterServiceClient.GetConn().ClustersMgmt().V1().Clusters().List().Search(query) + case strings.ToLower(api.NodePoolResourceTypeName): + var resourceDoc *database.ResourceDocument - // XXX This SHOULD avoid dealing with pagination from Cluster Service. - // As far I can tell, uhc-cluster-service does not impose its own - // limit on the page size. Further testing is needed to verify. - listRequest.Size(len(documentMap)) + // Fetch the cluster document for the Cluster Service ID. + resourceDoc, err = f.dbClient.GetResourceDoc(ctx, prefix) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } - listResponse, err := listRequest.SendContext(ctx) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } + csIterator := f.clusterServiceClient.ListCSNodePools(resourceDoc.InternalID, query) - for _, csCluster := range listResponse.Items().Slice() { - if doc, ok := documentMap[csCluster.ID()]; ok { - value, err := marshalCSCluster(csCluster, doc, versionedInterface) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return + for csNodePool := range csIterator.Items(ctx) { + if doc, ok := documentMap[csNodePool.ID()]; ok { + value, err := marshalCSNodePool(csNodePool, doc, versionedInterface) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } + pagedResponse.AddValue(value) } - pagedResponse.AddValue(value) } + err = csIterator.GetError() + + default: + err = fmt.Errorf("unsupported resource type: %s", resourceTypeName) } - if continuationToken != nil { - err = pagedResponse.SetNextLink(request.Referer(), *continuationToken) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } + // Check for iteration error. + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return } - resp, err := json.Marshal(pagedResponse) + err = pagedResponse.SetNextLink(request.Referer(), dbIterator.GetContinuationToken()) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - _, err = writer.Write(resp) + _, err = arm.WriteJSONResponse(writer, http.StatusOK, pagedResponse) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } @@ -267,32 +320,31 @@ func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Req // * 404 If the resource does not exist func (f *Frontend) ArmResourceRead(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() + logger := LoggerFromContext(ctx) versionedInterface, err := VersionFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: ArmResourceRead", versionedInterface)) - responseBody, cloudError := f.MarshalResource(ctx, resourceID, versionedInterface) if cloudError != nil { arm.WriteCloudError(writer, cloudError) return } - _, err = writer.Write(responseBody) + _, err = arm.WriteJSONResponse(writer, http.StatusOK, responseBody) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } @@ -312,40 +364,32 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request // that represents an existing resource to be updated. ctx := request.Context() + logger := LoggerFromContext(ctx) versionedInterface, err := VersionFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } systemData, err := SystemDataFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } - - tenantID := request.Header.Get(arm.HeaderNameHomeTenantID) - if tenantID == "" { - f.logger.Error("Missing " + arm.HeaderNameHomeTenantID + " header") + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: ArmResourceCreateOrUpdate", versionedInterface)) - doc, err := f.dbClient.GetResourceDoc(ctx, resourceID) if err != nil && !errors.Is(err, database.ErrNotFound) { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } @@ -366,7 +410,7 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request // appropriate to fail. csCluster, err := f.clusterServiceClient.GetCSCluster(ctx, doc.InternalID) if err != nil { - f.logger.Error(fmt.Sprintf("failed to fetch CS cluster for %s: %v", resourceID, err)) + logger.Error(fmt.Sprintf("failed to fetch CS cluster for %s: %v", resourceID, err)) arm.WriteInternalServerError(writer) return } @@ -400,7 +444,7 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request successStatusCode = http.StatusCreated case http.MethodPatch: // PATCH requests never create a new resource. - f.logger.Error("Resource not found") + logger.Error("Resource not found") arm.WriteResourceNotFoundError(writer, resourceID) return } @@ -418,19 +462,19 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request body, err := BodyFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if err = json.Unmarshal(body, versionedRequestCluster); err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInvalidRequestContentError(writer, err) return } cloudError = versionedRequestCluster.ValidateStatic(versionedCurrentCluster, updating, request.Method) if cloudError != nil { - f.logger.Error(cloudError.Error()) + logger.Error(cloudError.Error()) arm.WriteCloudError(writer, cloudError) return } @@ -439,41 +483,50 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request versionedRequestCluster.Normalize(hcpCluster) hcpCluster.Name = request.PathValue(PathSegmentResourceName) - csCluster, err := f.BuildCSCluster(resourceID, tenantID, hcpCluster, updating) + csCluster, err := f.BuildCSCluster(resourceID, request.Header, hcpCluster, updating) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if updating { - f.logger.Info(fmt.Sprintf("updating resource %s", resourceID)) + logger.Info(fmt.Sprintf("updating resource %s", resourceID)) csCluster, err = f.clusterServiceClient.UpdateCSCluster(ctx, doc.InternalID, csCluster) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } } else { - f.logger.Info(fmt.Sprintf("creating resource %s", resourceID)) + logger.Info(fmt.Sprintf("creating resource %s", resourceID)) csCluster, err = f.clusterServiceClient.PostCSCluster(ctx, csCluster) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } doc.InternalID, err = ocm.NewInternalID(csCluster.HREF()) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } } - operationDoc, err := f.StartOperation(writer, request, doc, operationRequest) + operationDoc := database.NewOperationDocument(operationRequest, doc.ResourceId, doc.InternalID) + + err = f.dbClient.CreateOperationDoc(ctx, operationDoc) if err != nil { - f.logger.Error(fmt.Sprintf("failed to write operation document: %v", err)) + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } + + err = f.ExposeOperation(writer, request, operationDoc.ID) + if err != nil { + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } @@ -505,35 +558,40 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request updateResourceMetadata(doc) err = f.dbClient.CreateResourceDoc(ctx, doc) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("document created for %s", resourceID)) + logger.Info(fmt.Sprintf("document created for %s", resourceID)) } else { updated, err := f.dbClient.UpdateResourceDoc(ctx, resourceID, updateResourceMetadata) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if updated { - f.logger.Info(fmt.Sprintf("document updated for %s", resourceID)) + logger.Info(fmt.Sprintf("document updated for %s", resourceID)) + } + // Get the updated resource document for the response. + doc, err = f.dbClient.GetResourceDoc(ctx, resourceID) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return } } responseBody, err := marshalCSCluster(csCluster, doc, versionedInterface) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - writer.WriteHeader(successStatusCode) - - _, err = writer.Write(responseBody) + _, err = arm.WriteJSONResponse(writer, successStatusCode, responseBody) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } @@ -542,121 +600,81 @@ func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request // * 202 if an asynchronous delete is initiated // * 204 if a well-formed request attempts to delete a nonexistent resource func (f *Frontend) ArmResourceDelete(writer http.ResponseWriter, request *http.Request) { - ctx := request.Context() + const operationRequest = database.OperationRequestDelete - versionedInterface, err := VersionFromContext(ctx) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } + ctx := request.Context() + logger := LoggerFromContext(ctx) resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: ArmResourceDelete", versionedInterface)) - - resourceDoc, cloudError := f.DeleteResource(ctx, resourceID) - if cloudError != nil { + resourceDoc, err := f.dbClient.GetResourceDoc(ctx, resourceID) + if err != nil { // For resource not found errors on deletion, ARM requires // us to simply return 204 No Content and no response body. - if cloudError.StatusCode == http.StatusNotFound { + if errors.Is(err, database.ErrNotFound) { writer.WriteHeader(http.StatusNoContent) } else { - arm.WriteCloudError(writer, cloudError) + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) } return } - operationRequest := database.OperationRequestDelete - // CheckForProvisioningStateConflict does not log conflict errors // but does log unexpected errors like database failures. - cloudError = f.CheckForProvisioningStateConflict(ctx, operationRequest, resourceDoc) + cloudError := f.CheckForProvisioningStateConflict(ctx, operationRequest, resourceDoc) if cloudError != nil { arm.WriteCloudError(writer, cloudError) return } - err = f.clusterServiceClient.DeleteCSCluster(ctx, resourceDoc.InternalID) - if err != nil { - f.logger.Error(fmt.Sprintf("failed to delete cluster %s: %v", resourceID, err)) - arm.WriteInternalServerError(writer) - return - } - - // Deletion is underway; mark any active operation as canceled. - if resourceDoc.ActiveOperationID != "" { - updated, err := f.dbClient.UpdateOperationDoc(ctx, resourceDoc.ActiveOperationID, func(updateDoc *database.OperationDocument) bool { - return updateDoc.UpdateStatus(arm.ProvisioningStateCanceled, nil) - }) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } - if updated { - f.logger.Info(fmt.Sprintf("canceled operation '%s'", resourceDoc.ActiveOperationID)) + operationID, cloudError := f.DeleteResource(ctx, resourceDoc) + if cloudError != nil { + // For resource not found errors on deletion, ARM requires + // us to simply return 204 No Content and no response body. + if cloudError.StatusCode == http.StatusNotFound { + writer.WriteHeader(http.StatusNoContent) + } else { + arm.WriteCloudError(writer, cloudError) } - } - - operationDoc, err := f.StartOperation(writer, request, resourceDoc, operationRequest) - if err != nil { - f.logger.Error(fmt.Sprintf("failed to write operation document: %v", err)) - arm.WriteInternalServerError(writer) return } - updated, err := f.dbClient.UpdateResourceDoc(ctx, resourceID, func(updateDoc *database.ResourceDocument) bool { - updateDoc.ActiveOperationID = operationDoc.ID - updateDoc.ProvisioningState = operationDoc.Status - return true - }) + err = f.ExposeOperation(writer, request, operationID) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - if updated { - f.logger.Info(fmt.Sprintf("document updated for %s", resourceID)) - } writer.WriteHeader(http.StatusAccepted) } func (f *Frontend) ArmResourceAction(writer http.ResponseWriter, request *http.Request) { - ctx := request.Context() - - versionedInterface, err := VersionFromContext(ctx) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } - - f.logger.Info(fmt.Sprintf("%s: ArmResourceAction", versionedInterface)) - writer.WriteHeader(http.StatusOK) } func (f *Frontend) ArmSubscriptionGet(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() - subscriptionID := request.PathValue(PathSegmentSubscriptionID) + logger := LoggerFromContext(ctx) resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } + subscriptionID := request.PathValue(PathSegmentSubscriptionID) + doc, err := f.dbClient.GetSubscriptionDoc(ctx, subscriptionID) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) if errors.Is(err, database.ErrNotFound) { arm.WriteResourceNotFoundError(writer, resourceID) } else { @@ -665,25 +683,19 @@ func (f *Frontend) ArmSubscriptionGet(writer http.ResponseWriter, request *http. return } - resp, err := json.Marshal(&doc.Subscription) + _, err = arm.WriteJSONResponse(writer, http.StatusOK, &doc.Subscription) if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } - - _, err = writer.Write(resp) - if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() + logger := LoggerFromContext(ctx) body, err := BodyFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } @@ -691,14 +703,14 @@ func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http. var subscription arm.Subscription err = json.Unmarshal(body, &subscription) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInvalidRequestContentError(writer, err) return } cloudError := api.ValidateSubscription(&subscription) if cloudError != nil { - f.logger.Error(cloudError.Error()) + logger.Error(cloudError.Error()) arm.WriteCloudError(writer, cloudError) return } @@ -710,20 +722,20 @@ func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http. doc := database.NewSubscriptionDocument(subscriptionID, &subscription) err = f.dbClient.CreateSubscriptionDoc(ctx, doc) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("created document for subscription %s", subscriptionID)) + logger.Info(fmt.Sprintf("created document for subscription %s", subscriptionID)) } else if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } else { updated, err := f.dbClient.UpdateSubscriptionDoc(ctx, subscriptionID, func(doc *database.SubscriptionDocument) bool { messages := getSubscriptionDifferences(doc.Subscription, &subscription) for _, message := range messages { - f.logger.Info(message) + logger.Info(message) } doc.Subscription = &subscription @@ -731,12 +743,12 @@ func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http. return len(messages) > 0 }) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if updated { - f.logger.Info(fmt.Sprintf("updated document for subscription %s", subscriptionID)) + logger.Info(fmt.Sprintf("updated document for subscription %s", subscriptionID)) } } @@ -746,17 +758,18 @@ func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http. "state": string(subscription.State), }) - resp, err := json.Marshal(subscription) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return + // Clean up resources if subscription is deleted. + if subscription.State == arm.SubscriptionStateDeleted { + cloudError := f.DeleteAllResources(ctx, subscriptionID) + if cloudError != nil { + arm.WriteCloudError(writer, cloudError) + return + } } - writer.WriteHeader(http.StatusCreated) - _, err = writer.Write(resp) + _, err = arm.WriteJSONResponse(writer, http.StatusOK, subscription) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } @@ -766,19 +779,20 @@ func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *h var apiVersion string = request.URL.Query().Get("api-version") ctx := request.Context() + logger := LoggerFromContext(ctx) - f.logger.Info(fmt.Sprintf("%s: ArmDeploymentPreflight", apiVersion)) + logger.Info(fmt.Sprintf("%s: ArmDeploymentPreflight", apiVersion)) body, err := BodyFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } deploymentPreflight, cloudError := arm.UnmarshalDeploymentPreflight(body) if cloudError != nil { - f.logger.Error(cloudError.Error()) + logger.Error(cloudError.Error()) arm.WriteCloudError(writer, cloudError) return } @@ -792,7 +806,7 @@ func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *h if err != nil { cloudError = arm.NewInvalidRequestContentError(err) // Preflight is best-effort: a malformed resource is not a validation failure. - f.logger.Warn(cloudError.Message) + logger.Warn(cloudError.Message) } // This is just "preliminary" validation to ensure all the base resource @@ -800,7 +814,7 @@ func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *h resourceErrors := api.ValidateRequest(validate, request.Method, resource) if len(resourceErrors) > 0 { // Preflight is best-effort: a malformed resource is not a validation failure. - f.logger.Warn( + logger.Warn( fmt.Sprintf("Resource #%d failed preliminary validation (see details)", index+1), "details", resourceErrors) continue @@ -813,7 +827,7 @@ func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *h err = json.Unmarshal(raw, versionedCluster) if err != nil { // Preflight is best effort: failure to parse a resource is not a validation failure. - f.logger.Warn(fmt.Sprintf("Failed to unmarshal %s resource named '%s': %s", resource.Type, resource.Name, err)) + logger.Warn(fmt.Sprintf("Failed to unmarshal %s resource named '%s': %s", resource.Type, resource.Name, err)) continue } @@ -874,26 +888,18 @@ func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *h func (f *Frontend) OperationStatus(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() - - versionedInterface, err := VersionFromContext(ctx) - if err != nil { - f.logger.Error(err.Error()) - writer.WriteHeader(http.StatusInternalServerError) - return - } + logger := LoggerFromContext(ctx) resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: OperationStatus", versionedInterface)) - doc, err := f.dbClient.GetOperationDoc(ctx, resourceID.Name) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) if errors.Is(err, database.ErrNotFound) { writer.WriteHeader(http.StatusNotFound) } else { @@ -909,28 +915,21 @@ func (f *Frontend) OperationStatus(writer http.ResponseWriter, request *http.Req return } - responseBody, err := json.Marshal(doc.ToStatus()) - if err != nil { - f.logger.Error(err.Error()) - arm.WriteInternalServerError(writer) - return - } - - _, err = writer.Write(responseBody) + _, err = arm.WriteJSONResponse(writer, http.StatusOK, doc.ToStatus()) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } // marshalCSCluster renders a CS Cluster object in JSON format, applying // the necessary conversions for the API version of the request. -func marshalCSCluster(csCluster *cmv1.Cluster, doc *database.ResourceDocument, versionedInterface api.Version) ([]byte, error) { - hcpCluster := ConvertCStoHCPOpenShiftCluster(doc.Key, csCluster) +func marshalCSCluster(csCluster *arohcpv1alpha1.Cluster, doc *database.ResourceDocument, versionedInterface api.Version) ([]byte, error) { + hcpCluster := ConvertCStoHCPOpenShiftCluster(doc.ResourceId, csCluster) hcpCluster.TrackedResource.Resource.SystemData = doc.SystemData hcpCluster.TrackedResource.Tags = maps.Clone(doc.Tags) hcpCluster.Properties.ProvisioningState = doc.ProvisioningState - return json.Marshal(versionedInterface.NewHCPOpenShiftCluster(hcpCluster)) + return arm.Marshal(versionedInterface.NewHCPOpenShiftCluster(hcpCluster)) } func getSubscriptionDifferences(oldSub, newSub *arm.Subscription) []string { @@ -971,26 +970,25 @@ func getSubscriptionDifferences(oldSub, newSub *arm.Subscription) []string { func (f *Frontend) OperationResult(writer http.ResponseWriter, request *http.Request) { ctx := request.Context() + logger := LoggerFromContext(ctx) versionedInterface, err := VersionFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: OperationResult", versionedInterface)) - doc, err := f.dbClient.GetOperationDoc(ctx, resourceID.Name) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) if errors.Is(err, database.ErrNotFound) { writer.WriteHeader(http.StatusNotFound) } else { @@ -1028,7 +1026,7 @@ func (f *Frontend) OperationResult(writer http.ResponseWriter, request *http.Req writer.WriteHeader(http.StatusNoContent) return default: - f.logger.Error(fmt.Sprintf("Unhandled request type: %s", doc.Request)) + logger.Error(fmt.Sprintf("Unhandled request type: %s", doc.Request)) writer.WriteHeader(http.StatusInternalServerError) return } @@ -1039,11 +1037,9 @@ func (f *Frontend) OperationResult(writer http.ResponseWriter, request *http.Req return } - writer.WriteHeader(successStatusCode) - - _, err = writer.Write(responseBody) + _, err = arm.WriteJSONResponse(writer, successStatusCode, responseBody) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } diff --git a/frontend/pkg/frontend/frontend_test.go b/frontend/pkg/frontend/frontend_test.go index ad991a25b..921ad0df2 100644 --- a/frontend/pkg/frontend/frontend_test.go +++ b/frontend/pkg/frontend/frontend_test.go @@ -9,14 +9,39 @@ import ( "net" "net/http" "net/http/httptest" + "strings" "testing" "time" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + "go.uber.org/mock/gomock" + "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/mocks" ) +var testLogger = slog.New(slog.NewTextHandler(io.Discard, nil)) + +const subscriptionID = "00000000-0000-0000-0000-000000000000" + +func getMockDBDoc[T any](t *T) (*T, error) { + if t != nil { + return t, nil + } else { + return nil, database.ErrNotFound + } +} + +func equalResourceID(expectResourceID *azcorearm.ResourceID) gomock.Matcher { + return gomock.Cond(func(actualResourceID *azcorearm.ResourceID) bool { + return strings.EqualFold(actualResourceID.String(), expectResourceID.String()) + }) +} + func TestReadiness(t *testing.T) { tests := []struct { name string @@ -37,17 +62,23 @@ func TestReadiness(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) + reg := prometheus.NewRegistry() + f := &Frontend{ - dbClient: database.NewCache(), - logger: slog.New(slog.NewTextHandler(io.Discard, nil)), - metrics: NewPrometheusEmitter(), + dbClient: mockDBClient, + metrics: NewPrometheusEmitter(reg), } f.ready.Store(test.ready) ts := httptest.NewServer(f.routes()) ts.Config.BaseContext = func(net.Listener) context.Context { - return ContextWithLogger(context.Background(), f.logger) + return ContextWithLogger(context.Background(), testLogger) } + // Call expected but is irrelevant to the test. + mockDBClient.EXPECT().DBConnectionTest(gomock.Any()) + rs, err := ts.Client().Get(ts.URL + "/healthz") if err != nil { t.Fatal(err) @@ -56,6 +87,8 @@ func TestReadiness(t *testing.T) { if rs.StatusCode != test.expectedStatusCode { t.Errorf("expected status code %d, got %d", test.expectedStatusCode, rs.StatusCode) } + + lintMetrics(t, reg) }) } } @@ -68,16 +101,12 @@ func TestSubscriptionsGET(t *testing.T) { }{ { name: "GET Subscription - Doc Exists", - subDoc: &database.SubscriptionDocument{ - BaseDocument: database.BaseDocument{ - ID: "00000000-0000-0000-0000-000000000000", - }, - Subscription: &arm.Subscription{ + subDoc: database.NewSubscriptionDocument(subscriptionID, + &arm.Subscription{ State: arm.SubscriptionStateRegistered, RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, - }, - }, + }), expectedStatusCode: http.StatusOK, }, { @@ -89,28 +118,30 @@ func TestSubscriptionsGET(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) + reg := prometheus.NewRegistry() + f := &Frontend{ - dbClient: database.NewCache(), - logger: slog.New(slog.NewTextHandler(io.Discard, nil)), - metrics: NewPrometheusEmitter(), + dbClient: mockDBClient, + metrics: NewPrometheusEmitter(reg), } - if test.subDoc != nil { - err := f.dbClient.CreateSubscriptionDoc(context.TODO(), test.subDoc) - if err != nil { - t.Fatal(err) - } - } + // ArmSubscriptionGet and MetricsMiddleware + mockDBClient.EXPECT(). + GetSubscriptionDoc(gomock.Any(), gomock.Any()). + Return(getMockDBDoc(test.subDoc)). + Times(2) ts := httptest.NewServer(f.routes()) ts.Config.BaseContext = func(net.Listener) context.Context { ctx := context.Background() - ctx = ContextWithLogger(ctx, f.logger) + ctx = ContextWithLogger(ctx, testLogger) ctx = ContextWithDBClient(ctx, f.dbClient) return ctx } - rs, err := ts.Client().Get(ts.URL + "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0") + rs, err := ts.Client().Get(ts.URL + "/subscriptions/" + subscriptionID + "?api-version=2.0") if err != nil { t.Fatal(err) } @@ -118,6 +149,8 @@ func TestSubscriptionsGET(t *testing.T) { if rs.StatusCode != test.expectedStatusCode { t.Errorf("expected status code %d, got %d", test.expectedStatusCode, rs.StatusCode) } + + lintMetrics(t, reg) }) } } @@ -132,34 +165,30 @@ func TestSubscriptionsPUT(t *testing.T) { }{ { name: "PUT Subscription - Doc does not exist", - urlPath: "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0", + urlPath: "/subscriptions/" + subscriptionID + "?api-version=2.0", subscription: &arm.Subscription{ State: arm.SubscriptionStateRegistered, RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, }, subDoc: nil, - expectedStatusCode: http.StatusCreated, + expectedStatusCode: http.StatusOK, }, { name: "PUT Subscription - Doc Exists", - urlPath: "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0", + urlPath: "/subscriptions/" + subscriptionID + "?api-version=2.0", subscription: &arm.Subscription{ State: arm.SubscriptionStateRegistered, RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, }, - subDoc: &database.SubscriptionDocument{ - BaseDocument: database.BaseDocument{ - ID: "00000000-0000-0000-0000-000000000000", - }, - Subscription: &arm.Subscription{ + subDoc: database.NewSubscriptionDocument(subscriptionID, + &arm.Subscription{ State: arm.SubscriptionStateRegistered, RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, - }, - }, - expectedStatusCode: http.StatusCreated, + }), + expectedStatusCode: http.StatusOK, }, { name: "PUT Subscription - Invalid Subscription", @@ -174,7 +203,7 @@ func TestSubscriptionsPUT(t *testing.T) { }, { name: "PUT Subscription - Missing State", - urlPath: "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0", + urlPath: "/subscriptions/" + subscriptionID + "?api-version=2.0", subscription: &arm.Subscription{ RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, @@ -184,7 +213,7 @@ func TestSubscriptionsPUT(t *testing.T) { }, { name: "PUT Subscription - Invalid State", - urlPath: "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0", + urlPath: "/subscriptions/" + subscriptionID + "?api-version=2.0", subscription: &arm.Subscription{ State: "Bogus", RegistrationDate: api.Ptr(time.Now().String()), @@ -195,7 +224,7 @@ func TestSubscriptionsPUT(t *testing.T) { }, { name: "PUT Subscription - Missing RegistrationDate", - urlPath: "/subscriptions/00000000-0000-0000-0000-000000000000?api-version=2.0", + urlPath: "/subscriptions/" + subscriptionID + "?api-version=2.0", subscription: &arm.Subscription{ State: arm.SubscriptionStateRegistered, Properties: nil, @@ -207,10 +236,13 @@ func TestSubscriptionsPUT(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) + reg := prometheus.NewRegistry() + f := &Frontend{ - dbClient: database.NewCache(), - logger: slog.New(slog.NewTextHandler(io.Discard, nil)), - metrics: NewPrometheusEmitter(), + dbClient: mockDBClient, + metrics: NewPrometheusEmitter(reg), } body, err := json.Marshal(&test.subscription) @@ -218,17 +250,36 @@ func TestSubscriptionsPUT(t *testing.T) { t.Fatal(err) } - if test.subDoc != nil { - err := f.dbClient.CreateSubscriptionDoc(context.TODO(), test.subDoc) - if err != nil { - t.Fatal(err) + // MiddlewareLockSubscription + // (except when MiddlewareValidateStatic fails) + mockDBClient.EXPECT(). + GetLockClient(). + MaxTimes(1) + if test.expectedStatusCode != http.StatusBadRequest { + // ArmSubscriptionPut + mockDBClient.EXPECT(). + GetSubscriptionDoc(gomock.Any(), gomock.Any()). + Return(getMockDBDoc(test.subDoc)) + // ArmSubscriptionPut + if test.subDoc == nil { + mockDBClient.EXPECT(). + CreateSubscriptionDoc(gomock.Any(), gomock.Any()) + } else { + mockDBClient.EXPECT(). + UpdateSubscriptionDoc(gomock.Any(), gomock.Any(), gomock.Any()) } } + // MiddlewareMetrics + // (except when MiddlewareValidateStatic fails) + mockDBClient.EXPECT(). + GetSubscriptionDoc(gomock.Any(), gomock.Any()). + Return(database.NewSubscriptionDocument(subscriptionID, test.subscription), nil). + MaxTimes(1) ts := httptest.NewServer(f.routes()) ts.Config.BaseContext = func(net.Listener) context.Context { ctx := context.Background() - ctx = ContextWithLogger(ctx, f.logger) + ctx = ContextWithLogger(ctx, testLogger) ctx = ContextWithDBClient(ctx, f.dbClient) return ctx } @@ -247,6 +298,21 @@ func TestSubscriptionsPUT(t *testing.T) { if rs.StatusCode != test.expectedStatusCode { t.Errorf("expected status code %d, got %d", test.expectedStatusCode, rs.StatusCode) } + + lintMetrics(t, reg) }) } } + +func lintMetrics(t *testing.T, r prometheus.Gatherer) { + t.Helper() + + problems, err := testutil.GatherAndLint(r) + if err != nil { + t.Fatal(err) + } + + for _, p := range problems { + t.Errorf("metric %q: %s", p.Metric, p.Text) + } +} diff --git a/frontend/pkg/frontend/helpers.go b/frontend/pkg/frontend/helpers.go index 11dd7fadf..87b564b22 100644 --- a/frontend/pkg/frontend/helpers.go +++ b/frontend/pkg/frontend/helpers.go @@ -5,11 +5,13 @@ package frontend import ( "context" + "encoding/json" "errors" "fmt" "net/http" "strings" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" ocmerrors "github.com/openshift-online/ocm-sdk-go/errors" @@ -22,6 +24,8 @@ import ( // provisioning state of the resource is non-terminal, or any of its parent resources // within the same provider namespace are in a "Deleting" state. func (f *Frontend) CheckForProvisioningStateConflict(ctx context.Context, operationRequest database.OperationRequest, doc *database.ResourceDocument) *arm.CloudError { + logger := LoggerFromContext(ctx) + switch operationRequest { case database.OperationRequestCreate: // Resource must already exist for there to be a conflict. @@ -30,7 +34,7 @@ func (f *Frontend) CheckForProvisioningStateConflict(ctx context.Context, operat return arm.NewCloudError( http.StatusConflict, arm.CloudErrorCodeConflict, - doc.Key.String(), + doc.ResourceId.String(), "Resource is already deleting") } case database.OperationRequestUpdate: @@ -38,19 +42,19 @@ func (f *Frontend) CheckForProvisioningStateConflict(ctx context.Context, operat return arm.NewCloudError( http.StatusConflict, arm.CloudErrorCodeConflict, - doc.Key.String(), + doc.ResourceId.String(), "Cannot update resource while resource is %s", strings.ToLower(string(doc.ProvisioningState))) } } - parent := doc.Key.GetParent() + parent := doc.ResourceId.Parent // ResourceType casing is preserved for parents in the same namespace. - for parent.ResourceType.Namespace == doc.Key.ResourceType.Namespace { + for parent.ResourceType.Namespace == doc.ResourceId.ResourceType.Namespace { parentDoc, err := f.dbClient.GetResourceDoc(ctx, parent) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) return arm.NewInternalServerError() } @@ -58,58 +62,182 @@ func (f *Frontend) CheckForProvisioningStateConflict(ctx context.Context, operat return arm.NewCloudError( http.StatusConflict, arm.CloudErrorCodeConflict, - doc.Key.String(), + doc.ResourceId.String(), "Cannot %s resource while parent resource is deleting", strings.ToLower(string(operationRequest))) } - parent = parent.GetParent() + parent = parent.Parent } return nil } -func (f *Frontend) DeleteResource(ctx context.Context, resourceID *arm.ResourceID) (*database.ResourceDocument, *arm.CloudError) { - doc, err := f.dbClient.GetResourceDoc(ctx, resourceID) +func (f *Frontend) DeleteAllResources(ctx context.Context, subscriptionID string) *arm.CloudError { + logger := LoggerFromContext(ctx) + + prefix, err := azcorearm.ParseResourceID("/subscriptions/" + subscriptionID) if err != nil { - if errors.Is(err, database.ErrNotFound) { - return nil, arm.NewResourceNotFoundError(resourceID) - } else { - f.logger.Error(err.Error()) - return nil, arm.NewInternalServerError() + logger.Error(err.Error()) + return arm.NewInternalServerError() + } + + dbIterator := f.dbClient.ListResourceDocs(prefix, -1, nil) + + // Start a deletion operation for all clusters under the subscription. + // Cluster Service will delete all node pools belonging to these clusters + // so we don't need to explicitly delete node pools here. + for item := range dbIterator.Items(ctx) { + var resourceDoc *database.ResourceDocument + + err = json.Unmarshal(item, &resourceDoc) + if err != nil { + logger.Error(err.Error()) + return arm.NewInternalServerError() + } + + if !strings.EqualFold(resourceDoc.ResourceId.ResourceType.String(), api.ClusterResourceType.String()) { + continue + } + + // Allow this method to be idempotent. + if resourceDoc.ProvisioningState != arm.ProvisioningStateDeleting { + _, cloudError := f.DeleteResource(ctx, resourceDoc) + if cloudError != nil { + return cloudError + } } } - switch doc.InternalID.Kind() { + return nil +} + +func (f *Frontend) DeleteResource(ctx context.Context, resourceDoc *database.ResourceDocument) (string, *arm.CloudError) { + const operationRequest = database.OperationRequestDelete + var err error + + logger := LoggerFromContext(ctx) + + switch resourceDoc.InternalID.Kind() { case cmv1.ClusterKind: - err = f.clusterServiceClient.DeleteCSCluster(ctx, doc.InternalID) + err = f.clusterServiceClient.DeleteCSCluster(ctx, resourceDoc.InternalID) case cmv1.NodePoolKind: - err = f.clusterServiceClient.DeleteCSNodePool(ctx, doc.InternalID) + err = f.clusterServiceClient.DeleteCSNodePool(ctx, resourceDoc.InternalID) default: - f.logger.Error(fmt.Sprintf("unsupported Cluster Service path: %s", doc.InternalID)) - return nil, arm.NewInternalServerError() + logger.Error(fmt.Sprintf("unsupported Cluster Service path: %s", resourceDoc.InternalID)) + return "", arm.NewInternalServerError() } if err != nil { var ocmError *ocmerrors.Error if errors.As(err, &ocmError) && ocmError.Status() == http.StatusNotFound { - return nil, arm.NewResourceNotFoundError(resourceID) + return "", arm.NewResourceNotFoundError(resourceDoc.ResourceId) } - f.logger.Error(err.Error()) - return nil, arm.NewInternalServerError() + logger.Error(err.Error()) + return "", arm.NewInternalServerError() } - return doc, nil + // Cluster Service will take care of canceling any ongoing operations + // on the resource or child resources, but we need to do some database + // bookkeeping to reflect that. + + // FIXME This would be a good place to use Cosmos DB's transactional batch + // operations to ensure all these write operations succeed together + // or roll back. We would need two parallel transactions: one for + // the Operations container and another for the Resources container. + // But we're stymied currently by the DBClient interface, and I have + // no desire to implement this in the in-memory cache. DBClient has + // served us well up to this point, but I think it's time to bid it + // farewell and switch to gomock in unit tests. + + err = f.CancelActiveOperation(ctx, resourceDoc) + if err != nil { + logger.Error(err.Error()) + return "", arm.NewInternalServerError() + } + + operationDoc := database.NewOperationDocument(operationRequest, resourceDoc.ResourceId, resourceDoc.InternalID) + + err = f.dbClient.CreateOperationDoc(ctx, operationDoc) + if err != nil { + logger.Error(err.Error()) + return "", arm.NewInternalServerError() + } + + _, err = f.dbClient.UpdateResourceDoc(ctx, resourceDoc.ResourceId, func(updateDoc *database.ResourceDocument) bool { + updateDoc.ActiveOperationID = operationDoc.ID + updateDoc.ProvisioningState = operationDoc.Status + return true + }) + if err != nil { + logger.Error(err.Error()) + return "", arm.NewInternalServerError() + } + + iterator := f.dbClient.ListResourceDocs(resourceDoc.ResourceId, -1, nil) + + for item := range iterator.Items(ctx) { + // Anonymous function avoids repetitive error handling. + err = func() error { + var child database.ResourceDocument + + err = json.Unmarshal(item, &child) + if err != nil { + return err + } + + err = f.CancelActiveOperation(ctx, &child) + if err != nil { + return err + } + + // This operation is not accessible through any REST endpoint. + // Its purpose is to cause the backend to delete the resource + // document once resource deletion completes. + + childOperationDoc := database.NewOperationDocument(operationRequest, child.ResourceId, child.InternalID) + + err = f.dbClient.CreateOperationDoc(ctx, childOperationDoc) + if err != nil { + return err + } + + _, err = f.dbClient.UpdateResourceDoc(ctx, child.ResourceId, func(updateDoc *database.ResourceDocument) bool { + updateDoc.ActiveOperationID = childOperationDoc.ID + updateDoc.ProvisioningState = childOperationDoc.Status + return true + }) + if err != nil { + return err + } + + return nil + }() + if err != nil { + logger.Error(err.Error()) + return "", arm.NewInternalServerError() + } + } + + err = iterator.GetError() + if err != nil { + logger.Error(err.Error()) + return "", arm.NewInternalServerError() + } + + return operationDoc.ID, nil } -func (f *Frontend) MarshalResource(ctx context.Context, resourceID *arm.ResourceID, versionedInterface api.Version) ([]byte, *arm.CloudError) { +func (f *Frontend) MarshalResource(ctx context.Context, resourceID *azcorearm.ResourceID, versionedInterface api.Version) ([]byte, *arm.CloudError) { var responseBody []byte + logger := LoggerFromContext(ctx) + doc, err := f.dbClient.GetResourceDoc(ctx, resourceID) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) if errors.Is(err, database.ErrNotFound) { return nil, arm.NewResourceNotFoundError(resourceID) } else { @@ -121,7 +249,7 @@ func (f *Frontend) MarshalResource(ctx context.Context, resourceID *arm.Resource case cmv1.ClusterKind: csCluster, err := f.clusterServiceClient.GetCSCluster(ctx, doc.InternalID) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) var ocmError *ocmerrors.Error if errors.As(err, &ocmError) && ocmError.Status() == http.StatusNotFound { return nil, arm.NewResourceNotFoundError(resourceID) @@ -130,14 +258,14 @@ func (f *Frontend) MarshalResource(ctx context.Context, resourceID *arm.Resource } responseBody, err = marshalCSCluster(csCluster, doc, versionedInterface) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) return nil, arm.NewInternalServerError() } case cmv1.NodePoolKind: csNodePool, err := f.clusterServiceClient.GetCSNodePool(ctx, doc.InternalID) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) var ocmError *ocmerrors.Error if errors.As(err, &ocmError) && ocmError.Status() == http.StatusNotFound { return nil, arm.NewResourceNotFoundError(resourceID) @@ -146,12 +274,12 @@ func (f *Frontend) MarshalResource(ctx context.Context, resourceID *arm.Resource } responseBody, err = marshalCSNodePool(csNodePool, doc, versionedInterface) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) return nil, arm.NewInternalServerError() } default: - f.logger.Error(fmt.Sprintf("unsupported Cluster Service path: %s", doc.InternalID)) + logger.Error(fmt.Sprintf("unsupported Cluster Service path: %s", doc.InternalID)) return nil, arm.NewInternalServerError() } diff --git a/frontend/pkg/frontend/helpers_test.go b/frontend/pkg/frontend/helpers_test.go index 1cda3e16d..5b95269eb 100644 --- a/frontend/pkg/frontend/helpers_test.go +++ b/frontend/pkg/frontend/helpers_test.go @@ -6,12 +6,15 @@ package frontend import ( "context" "fmt" - "log/slog" "net/http" "testing" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "go.uber.org/mock/gomock" + "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/mocks" ) func TestCheckForProvisioningStateConflict(t *testing.T) { @@ -141,7 +144,7 @@ func TestCheckForProvisioningStateConflict(t *testing.T) { for _, tt := range tests { var name string - resourceID, err := arm.ParseResourceID(tt.resourceID) + resourceID, err := azcorearm.ParseResourceID(tt.resourceID) if err != nil { t.Fatal(err) } @@ -149,23 +152,26 @@ func TestCheckForProvisioningStateConflict(t *testing.T) { for directState, directConflict := range tt.directConflicts { name = fmt.Sprintf("%s (directState=%s)", tt.name, directState) t.Run(name, func(t *testing.T) { - ctx := context.Background() + ctx := ContextWithLogger(context.Background(), testLogger) + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) frontend := &Frontend{ - logger: slog.Default(), - dbClient: database.NewCache(), + dbClient: mockDBClient, } doc := database.NewResourceDocument(resourceID) doc.ProvisioningState = directState - parentResourceID := resourceID.GetParent() - if parentResourceID.ResourceType.Namespace == resourceID.ResourceType.Namespace { - parentDoc := database.NewResourceDocument(parentResourceID) - // Hold the provisioning state to something benign. - parentDoc.ProvisioningState = arm.ProvisioningStateSucceeded - _ = frontend.dbClient.CreateResourceDoc(ctx, parentDoc) - } + parentResourceID := resourceID.Parent + parentDoc := database.NewResourceDocument(parentResourceID) + // Hold the provisioning state to something benign. + parentDoc.ProvisioningState = arm.ProvisioningStateSucceeded + + mockDBClient.EXPECT(). + GetResourceDoc(gomock.Any(), equalResourceID(parentResourceID)). // defined in frontend_test.go + Return(parentDoc, nil). + MaxTimes(1) cloudError := frontend.CheckForProvisioningStateConflict(ctx, tt.operationRequest, doc) @@ -184,22 +190,26 @@ func TestCheckForProvisioningStateConflict(t *testing.T) { for parentState, parentConflict := range tt.parentConflicts { name = fmt.Sprintf("%s (parentState=%s)", tt.name, parentState) t.Run(name, func(t *testing.T) { - ctx := context.Background() + ctx := ContextWithLogger(context.Background(), testLogger) + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) frontend := &Frontend{ - logger: slog.Default(), - dbClient: database.NewCache(), + dbClient: mockDBClient, } doc := database.NewResourceDocument(resourceID) // Hold the provisioning state to something benign. doc.ProvisioningState = arm.ProvisioningStateSucceeded - parentResourceID := resourceID.GetParent() + parentResourceID := resourceID.Parent if parentResourceID.ResourceType.Namespace == resourceID.ResourceType.Namespace { parentDoc := database.NewResourceDocument(parentResourceID) parentDoc.ProvisioningState = parentState - _ = frontend.dbClient.CreateResourceDoc(ctx, parentDoc) + + mockDBClient.EXPECT(). + GetResourceDoc(gomock.Any(), equalResourceID(parentResourceID)). // defined in frontend_test.go + Return(parentDoc, nil) } else { t.Fatalf("Parent resource type namespace (%s) differs from child namespace (%s)", parentResourceID.ResourceType.Namespace, diff --git a/frontend/pkg/frontend/metrics.go b/frontend/pkg/frontend/metrics.go index 987d7c5db..4b54587f0 100644 --- a/frontend/pkg/frontend/metrics.go +++ b/frontend/pkg/frontend/metrics.go @@ -5,37 +5,41 @@ package frontend import ( "net/http" + "regexp" "strconv" + "sync" "time" "github.com/prometheus/client_golang/prometheus" "golang.org/x/exp/maps" - "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/database" ) // Emitter emits different types of metrics type Emitter interface { - EmitCounter(metricName string, value float64, labels map[string]string) + AddCounter(metricName string, value float64, labels map[string]string) EmitGauge(metricName string, value float64, labels map[string]string) } type PrometheusEmitter struct { + mutex sync.Mutex gauges map[string]*prometheus.GaugeVec counters map[string]*prometheus.CounterVec registry prometheus.Registerer } -func NewPrometheusEmitter() *PrometheusEmitter { +func NewPrometheusEmitter(r prometheus.Registerer) *PrometheusEmitter { return &PrometheusEmitter{ gauges: make(map[string]*prometheus.GaugeVec), counters: make(map[string]*prometheus.CounterVec), - registry: prometheus.NewRegistry(), + registry: r, } } func (pe *PrometheusEmitter) EmitGauge(name string, value float64, labels map[string]string) { + pe.mutex.Lock() + defer pe.mutex.Unlock() vec, exists := pe.gauges[name] if !exists { labelKeys := maps.Keys(labels) @@ -46,17 +50,22 @@ func (pe *PrometheusEmitter) EmitGauge(name string, value float64, labels map[st vec.With(labels).Set(value) } -func (pe *PrometheusEmitter) EmitCounter(name string, value float64, labels map[string]string) { +func (pe *PrometheusEmitter) AddCounter(name string, value float64, labels map[string]string) { + pe.mutex.Lock() + defer pe.mutex.Unlock() vec, exists := pe.counters[name] if !exists { labelKeys := maps.Keys(labels) vec = prometheus.NewCounterVec(prometheus.CounterOpts{Name: name}, labelKeys) - prometheus.MustRegister(vec) + pe.registry.MustRegister(vec) pe.counters[name] = vec } vec.With(labels).Add(value) } +// patternRe is used to strip the METHOD string from the [ServerMux] pattern string. +var patternRe = regexp.MustCompile(`^[^\s]*\s+`) + type MetricsMiddleware struct { Emitter dbClient database.DBClient @@ -76,10 +85,8 @@ func (lrw *logResponseWriter) WriteHeader(code int) { // Metrics middleware to capture response time and status code func (mm MetricsMiddleware) Metrics() MiddlewareFunc { return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - logger, err := LoggerFromContext(r.Context()) - if err != nil { - logger = config.DefaultLogger() - } + ctx := r.Context() + logger := LoggerFromContext(ctx) startTime := time.Now() @@ -87,9 +94,11 @@ func (mm MetricsMiddleware) Metrics() MiddlewareFunc { next(lrw, r) // Process the request + duration := time.Since(startTime).Seconds() + // Get the route pattern that matched - routePattern := r.URL.Path - duration := time.Since(startTime).Milliseconds() + routePattern := r.Pattern + routePattern = patternRe.ReplaceAllString(routePattern, "") subscriptionState := "Unknown" subscriptionId := r.PathValue(PathSegmentSubscriptionID) @@ -97,13 +106,13 @@ func (mm MetricsMiddleware) Metrics() MiddlewareFunc { sub, err := mm.dbClient.GetSubscriptionDoc(r.Context(), subscriptionId) if err != nil { // If we can't determine the subscription state, we can still expose a metric for subscriptionState "Unknown" - logger.Info("unable to retrieve subscription document for the `frontend_count` metric", "subscriptionId", subscriptionId, "error", err) + logger.Info("unable to retrieve subscription document for the `frontend_requests_total` metric", "subscriptionId", subscriptionId, "error", err) } else { subscriptionState = string(sub.Subscription.State) } } - mm.Emitter.EmitCounter("frontend_count", 1.0, map[string]string{ + mm.Emitter.AddCounter("frontend_requests_total", 1.0, map[string]string{ "verb": r.Method, "api_version": r.URL.Query().Get(APIVersionKey), "code": strconv.Itoa(lrw.statusCode), diff --git a/frontend/pkg/frontend/middleware_locksubscription.go b/frontend/pkg/frontend/middleware_locksubscription.go index 08a893300..53152634c 100644 --- a/frontend/pkg/frontend/middleware_locksubscription.go +++ b/frontend/pkg/frontend/middleware_locksubscription.go @@ -9,7 +9,6 @@ import ( "fmt" "net/http" - "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" ) @@ -18,13 +17,7 @@ func MiddlewareLockSubscription(w http.ResponseWriter, r *http.Request, next htt var lockClient *database.LockClient ctx := r.Context() - - logger, err := LoggerFromContext(ctx) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } + logger := LoggerFromContext(ctx) dbClient, err := DBClientFromContext(ctx) if err != nil { diff --git a/frontend/pkg/frontend/middleware_logging.go b/frontend/pkg/frontend/middleware_logging.go index df840a913..a233db1e2 100644 --- a/frontend/pkg/frontend/middleware_logging.go +++ b/frontend/pkg/frontend/middleware_logging.go @@ -11,7 +11,9 @@ import ( "strings" "time" - "github.com/Azure/ARO-HCP/frontend/pkg/config" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" ) @@ -34,8 +36,6 @@ type LoggingResponseWriter struct { } func (w *LoggingResponseWriter) Write(b []byte) (int, error) { - // All response body content is application/json. - w.Header().Set("Content-Type", "application/json") n, err := w.ResponseWriter.Write(b) w.bytesWritten += n return n, err @@ -47,23 +47,20 @@ func (w *LoggingResponseWriter) WriteHeader(statusCode int) { } func MiddlewareLogging(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + ctx := r.Context() + logger := LoggerFromContext(ctx) + // Capture request and response data for logging r.Body = &LoggingReadCloser{ReadCloser: r.Body} w = &LoggingResponseWriter{ResponseWriter: w, statusCode: http.StatusOK} startTime := time.Now() - logger, err := LoggerFromContext(r.Context()) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } - logger = logger.With( "request_method", r.Method, "request_path", r.URL.Path, "request_proto", r.Proto, + "request_query", r.URL.RawQuery, "request_remote_addr", r.RemoteAddr, "request_user_agent", r.UserAgent()) @@ -80,28 +77,26 @@ func MiddlewareLogging(w http.ResponseWriter, r *http.Request, next http.Handler func MiddlewareLoggingPostMux(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { ctx := r.Context() + logger := LoggerFromContext(ctx) correlationData := arm.NewCorrelationData(r) + + // NOTE: Here the middleware span is extended by further attributes. + // If the tracingMiddleware is not registered, this lines will have no effect. + span := trace.SpanFromContext(ctx) + span.SetAttributes(attribute.String("correlation.id", correlationData.CorrelationRequestID)) + span.SetAttributes(attribute.String("client.request.id", correlationData.ClientRequestID)) + ctx = ContextWithCorrelationData(ctx, correlationData) setHeaders(w, r, correlationData) attrs := getLogAttrs(correlationData, r) + logger = slog.New(logger.Handler().WithAttrs(attrs)) + ctx = ContextWithLogger(ctx, logger) + r = r.WithContext(ctx) - logger, err := LoggerFromContext(ctx) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } - - handler := logger.Handler() - loggerWithAttrs := slog.New(handler.WithAttrs(attrs)) - ctx = ContextWithLogger(ctx, loggerWithAttrs) - - reqWithContext := r.WithContext(ctx) - - next(w, reqWithContext) + next(w, r) } // setHeaders writes the appropriate headers in the response writer diff --git a/frontend/pkg/frontend/middleware_panic.go b/frontend/pkg/frontend/middleware_panic.go index e31908384..f594bbde9 100644 --- a/frontend/pkg/frontend/middleware_panic.go +++ b/frontend/pkg/frontend/middleware_panic.go @@ -8,20 +8,14 @@ import ( "net/http" "runtime/debug" - "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/api/arm" ) func MiddlewarePanic(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { defer func() { if e := recover(); e != nil { - logger, err := LoggerFromContext(r.Context()) - if err != nil { - logger = config.DefaultLogger() - } - + logger := LoggerFromContext(r.Context()) logger.Error(fmt.Sprintf("panic: %#v\n%s\n", e, string(debug.Stack()))) - arm.WriteInternalServerError(w) } }() diff --git a/frontend/pkg/frontend/middleware_resourceid.go b/frontend/pkg/frontend/middleware_resourceid.go index 8eb0fbe1a..93c9d0f0a 100644 --- a/frontend/pkg/frontend/middleware_resourceid.go +++ b/frontend/pkg/frontend/middleware_resourceid.go @@ -7,31 +7,26 @@ import ( "fmt" "net/http" - "github.com/Azure/ARO-HCP/frontend/pkg/config" - "github.com/Azure/ARO-HCP/internal/api/arm" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" ) // This middleware only applies to endpoints whose path form a valid Azure // resource ID. It should follow the MiddlewareLowercase function. func MiddlewareResourceID(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - logger, err := LoggerFromContext(r.Context()) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } + ctx := r.Context() + logger := LoggerFromContext(ctx) - originalPath, _ := OriginalPathFromContext(r.Context()) + originalPath, _ := OriginalPathFromContext(ctx) if originalPath == "" { // MiddlewareLowercase has not run; fall back to the request path. logger.Warn("Middleware dependency error: MiddlewareResourceID ran before MiddlewareLowercase") originalPath = r.URL.Path } - resourceID, err := arm.ParseResourceID(originalPath) + resourceID, err := azcorearm.ParseResourceID(originalPath) if err == nil { - ctx := ContextWithResourceID(r.Context(), resourceID) + ctx = ContextWithResourceID(ctx, resourceID) r = r.WithContext(ctx) } else { logger.Warn(fmt.Sprintf("Failed to parse '%s' as resource ID: %v", originalPath, err)) diff --git a/frontend/pkg/frontend/middleware_resourceid_test.go b/frontend/pkg/frontend/middleware_resourceid_test.go index 91aa4d202..58dea0037 100644 --- a/frontend/pkg/frontend/middleware_resourceid_test.go +++ b/frontend/pkg/frontend/middleware_resourceid_test.go @@ -61,6 +61,17 @@ func TestMiddlewareResourceID(t *testing.T) { "Microsoft.Resources/tenants", }, }, + { + name: "node pool collection", + path: "/SUBSCRIPTIONS/00000000-0000-0000-0000-000000000000/RESOURCEGROUPS/MyResourceGroup/PROVIDERS/MICROSOFT.REDHATOPENSHIFT/HCPOPENSHIFTCLUSTERS/myCluster/NODEPOOLS", + resourceTypes: []string{ + "MICROSOFT.REDHATOPENSHIFT/HCPOPENSHIFTCLUSTERS/NODEPOOLS", + "MICROSOFT.REDHATOPENSHIFT/HCPOPENSHIFTCLUSTERS", + "Microsoft.Resources/resourceGroups", + "Microsoft.Resources/subscriptions", + "Microsoft.Resources/tenants", + }, + }, { name: "preflight deployment", path: "/SUBSCRIPTIONS/00000000-0000-0000-0000-000000000000/RESOURCEGROUPS/MyResourceGroup/PROVIDERS/MICROSOFT.REDHATOPENSHIFT/DEPLOYMENTS/preflight", @@ -109,7 +120,7 @@ func TestMiddlewareResourceID(t *testing.T) { resourceTypes := []string{} for resourceID != nil { resourceTypes = append(resourceTypes, resourceID.ResourceType.String()) - resourceID = resourceID.GetParent() + resourceID = resourceID.Parent } if !reflect.DeepEqual(resourceTypes, tt.resourceTypes) { diff --git a/frontend/pkg/frontend/middleware_systemdata.go b/frontend/pkg/frontend/middleware_systemdata.go index 384934617..165d2a07d 100644 --- a/frontend/pkg/frontend/middleware_systemdata.go +++ b/frontend/pkg/frontend/middleware_systemdata.go @@ -8,27 +8,22 @@ import ( "fmt" "net/http" - "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/api/arm" ) func MiddlewareSystemData(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + ctx := r.Context() + logger := LoggerFromContext(ctx) + // See https://eng.ms/docs/products/arm/api_contracts/resourcesystemdata data := r.Header.Get(arm.HeaderNameARMResourceSystemData) if data != "" { var systemData arm.SystemData err := json.Unmarshal([]byte(data), &systemData) if err == nil { - ctx := ContextWithSystemData(r.Context(), &systemData) + ctx = ContextWithSystemData(ctx, &systemData) r = r.WithContext(ctx) } else { - logger, err := LoggerFromContext(r.Context()) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } - logger.Warn(fmt.Sprintf("Failed to parse %s header: %v", arm.HeaderNameARMResourceSystemData, err)) } } diff --git a/frontend/pkg/frontend/middleware_tracing.go b/frontend/pkg/frontend/middleware_tracing.go new file mode 100644 index 000000000..71778e2e6 --- /dev/null +++ b/frontend/pkg/frontend/middleware_tracing.go @@ -0,0 +1,18 @@ +package frontend + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "fmt" + "net/http" + + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +// MiddlewareTracing starts a span wrapping all incoming HTTP requests. +// Other middlwares or actual request handlers can extend its metadata or create +// their own associated spans. +func MiddlewareTracing(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + otelhttp.NewHandler(http.Handler(next), fmt.Sprintf("HTTP %s", r.Method)).ServeHTTP(w, r) +} diff --git a/frontend/pkg/frontend/middleware_validateapi.go b/frontend/pkg/frontend/middleware_validateapi.go index f96b6c96b..e0bbd2449 100644 --- a/frontend/pkg/frontend/middleware_validateapi.go +++ b/frontend/pkg/frontend/middleware_validateapi.go @@ -11,6 +11,9 @@ import ( ) func MiddlewareValidateAPIVersion(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + ctx := r.Context() + logger := LoggerFromContext(ctx) + apiVersion := r.URL.Query().Get(APIVersionKey) if apiVersion == "" { arm.WriteError( @@ -26,7 +29,9 @@ func MiddlewareValidateAPIVersion(w http.ResponseWriter, r *http.Request, next h api.ClusterResourceType, apiVersion) } else { - ctx := ContextWithVersion(r.Context(), version) + logger = logger.With("api_version", apiVersion) + ctx = ContextWithLogger(ctx, logger) + ctx = ContextWithVersion(ctx, version) r = r.WithContext(ctx) next(w, r) } diff --git a/frontend/pkg/frontend/middleware_validatestatic.go b/frontend/pkg/frontend/middleware_validatestatic.go index 4f172d898..26510804e 100644 --- a/frontend/pkg/frontend/middleware_validatestatic.go +++ b/frontend/pkg/frontend/middleware_validatestatic.go @@ -8,6 +8,7 @@ import ( "regexp" "strings" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/google/uuid" "github.com/Azure/ARO-HCP/internal/api" @@ -18,15 +19,13 @@ import ( var rxHCPOpenShiftClusterResourceName = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-]{2,53}$`) var rxNodePoolResourceName = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-]{2,14}$`) -var resourceTypeSubscription = "Microsoft.Resources/subscriptions" - func MiddlewareValidateStatic(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // To conform with "OAPI012: Resource IDs must not be case sensitive" // we need to use the original, non-lowercased resource ID components // in response messages. //TODO: Inspect the error instead of ignoring it originalPath, _ := OriginalPathFromContext(r.Context()) - resource, _ := arm.ParseResourceID(originalPath) + resource, _ := azcorearm.ParseResourceID(originalPath) if resource != nil { if resource.SubscriptionID != "" { @@ -40,29 +39,28 @@ func MiddlewareValidateStatic(w http.ResponseWriter, r *http.Request, next http. } } - // Skip static validation for subscription resources - if !strings.EqualFold(resource.ResourceType.String(), resourceTypeSubscription) { - switch strings.ToLower(resource.ResourceType.Type) { - case strings.ToLower(api.ClusterResourceType.Type): - if !rxHCPOpenShiftClusterResourceName.MatchString(resource.Name) { - arm.WriteError(w, http.StatusBadRequest, - arm.CloudErrorCodeInvalidResourceName, - resource.String(), - "The Resource '%s/%s' under resource group '%s' does not conform to the naming restriction.", - resource.ResourceType, resource.Name, - resource.ResourceGroupName) - return - } - case strings.ToLower(api.NodePoolResourceType.Type): - if !rxNodePoolResourceName.MatchString(resource.Name) { - arm.WriteError(w, http.StatusBadRequest, - arm.CloudErrorCodeInvalidResourceName, - resource.String(), - "The Resource '%s/%s' under resource group '%s' does not conform to the naming restriction.", - resource.ResourceType, resource.Name, - resource.ResourceGroupName) - return - } + switch strings.ToLower(resource.ResourceType.Type) { + case strings.ToLower(api.ClusterResourceType.Type): + if !rxHCPOpenShiftClusterResourceName.MatchString(resource.Name) { + arm.WriteError(w, http.StatusBadRequest, + arm.CloudErrorCodeInvalidResourceName, + resource.String(), + "The Resource '%s/%s' under resource group '%s' does not conform to the naming restriction.", + resource.ResourceType, resource.Name, + resource.ResourceGroupName) + return + } + case strings.ToLower(api.NodePoolResourceType.Type): + // The collection GET endpoint for nested resources + // parses into a ResourceID with an empty Name field. + if resource.Name != "" && !rxNodePoolResourceName.MatchString(resource.Name) { + arm.WriteError(w, http.StatusBadRequest, + arm.CloudErrorCodeInvalidResourceName, + resource.String(), + "The Resource '%s/%s' under resource group '%s' does not conform to the naming restriction.", + resource.ResourceType, resource.Name, + resource.ResourceGroupName) + return } } } diff --git a/frontend/pkg/frontend/middleware_validatesubscription.go b/frontend/pkg/frontend/middleware_validatesubscription.go index 3e1d3fb3c..6c98f5bf0 100644 --- a/frontend/pkg/frontend/middleware_validatesubscription.go +++ b/frontend/pkg/frontend/middleware_validatesubscription.go @@ -4,9 +4,9 @@ package frontend // Licensed under the Apache License 2.0. import ( + "fmt" "net/http" - "github.com/Azure/ARO-HCP/frontend/pkg/config" "github.com/Azure/ARO-HCP/internal/api/arm" ) @@ -20,18 +20,13 @@ const ( // https://github.com/cloud-and-ai-microsoft/resource-provider-contract/blob/master/v1.0/subscription-lifecycle-api-reference.md func MiddlewareValidateSubscriptionState(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { ctx := r.Context() - - logger, err := LoggerFromContext(ctx) - if err != nil { - config.DefaultLogger().Error(err.Error()) - arm.WriteInternalServerError(w) - return - } + logger := LoggerFromContext(ctx) dbClient, err := DBClientFromContext(ctx) if err != nil { logger.Error(err.Error()) arm.WriteInternalServerError(w) + return } subscriptionId := r.PathValue(PathSegmentSubscriptionID) @@ -94,5 +89,8 @@ func MiddlewareValidateSubscriptionState(w http.ResponseWriter, r *http.Request, arm.CloudErrorCodeInvalidSubscriptionState, "", InvalidSubscriptionStateMessage, sub.Subscription.State) + default: + logger.Error(fmt.Sprintf("unsupported subscription state %q", sub.Subscription.State)) + arm.WriteInternalServerError(w) } } diff --git a/frontend/pkg/frontend/middleware_validatesubscription_test.go b/frontend/pkg/frontend/middleware_validatesubscription_test.go index ee803a0f8..dbdd230e5 100644 --- a/frontend/pkg/frontend/middleware_validatesubscription_test.go +++ b/frontend/pkg/frontend/middleware_validatesubscription_test.go @@ -4,7 +4,6 @@ package frontend // Licensed under the Apache License 2.0. import ( - "context" "encoding/json" "fmt" "io" @@ -14,9 +13,11 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "go.uber.org/mock/gomock" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/mocks" ) func TestMiddlewareValidateSubscription(t *testing.T) { @@ -150,26 +151,36 @@ func TestMiddlewareValidateSubscription(t *testing.T) { }, }, }, + { + name: "subscription state value is invalid", + cachedState: arm.SubscriptionState("Invalid"), + httpMethod: http.MethodGet, + requestPath: defaultRequestPath, + expectedError: &arm.CloudError{ + StatusCode: http.StatusInternalServerError, + CloudErrorBody: &arm.CloudErrorBody{ + Code: arm.CloudErrorCodeInternalServerError, + Message: "Internal server error.", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - dbClient := database.NewCache() + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) + + var doc *database.SubscriptionDocument if tt.cachedState != "" { - if err := dbClient.CreateSubscriptionDoc(context.Background(), &database.SubscriptionDocument{ - BaseDocument: database.BaseDocument{ - ID: subscriptionId, - }, - Subscription: &arm.Subscription{ + doc = database.NewSubscriptionDocument(subscriptionId, + &arm.Subscription{ State: tt.cachedState, Properties: &arm.SubscriptionProperties{ TenantId: &tenantId, }, - }, - }); err != nil { - t.Fatal(err) - } + }) } writer := httptest.NewRecorder() @@ -182,13 +193,16 @@ func TestMiddlewareValidateSubscription(t *testing.T) { // Add a logger to the context so parsing errors will be logged. ctx := request.Context() ctx = ContextWithLogger(ctx, slog.Default()) - ctx = ContextWithDBClient(ctx, dbClient) + ctx = ContextWithDBClient(ctx, mockDBClient) request = request.WithContext(ctx) next := func(w http.ResponseWriter, r *http.Request) { request = r // capture modified request } if tt.requestPath == defaultRequestPath { request.SetPathValue(PathSegmentSubscriptionID, subscriptionId) + mockDBClient.EXPECT(). + GetSubscriptionDoc(gomock.Any(), subscriptionId). + Return(getMockDBDoc(doc)) // defined in frontend_test.go } MiddlewareValidateSubscriptionState(writer, request, next) @@ -201,14 +215,30 @@ func TestMiddlewareValidateSubscription(t *testing.T) { t.Errorf("unexpected CloudError, wanted %v, got %v", tt.expectedError, actualError) } } else { - doc, err := dbClient.GetSubscriptionDoc(request.Context(), subscriptionId) - if err != nil { - t.Fatal(err.Error()) - } if doc.Subscription.State != tt.expectedState { t.Error(cmp.Diff(doc.Subscription.State, tt.expectedState)) } } }) } + + t.Run("nil DB client in the context", func(t *testing.T) { + writer := httptest.NewRecorder() + + request, err := http.NewRequest(http.MethodGet, defaultRequestPath, nil) + if err != nil { + t.Fatal(err) + } + request.SetPathValue(PathSegmentSubscriptionID, subscriptionId) + + ctx := request.Context() + ctx = ContextWithLogger(ctx, slog.Default()) + request = request.WithContext(ctx) + + next := func(w http.ResponseWriter, r *http.Request) {} + MiddlewareValidateSubscriptionState(writer, request, next) + if writer.Code != http.StatusInternalServerError { + t.Errorf("expected status code %d, got %d", http.StatusInternalServerError, writer.Code) + } + }) } diff --git a/frontend/pkg/frontend/node_pool.go b/frontend/pkg/frontend/node_pool.go index e5e5dad7e..0970c5add 100644 --- a/frontend/pkg/frontend/node_pool.go +++ b/frontend/pkg/frontend/node_pool.go @@ -34,33 +34,32 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h // that represents an existing resource to be updated. ctx := request.Context() + logger := LoggerFromContext(ctx) versionedInterface, err := VersionFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } resourceID, err := ResourceIDFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } systemData, err := SystemDataFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("%s: CreateNodePool", versionedInterface)) - doc, err := f.dbClient.GetResourceDoc(ctx, resourceID) if err != nil && !errors.Is(err, database.ErrNotFound) { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } @@ -81,7 +80,7 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h // appropriate to fail. csNodePool, err := f.clusterServiceClient.GetCSNodePool(ctx, doc.InternalID) if err != nil { - f.logger.Error(fmt.Sprintf("failed to fetch CS node pool for %s: %v", resourceID, err)) + logger.Error(fmt.Sprintf("failed to fetch CS node pool for %s: %v", resourceID, err)) arm.WriteInternalServerError(writer) return } @@ -115,7 +114,7 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h successStatusCode = http.StatusCreated case http.MethodPatch: // PATCH requests never create a new resource. - f.logger.Error("Resource not found") + logger.Error("Resource not found") arm.WriteResourceNotFoundError(writer, resourceID) return } @@ -133,19 +132,19 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h body, err := BodyFromContext(ctx) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if err = json.Unmarshal(body, versionedRequestNodePool); err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInvalidRequestContentError(writer, err) return } cloudError = versionedRequestNodePool.ValidateStatic(versionedCurrentNodePool, updating, request.Method) if cloudError != nil { - f.logger.Error(cloudError.Error()) + logger.Error(cloudError.Error()) arm.WriteCloudError(writer, cloudError) return } @@ -156,46 +155,55 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h hcpNodePool.Name = request.PathValue(PathSegmentNodePoolName) csNodePool, err := f.BuildCSNodePool(ctx, hcpNodePool, updating) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if updating { - f.logger.Info(fmt.Sprintf("updating resource %s", resourceID)) + logger.Info(fmt.Sprintf("updating resource %s", resourceID)) csNodePool, err = f.clusterServiceClient.UpdateCSNodePool(ctx, doc.InternalID, csNodePool) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } } else { - f.logger.Info(fmt.Sprintf("creating resource %s", resourceID)) - clusterDoc, err := f.dbClient.GetResourceDoc(ctx, resourceID.GetParent()) + logger.Info(fmt.Sprintf("creating resource %s", resourceID)) + clusterDoc, err := f.dbClient.GetResourceDoc(ctx, resourceID.Parent) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } csNodePool, err = f.clusterServiceClient.PostCSNodePool(ctx, clusterDoc.InternalID, csNodePool) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } doc.InternalID, err = ocm.NewInternalID(csNodePool.HREF()) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } } - operationDoc, err := f.StartOperation(writer, request, doc, operationRequest) + operationDoc := database.NewOperationDocument(operationRequest, doc.ResourceId, doc.InternalID) + + err = f.dbClient.CreateOperationDoc(ctx, operationDoc) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return + } + + err = f.ExposeOperation(writer, request, operationDoc.ID) if err != nil { - f.logger.Error(fmt.Sprintf("failed to write operation document: %v", err)) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } @@ -227,44 +235,49 @@ func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *h updateResourceMetadata(doc) err = f.dbClient.CreateResourceDoc(ctx, doc) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - f.logger.Info(fmt.Sprintf("document created for %s", resourceID)) + logger.Info(fmt.Sprintf("document created for %s", resourceID)) } else { updated, err := f.dbClient.UpdateResourceDoc(ctx, resourceID, updateResourceMetadata) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } if updated { - f.logger.Info(fmt.Sprintf("document updated for %s", resourceID)) + logger.Info(fmt.Sprintf("document updated for %s", resourceID)) + } + // Get the updated resource document for the response. + doc, err = f.dbClient.GetResourceDoc(ctx, resourceID) + if err != nil { + logger.Error(err.Error()) + arm.WriteInternalServerError(writer) + return } } responseBody, err := marshalCSNodePool(csNodePool, doc, versionedInterface) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) arm.WriteInternalServerError(writer) return } - writer.WriteHeader(successStatusCode) - - _, err = writer.Write(responseBody) + _, err = arm.WriteJSONResponse(writer, successStatusCode, responseBody) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) } } // the necessary conversions for the API version of the request. func marshalCSNodePool(csNodePool *cmv1.NodePool, doc *database.ResourceDocument, versionedInterface api.Version) ([]byte, error) { - hcpNodePool := ConvertCStoNodePool(doc.Key, csNodePool) + hcpNodePool := ConvertCStoNodePool(doc.ResourceId, csNodePool) hcpNodePool.TrackedResource.Resource.SystemData = doc.SystemData hcpNodePool.TrackedResource.Tags = maps.Clone(doc.Tags) hcpNodePool.Properties.ProvisioningState = doc.ProvisioningState - return json.Marshal(versionedInterface.NewHCPOpenShiftClusterNodePool(hcpNodePool)) + return arm.Marshal(versionedInterface.NewHCPOpenShiftClusterNodePool(hcpNodePool)) } diff --git a/frontend/pkg/frontend/node_pool_test.go b/frontend/pkg/frontend/node_pool_test.go index 09474b591..82b50d88b 100644 --- a/frontend/pkg/frontend/node_pool_test.go +++ b/frontend/pkg/frontend/node_pool_test.go @@ -6,29 +6,32 @@ import ( "bytes" "context" "encoding/json" - "io" - "log/slog" "net" "net/http" "net/http/httptest" "testing" "time" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/mock/gomock" + "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" _ "github.com/Azure/ARO-HCP/internal/api/v20240610preview" "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/mocks" "github.com/Azure/ARO-HCP/internal/ocm" ) const dummyTenantId = "dummy-tenant-id" -const dummySubscrtiptionId = "00000000-0000-0000-0000-000000000000" +const dummySubscriptionId = "00000000-0000-0000-0000-000000000000" const dummyResourceGroupId = "dummy_resource_group_name" const dummyClusterName = "dev-test-cluster" const dummyNodePoolName = "dev-nodepool" -const dummyClusterID = ("/subscriptions/" + dummySubscrtiptionId + "/resourcegroups/" + dummyResourceGroupId + +const dummyClusterID = ("/subscriptions/" + dummySubscriptionId + "/resourcegroups/" + dummyResourceGroupId + "/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/" + dummyClusterName) const dummyNodePoolID = dummyClusterID + "/nodePools/" + dummyNodePoolName @@ -41,12 +44,12 @@ var dummyChannelGroup = "dummyChannelGroup" var dummyVersionID = "dummy" func TestCreateNodePool(t *testing.T) { - clusterResouceID, _ := arm.ParseResourceID(dummyClusterID) - clusterDoc := database.NewResourceDocument(clusterResouceID) + clusterResourceID, _ := azcorearm.ParseResourceID(dummyClusterID) + clusterDoc := database.NewResourceDocument(clusterResourceID) clusterDoc.InternalID, _ = ocm.NewInternalID(dummyClusterHREF) - nodePoolResouceID, _ := arm.ParseResourceID(dummyNodePoolID) - nodePoolDoc := database.NewResourceDocument(nodePoolResouceID) + nodePoolResourceID, _ := azcorearm.ParseResourceID(dummyNodePoolID) + nodePoolDoc := database.NewResourceDocument(nodePoolResourceID) nodePoolDoc.InternalID, _ = ocm.NewInternalID(dummyNodePoolHREF) requestBody := generated.HcpOpenShiftClusterNodePoolResource{ @@ -66,16 +69,12 @@ func TestCreateNodePool(t *testing.T) { { name: "PUT Node Pool - Create a new Node Pool", urlPath: dummyNodePoolID + "?api-version=2024-06-10-preview", - subDoc: &database.SubscriptionDocument{ - BaseDocument: database.BaseDocument{ - ID: dummySubscrtiptionId, - }, - Subscription: &arm.Subscription{ + subDoc: database.NewSubscriptionDocument(dummySubscriptionId, + &arm.Subscription{ State: arm.SubscriptionStateRegistered, RegistrationDate: api.Ptr(time.Now().String()), Properties: nil, - }, - }, + }), clusterDoc: clusterDoc, nodePoolDoc: nodePoolDoc, systemData: &arm.SystemData{}, @@ -86,30 +85,25 @@ func TestCreateNodePool(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockDBClient := mocks.NewMockDBClient(ctrl) + reg := prometheus.NewRegistry() + f := &Frontend{ - dbClient: database.NewCache(), - logger: slog.New(slog.NewTextHandler(io.Discard, nil)), - metrics: NewPrometheusEmitter(), + dbClient: mockDBClient, + metrics: NewPrometheusEmitter(reg), clusterServiceClient: &mockCSClient, } hcpCluster := api.NewDefaultHCPOpenShiftCluster() - hcpCluster.Name = dummyClusterName - csCluster, _ := f.BuildCSCluster(clusterResouceID, dummyTenantId, hcpCluster, false) + requestHeader := make(http.Header) + requestHeader.Add(arm.HeaderNameHomeTenantID, dummyTenantId) - if test.subDoc != nil { - err := f.dbClient.CreateSubscriptionDoc(context.TODO(), test.subDoc) - if err != nil { - t.Fatal(err) - } - } + hcpCluster.Name = dummyClusterName + csCluster, _ := f.BuildCSCluster(clusterResourceID, requestHeader, hcpCluster, false) if test.clusterDoc != nil { - err := f.dbClient.CreateResourceDoc(context.TODO(), test.clusterDoc) - if err != nil { - t.Fatal(err) - } - _, err = f.clusterServiceClient.PostCSCluster(context.TODO(), csCluster) + _, err := f.clusterServiceClient.PostCSCluster(context.TODO(), csCluster) if err != nil { t.Fatal(err) } @@ -120,13 +114,40 @@ func TestCreateNodePool(t *testing.T) { ts := httptest.NewServer(f.routes()) ts.Config.BaseContext = func(net.Listener) context.Context { ctx := context.Background() - ctx = ContextWithLogger(ctx, f.logger) + ctx = ContextWithLogger(ctx, testLogger) // defined in frontend_test.go ctx = ContextWithDBClient(ctx, f.dbClient) ctx = ContextWithSystemData(ctx, test.systemData) return ctx } + // MiddlewareLockSubscription + mockDBClient.EXPECT(). + GetLockClient() + // MiddlewareValidateSubscriptionState and MetricsMiddleware + mockDBClient.EXPECT(). + GetSubscriptionDoc(gomock.Any(), test.subDoc.ID). + Return(test.subDoc, nil). + Times(2) + // CreateOrUpdateNodePool + mockDBClient.EXPECT(). + GetResourceDoc(gomock.Any(), test.nodePoolDoc.ResourceId). + Return(nil, database.ErrNotFound) + // CheckForProvisioningStateConflict and CreateOrUpdateNodePool + mockDBClient.EXPECT(). + GetResourceDoc(gomock.Any(), equalResourceID(test.clusterDoc.ResourceId)). // defined in frontend_test.go + Return(test.clusterDoc, nil). + Times(2) + // CreateOrUpdateNodePool + mockDBClient.EXPECT(). + CreateOperationDoc(gomock.Any(), gomock.Any()) + // ExposeOperation + mockDBClient.EXPECT(). + UpdateOperationDoc(gomock.Any(), gomock.Any(), gomock.Any()) + // CreateOrUpdateNodePool + mockDBClient.EXPECT(). + CreateResourceDoc(gomock.Any(), gomock.Any()) + req, err := http.NewRequest(http.MethodPut, ts.URL+test.urlPath, bytes.NewReader(body)) if err != nil { t.Fatal(err) @@ -143,6 +164,8 @@ func TestCreateNodePool(t *testing.T) { if rs.StatusCode != test.expectedStatusCode { t.Errorf("expected status code %d, got %d", test.expectedStatusCode, rs.StatusCode) } + + lintMetrics(t, reg) }) } } @@ -150,12 +173,12 @@ func TestCreateNodePool(t *testing.T) { // TODO: Fix the update logic for this test. // func TestUpdateNodePool(t *testing.T) { -// clusterResouceID, _ := arm.ParseResourceID(dummyClusterID) -// clusterDoc := database.NewResourceDocument(clusterResouceID) +// clusterResourceID, _ := arm.ParseResourceID(dummyClusterID) +// clusterDoc := database.NewResourceDocument(clusterResourceID) // clusterDoc.InternalID, _ = ocm.NewInternalID(dummyClusterHREF) -// nodePoolResouceID, _ := arm.ParseResourceID(dummyNodePoolID) -// nodePoolDoc := database.NewResourceDocument(nodePoolResouceID) +// nodePoolResourceID, _ := arm.ParseResourceID(dummyNodePoolID) +// nodePoolDoc := database.NewResourceDocument(nodePoolResourceID) // nodePoolDoc.InternalID, _ = ocm.NewInternalID(dummyNodePoolHREF) // var dummyReplicas int32 = 2 @@ -184,16 +207,12 @@ func TestCreateNodePool(t *testing.T) { // { // name: "PUT Node Pool - Update an existing Node Pool", // urlPath: dummyNodePoolID + "?api-version=2024-06-10-preview", -// subDoc: &database.SubscriptionDocument{ -// BaseDocument: database.BaseDocument{ -// ID: dummySubscrtiptionId, -// }, -// Subscription: &arm.Subscription{ +// subDoc: database.NewSubscriptionDocument(dummySubscriptionId, +// &arm.Subscription{ // State: arm.SubscriptionStateRegistered, // RegistrationDate: api.Ptr(time.Now().String()), // Properties: nil, -// }, -// }, +// }), // clusterDoc: clusterDoc, // nodePoolDoc: nodePoolDoc, // systemData: &arm.SystemData{}, @@ -212,7 +231,7 @@ func TestCreateNodePool(t *testing.T) { // } // hcpCluster := api.NewDefaultHCPOpenShiftCluster() // hcpCluster.Name = dummyCluster -// csCluster, _ := f.BuildCSCluster(clusterResouceID, dummyTenantId, hcpCluster, false) +// csCluster, _ := f.BuildCSCluster(clusterResourceID, dummyTenantId, hcpCluster, false) // hcpNodePool := api.NewDefaultHCPOpenShiftClusterNodePool() // hcpNodePool.Name = dummyNodePool diff --git a/frontend/pkg/frontend/ocm.go b/frontend/pkg/frontend/ocm.go index 29e1c5b97..fbbbb24c6 100644 --- a/frontend/pkg/frontend/ocm.go +++ b/frontend/pkg/frontend/ocm.go @@ -2,12 +2,15 @@ package frontend import ( "context" + "fmt" + "net/http" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/google/uuid" + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" configv1 "github.com/openshift/api/config/v1" - "github.com/google/uuid" - "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" ) @@ -21,28 +24,44 @@ const ( csCCSEnabled bool = true ) -func convertListeningToVisibility(listening cmv1.ListeningMethod) (visibility api.Visibility) { +func convertListeningToVisibility(listening arohcpv1alpha1.ListeningMethod) (visibility api.Visibility) { switch listening { - case cmv1.ListeningMethodExternal: + case arohcpv1alpha1.ListeningMethodExternal: visibility = api.VisibilityPublic - case cmv1.ListeningMethodInternal: + case arohcpv1alpha1.ListeningMethodInternal: visibility = api.VisibilityPrivate } return } -func convertVisibilityToListening(visibility api.Visibility) (listening cmv1.ListeningMethod) { +func convertVisibilityToListening(visibility api.Visibility) (listening arohcpv1alpha1.ListeningMethod) { switch visibility { case api.VisibilityPublic: - listening = cmv1.ListeningMethodExternal + listening = arohcpv1alpha1.ListeningMethodExternal case api.VisibilityPrivate: - listening = cmv1.ListeningMethodInternal + listening = arohcpv1alpha1.ListeningMethodInternal + } + return +} + +func convertOutboundTypeCSToRP(outboundTypeCS string) (outboundTypeRP api.OutboundType) { + switch outboundTypeCS { + case "load_balancer": + outboundTypeRP = api.OutboundTypeLoadBalancer + } + return +} + +func convertOutboundTypeRPToCS(outboundTypeRP api.OutboundType) (outboundTypeCS string) { + switch outboundTypeRP { + case api.OutboundTypeLoadBalancer: + outboundTypeCS = "load_balancer" } return } // ConvertCStoHCPOpenShiftCluster converts a CS Cluster object into HCPOpenShiftCluster object -func ConvertCStoHCPOpenShiftCluster(resourceID *arm.ResourceID, cluster *cmv1.Cluster) *api.HCPOpenShiftCluster { +func ConvertCStoHCPOpenShiftCluster(resourceID *azcorearm.ResourceID, cluster *arohcpv1alpha1.Cluster) *api.HCPOpenShiftCluster { // A word about ProvisioningState: // ProvisioningState is stored in Cosmos and is applied to the // HCPOpenShiftCluster struct along with the ARM metadata that @@ -97,7 +116,7 @@ func ConvertCStoHCPOpenShiftCluster(resourceID *arm.ResourceID, cluster *cmv1.Cl Platform: api.PlatformProfile{ ManagedResourceGroup: cluster.Azure().ManagedResourceGroupName(), SubnetID: cluster.Azure().SubnetResourceID(), - OutboundType: api.OutboundTypeLoadBalancer, + OutboundType: convertOutboundTypeCSToRP(cluster.Azure().NodesOutboundConnectivity().OutboundType()), NetworkSecurityGroupID: cluster.Azure().NetworkSecurityGroupResourceID(), EtcdEncryptionSetID: "", }, @@ -110,6 +129,36 @@ func ConvertCStoHCPOpenShiftCluster(resourceID *arm.ResourceID, cluster *cmv1.Cl }, } + // Each managed identity retrieved from Cluster Service needs to be added + // to the HCPOpenShiftCluster in two places: + // - The top-level Identity.UserAssignedIdentities map will need both the + // resourceID (as keys) and principal+client IDs (as values). + // - The operator-specific maps under OperatorsAuthentication mimics the + // Cluster Service maps but just has operator-to-resourceID pairings. + if cluster.Azure().OperatorsAuthentication() != nil { + if mi, ok := cluster.Azure().OperatorsAuthentication().GetManagedIdentities(); ok { + hcpcluster.Identity.UserAssignedIdentities = make(map[string]*arm.UserAssignedIdentity) + hcpcluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ControlPlaneOperators = make(map[string]string) + hcpcluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.DataPlaneOperators = make(map[string]string) + for operatorName, operatorIdentity := range mi.ControlPlaneOperatorsManagedIdentities() { + clientID, _ := operatorIdentity.GetClientID() + principalID, _ := operatorIdentity.GetPrincipalID() + hcpcluster.Identity.UserAssignedIdentities[operatorIdentity.ResourceID()] = &arm.UserAssignedIdentity{ClientID: &clientID, + PrincipalID: &principalID} + hcpcluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ControlPlaneOperators[operatorName] = operatorIdentity.ResourceID() + } + for operatorName, operatorIdentity := range mi.DataPlaneOperatorsManagedIdentities() { + // Skip adding to hcpcluster.Identity.UserAssignedIdentities map as it is not needed for the dataplane operator MIs. + hcpcluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.DataPlaneOperators[operatorName] = operatorIdentity.ResourceID() + } + clientID, _ := mi.ServiceManagedIdentity().GetClientID() + principalID, _ := mi.ServiceManagedIdentity().GetPrincipalID() + hcpcluster.Identity.UserAssignedIdentities[mi.ServiceManagedIdentity().ResourceID()] = &arm.UserAssignedIdentity{ClientID: &clientID, + PrincipalID: &principalID} + hcpcluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ServiceManagedIdentity = mi.ServiceManagedIdentity().ResourceID() + } + } + return hcpcluster } @@ -130,12 +179,16 @@ func ensureManagedResourceGroupName(hcpCluster *api.HCPOpenShiftCluster) string } // BuildCSCluster creates a CS Cluster object from an HCPOpenShiftCluster object -func (f *Frontend) BuildCSCluster(resourceID *arm.ResourceID, tenantID string, hcpCluster *api.HCPOpenShiftCluster, updating bool) (*cmv1.Cluster, error) { +func (f *Frontend) BuildCSCluster(resourceID *azcorearm.ResourceID, requestHeader http.Header, hcpCluster *api.HCPOpenShiftCluster, updating bool) (*arohcpv1alpha1.Cluster, error) { + + // Ensure required headers are present. + if requestHeader.Get(arm.HeaderNameHomeTenantID) == "" { + return nil, fmt.Errorf("Missing " + arm.HeaderNameHomeTenantID + " header") + } - clusterBuilder := cmv1.NewCluster() + clusterBuilder := arohcpv1alpha1.NewCluster() // FIXME HcpOpenShiftCluster attributes not being passed: - // PlatformProfile.OutboundType (no CS equivalent?) // PlatformProfile.EtcdEncryptionSetID (no CS equivalent?) // ExternalAuth (TODO, complicated) @@ -149,34 +202,70 @@ func (f *Frontend) BuildCSCluster(resourceID *arm.ResourceID, tenantID string, h ID(f.location)). CloudProvider(cmv1.NewCloudProvider(). ID(csCloudProvider)). - Azure(cmv1.NewAzure(). - TenantID(tenantID). - SubscriptionID(resourceID.SubscriptionID). - ResourceGroupName(resourceID.ResourceGroupName). - ResourceName(hcpCluster.Name). - ManagedResourceGroupName(ensureManagedResourceGroupName(hcpCluster)). - SubnetResourceID(hcpCluster.Properties.Spec.Platform.SubnetID). - NetworkSecurityGroupResourceID(hcpCluster.Properties.Spec.Platform.NetworkSecurityGroupID)). Product(cmv1.NewProduct(). ID(csProductId)). - Hypershift(cmv1.NewHypershift(). + Hypershift(arohcpv1alpha1.NewHypershift(). Enabled(csHypershifEnabled)). MultiAZ(csMultiAzEnabled). - CCS(cmv1.NewCCS().Enabled(csCCSEnabled)). + CCS(arohcpv1alpha1.NewCCS().Enabled(csCCSEnabled)). Version(cmv1.NewVersion(). ID(hcpCluster.Properties.Spec.Version.ID). ChannelGroup(hcpCluster.Properties.Spec.Version.ChannelGroup)). - Network(cmv1.NewNetwork(). + Network(arohcpv1alpha1.NewNetwork(). Type(string(hcpCluster.Properties.Spec.Network.NetworkType)). PodCIDR(hcpCluster.Properties.Spec.Network.PodCIDR). ServiceCIDR(hcpCluster.Properties.Spec.Network.ServiceCIDR). MachineCIDR(hcpCluster.Properties.Spec.Network.MachineCIDR). HostPrefix(int(hcpCluster.Properties.Spec.Network.HostPrefix))). - API(cmv1.NewClusterAPI(). + API(arohcpv1alpha1.NewClusterAPI(). Listening(convertVisibilityToListening(hcpCluster.Properties.Spec.API.Visibility))). FIPS(hcpCluster.Properties.Spec.FIPS). EtcdEncryption(hcpCluster.Properties.Spec.EtcdEncryption) + azureBuilder := arohcpv1alpha1.NewAzure(). + TenantID(requestHeader.Get(arm.HeaderNameHomeTenantID)). + SubscriptionID(resourceID.SubscriptionID). + ResourceGroupName(resourceID.ResourceGroupName). + ResourceName(hcpCluster.Name). + ManagedResourceGroupName(ensureManagedResourceGroupName(hcpCluster)). + SubnetResourceID(hcpCluster.Properties.Spec.Platform.SubnetID). + NodesOutboundConnectivity(arohcpv1alpha1.NewAzureNodesOutboundConnectivity(). + OutboundType(convertOutboundTypeRPToCS(hcpCluster.Properties.Spec.Platform.OutboundType))) + + // Cluster Service rejects an empty NetworkSecurityGroupResourceID string. + if hcpCluster.Properties.Spec.Platform.NetworkSecurityGroupID != "" { + azureBuilder = azureBuilder. + NetworkSecurityGroupResourceID(hcpCluster.Properties.Spec.Platform.NetworkSecurityGroupID) + } + + // Only pass managed identity information if the x-ms-identity-url header is present. + if requestHeader.Get(arm.HeaderNameIdentityURL) != "" { + controlPlaneOperators := make(map[string]*arohcpv1alpha1.AzureControlPlaneManagedIdentityBuilder) + for operatorName, identityResourceID := range hcpCluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ControlPlaneOperators { + controlPlaneOperators[operatorName] = arohcpv1alpha1.NewAzureControlPlaneManagedIdentity().ResourceID(identityResourceID) + } + + dataPlaneOperators := make(map[string]*arohcpv1alpha1.AzureDataPlaneManagedIdentityBuilder) + for operatorName, identityResourceID := range hcpCluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.DataPlaneOperators { + dataPlaneOperators[operatorName] = arohcpv1alpha1.NewAzureDataPlaneManagedIdentity().ResourceID(identityResourceID) + } + + managedIdentitiesBuilder := arohcpv1alpha1.NewAzureOperatorsAuthenticationManagedIdentities(). + ManagedIdentitiesDataPlaneIdentityUrl(requestHeader.Get(arm.HeaderNameIdentityURL)). + ControlPlaneOperatorsManagedIdentities(controlPlaneOperators). + DataPlaneOperatorsManagedIdentities(dataPlaneOperators) + + if hcpCluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ServiceManagedIdentity != "" { + managedIdentitiesBuilder = managedIdentitiesBuilder.ServiceManagedIdentity(arohcpv1alpha1.NewAzureServiceManagedIdentity(). + ResourceID(hcpCluster.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ServiceManagedIdentity)) + } + + azureBuilder = azureBuilder.OperatorsAuthentication( + arohcpv1alpha1.NewAzureOperatorsAuthentication().ManagedIdentities(managedIdentitiesBuilder)) + } + + clusterBuilder = clusterBuilder.Azure(azureBuilder) + // Cluster Service rejects an empty DomainPrefix string. if hcpCluster.Properties.Spec.DNS.BaseDomainPrefix != "" { clusterBuilder = clusterBuilder. @@ -184,7 +273,7 @@ func (f *Frontend) BuildCSCluster(resourceID *arm.ResourceID, tenantID string, h } } - proxyBuilder := cmv1.NewProxy() + proxyBuilder := arohcpv1alpha1.NewProxy() // Cluster Service allows an empty HTTPProxy on PATCH but not PUT. if updating || hcpCluster.Properties.Spec.Proxy.HTTPProxy != "" { proxyBuilder = proxyBuilder. @@ -212,7 +301,7 @@ func (f *Frontend) BuildCSCluster(resourceID *arm.ResourceID, tenantID string, h } // ConvertCStoNodePool converts a CS Node Pool object into HCPOpenShiftClusterNodePool object -func ConvertCStoNodePool(resourceID *arm.ResourceID, np *cmv1.NodePool) *api.HCPOpenShiftClusterNodePool { +func ConvertCStoNodePool(resourceID *azcorearm.ResourceID, np *cmv1.NodePool) *api.HCPOpenShiftClusterNodePool { nodePool := &api.HCPOpenShiftClusterNodePool{ TrackedResource: arm.TrackedResource{ Resource: arm.Resource{ diff --git a/frontend/pkg/frontend/operations.go b/frontend/pkg/frontend/operations.go index 4678a5f3f..147339b68 100644 --- a/frontend/pkg/frontend/operations.go +++ b/frontend/pkg/frontend/operations.go @@ -4,12 +4,16 @@ package frontend // Licensed under the Apache License 2.0. import ( + "context" + "errors" "fmt" "net/http" "net/url" "path" "strings" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" "github.com/Azure/ARO-HCP/internal/database" @@ -18,17 +22,19 @@ import ( // AddAsyncOperationHeader adds an "Azure-AsyncOperation" header to the ResponseWriter // with a URL of the operation status endpoint for the given OperationDocument. func (f *Frontend) AddAsyncOperationHeader(writer http.ResponseWriter, request *http.Request, doc *database.OperationDocument) { + logger := LoggerFromContext(request.Context()) + // ARM will always add a Referer header, but // requests from test environments might not. referer := request.Referer() if referer == "" { - f.logger.Info("Omitting " + arm.HeaderNameAsyncOperation + " header: no referer") + logger.Info("Omitting " + arm.HeaderNameAsyncOperation + " header: no referer") return } u, err := url.ParseRequestURI(referer) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) return } @@ -47,17 +53,19 @@ func (f *Frontend) AddAsyncOperationHeader(writer http.ResponseWriter, request * // AddLocationHeader adds a "Location" header to the ResponseWriter with a URL of the // operation result endpoint for the given OperationDocument. func (f *Frontend) AddLocationHeader(writer http.ResponseWriter, request *http.Request, doc *database.OperationDocument) { + logger := LoggerFromContext(request.Context()) + // ARM will always add a Referer header, but // requests from test environments might not. referer := request.Referer() if referer == "" { - f.logger.Info("Omitting Location header: no referer") + logger.Info("Omitting Location header: no referer") return } u, err := url.ParseRequestURI(referer) if err != nil { - f.logger.Error(err.Error()) + logger.Error(err.Error()) return } @@ -77,47 +85,71 @@ func (f *Frontend) AddLocationHeader(writer http.ResponseWriter, request *http.R writer.Header().Set("Location", u.String()) } -func (f *Frontend) StartOperation(writer http.ResponseWriter, request *http.Request, resourceDoc *database.ResourceDocument, operationRequest database.OperationRequest) (*database.OperationDocument, error) { +// ExposeOperation fully initiates a new asynchronous operation by enriching +// the operation database item and adding the necessary response headers. +func (f *Frontend) ExposeOperation(writer http.ResponseWriter, request *http.Request, operationID string) error { ctx := request.Context() - operationDoc := database.NewOperationDocument(operationRequest) - - operationID, err := arm.ParseResourceID(path.Join("/", - "subscriptions", resourceDoc.Key.SubscriptionID, - "providers", api.ProviderNamespace, - "locations", f.location, - api.OperationStatusResourceTypeName, operationDoc.ID)) - if err != nil { - return nil, err - } - - operationDoc.TenantID = request.Header.Get(arm.HeaderNameHomeTenantID) - operationDoc.ClientID = request.Header.Get(arm.HeaderNameClientObjectID) - operationDoc.ExternalID = resourceDoc.Key - operationDoc.InternalID = resourceDoc.InternalID - operationDoc.OperationID = operationID - operationDoc.NotificationURI = request.Header.Get(arm.HeaderNameAsyncNotificationURI) - - err = f.dbClient.CreateOperationDoc(ctx, operationDoc) + _, err := f.dbClient.UpdateOperationDoc(ctx, operationID, func(updateDoc *database.OperationDocument) bool { + // There is no way to propagate a parse error here but it should + // never fail since we are building a trusted resource ID string. + operationID, err := azcorearm.ParseResourceID(path.Join("/", + "subscriptions", updateDoc.ExternalID.SubscriptionID, + "providers", api.ProviderNamespace, + "locations", f.location, + api.OperationStatusResourceTypeName, operationID)) + if err != nil { + LoggerFromContext(ctx).Error(err.Error()) + return false + } + + updateDoc.TenantID = request.Header.Get(arm.HeaderNameHomeTenantID) + updateDoc.ClientID = request.Header.Get(arm.HeaderNameClientObjectID) + updateDoc.OperationID = operationID + updateDoc.NotificationURI = request.Header.Get(arm.HeaderNameAsyncNotificationURI) + + // If ARM passed a notification URI, acknowledge it. + if updateDoc.NotificationURI != "" { + writer.Header().Set(arm.HeaderNameAsyncNotification, "Enabled") + } + + // Add callback header(s) based on the request method. + switch request.Method { + case http.MethodDelete, http.MethodPatch: + f.AddLocationHeader(writer, request, updateDoc) + fallthrough + case http.MethodPut: + f.AddAsyncOperationHeader(writer, request, updateDoc) + } + + return true + }) if err != nil { - return nil, err + // Delete any response headers that may have been added. + writer.Header().Del(arm.HeaderNameAsyncNotification) + writer.Header().Del(arm.HeaderNameAsyncOperation) + writer.Header().Del("Location") } - // If ARM passed a notification URI, acknowledge it. - if operationDoc.NotificationURI != "" { - writer.Header().Set(arm.HeaderNameAsyncNotification, "Enabled") - } + return err +} - // Add callback header(s) based on the request method. - switch request.Method { - case http.MethodDelete, http.MethodPatch: - f.AddLocationHeader(writer, request, operationDoc) - fallthrough - case http.MethodPut: - f.AddAsyncOperationHeader(writer, request, operationDoc) +// CancelActiveOperation marks the status of any active operation on the resource as canceled. +func (f *Frontend) CancelActiveOperation(ctx context.Context, resourceDoc *database.ResourceDocument) error { + if resourceDoc.ActiveOperationID != "" { + updated, err := f.dbClient.UpdateOperationDoc(ctx, resourceDoc.ActiveOperationID, func(updateDoc *database.OperationDocument) bool { + return updateDoc.UpdateStatus(arm.ProvisioningStateCanceled, nil) + }) + // Disregard "not found" errors; a missing operation is effectively canceled. + if err != nil && !errors.Is(err, database.ErrNotFound) { + return err + } + if updated { + logger := LoggerFromContext(ctx) + logger.Info(fmt.Sprintf("Canceled operation '%s'", resourceDoc.ActiveOperationID)) + } } - - return operationDoc, nil + return nil } // OperationIsVisible returns true if the request is being called from the same @@ -125,22 +157,29 @@ func (f *Frontend) StartOperation(writer http.ResponseWriter, request *http.Requ func (f *Frontend) OperationIsVisible(request *http.Request, doc *database.OperationDocument) bool { var visible = true + logger := LoggerFromContext(request.Context()) + tenantID := request.Header.Get(arm.HeaderNameHomeTenantID) clientID := request.Header.Get(arm.HeaderNameClientObjectID) subscriptionID := request.PathValue(PathSegmentSubscriptionID) - if doc.TenantID != "" && !strings.EqualFold(tenantID, doc.TenantID) { - f.logger.Info(fmt.Sprintf("Unauthorized tenant '%s' in status request for operation '%s'", tenantID, doc.ID)) - visible = false - } - - if doc.ClientID != "" && !strings.EqualFold(clientID, doc.ClientID) { - f.logger.Info(fmt.Sprintf("Unauthorized client '%s' in status request for operation '%s'", clientID, doc.ID)) - visible = false - } - - if !strings.EqualFold(subscriptionID, doc.OperationID.SubscriptionID) { - f.logger.Info(fmt.Sprintf("Unauthorized subscription '%s' in status request for operation '%s'", subscriptionID, doc.ID)) + if doc.OperationID != nil { + if doc.TenantID != "" && !strings.EqualFold(tenantID, doc.TenantID) { + logger.Info(fmt.Sprintf("Unauthorized tenant '%s' in status request for operation '%s'", tenantID, doc.ID)) + visible = false + } + + if doc.ClientID != "" && !strings.EqualFold(clientID, doc.ClientID) { + logger.Info(fmt.Sprintf("Unauthorized client '%s' in status request for operation '%s'", clientID, doc.ID)) + visible = false + } + + if !strings.EqualFold(subscriptionID, doc.OperationID.SubscriptionID) { + logger.Info(fmt.Sprintf("Unauthorized subscription '%s' in status request for operation '%s'", subscriptionID, doc.ID)) + visible = false + } + } else { + logger.Info(fmt.Sprintf("Status request for implicit operation '%s'", doc.ID)) visible = false } diff --git a/frontend/pkg/frontend/otel_sdk.go b/frontend/pkg/frontend/otel_sdk.go new file mode 100644 index 000000000..71217a09f --- /dev/null +++ b/frontend/pkg/frontend/otel_sdk.go @@ -0,0 +1,93 @@ +package frontend + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +// TODO: can we move this into ocm-sdk-go/tracing? +import ( + "context" + "fmt" + "log/slog" + "time" + + "go.opentelemetry.io/contrib/exporters/autoexport" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/trace" + tracesdk "go.opentelemetry.io/otel/sdk/trace" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/sdk/resource" +) + +func InstallOpenTelemetryTracer(ctx context.Context, logger *slog.Logger, resourceAttrs ...attribute.KeyValue) ( + func(context.Context) error, + error, +) { + exp, err := autoexport.NewSpanExporter(ctx, autoexport.WithFallbackSpanExporter(newNoopFactory)) + if err != nil { + return nil, fmt.Errorf("failed to create OTEL exporter: %w", err) + } + + var isNoop bool + if _, isNoop = exp.(*noopSpanExporter); !isNoop || autoexport.IsNoneSpanExporter(exp) { + isNoop = true + } + logger.InfoContext(ctx, "initialising OpenTelemetry tracer", "isNoop", isNoop) + + opts := []resource.Option{resource.WithHost()} + if len(resourceAttrs) > 0 { + opts = append(opts, resource.WithAttributes(resourceAttrs...)) + } + resources, err := resource.New(ctx, opts...) + if err != nil { + return nil, fmt.Errorf("failed to initialise trace resources: %w", err) + } + + tp := tracesdk.NewTracerProvider( + tracesdk.WithBatcher(exp), + tracesdk.WithResource(resources), + ) + otel.SetTracerProvider(tp) + + shutdown := func(ctx context.Context) error { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + return tp.Shutdown(ctx) + } + + propagator := propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}) + otel.SetTextMapPropagator(propagator) + + otel.SetErrorHandler(otelErrorHandlerFunc(func(err error) { + logger.ErrorContext(ctx, fmt.Sprintf("OpenTelemetry.ErrorHandler: %v", err)) + })) + + return shutdown, nil +} + +type otelErrorHandlerFunc func(error) + +// Handle implements otel.ErrorHandler +func (f otelErrorHandlerFunc) Handle(err error) { + f(err) +} + +func newNoopFactory(_ context.Context) (trace.SpanExporter, error) { + return &noopSpanExporter{}, nil +} + +var _ trace.SpanExporter = noopSpanExporter{} + +// noopSpanExporter is an implementation of trace.SpanExporter that performs no operations. +type noopSpanExporter struct{} + +// ExportSpans is part of trace.SpanExporter interface. +func (e noopSpanExporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error { + return nil +} + +// Shutdown is part of trace.SpanExporter interface. +func (e noopSpanExporter) Shutdown(ctx context.Context) error { + return nil +} diff --git a/frontend/pkg/frontend/routes.go b/frontend/pkg/frontend/routes.go index 70bc9e34c..e1cda53e6 100644 --- a/frontend/pkg/frontend/routes.go +++ b/frontend/pkg/frontend/routes.go @@ -45,7 +45,12 @@ func (f *Frontend) routes() *MiddlewareMux { mux := NewMiddlewareMux( MiddlewarePanic, + MiddlewareTracing, MiddlewareLogging, + // NOTE: register panic middlware twice. + // Making sure we can capture paniced requests in our trace data. + // But we also can recover if the tracing or logging middleware caused a panic. + MiddlewarePanic, MiddlewareBody, MiddlewareLowercase, MiddlewareSystemData, @@ -68,6 +73,9 @@ func (f *Frontend) routes() *MiddlewareMux { mux.Handle( MuxPattern(http.MethodGet, PatternSubscriptions, PatternResourceGroups, PatternProviders, api.ClusterResourceTypeName), postMuxMiddleware.HandlerFunc(f.ArmResourceList)) + mux.Handle( + MuxPattern(http.MethodGet, PatternSubscriptions, PatternResourceGroups, PatternProviders, PatternClusters, api.NodePoolResourceTypeName), + postMuxMiddleware.HandlerFunc(f.ArmResourceList)) // Resource ID endpoints // Request context holds an azcorearm.ResourceID diff --git a/frontend/utils/create.go b/frontend/utils/create.go index f4196963d..514241ad6 100644 --- a/frontend/utils/create.go +++ b/frontend/utils/create.go @@ -48,7 +48,7 @@ func CreateJSONFile() error { Properties: api.HCPOpenShiftClusterProperties{ Spec: api.ClusterSpec{ Version: api.VersionProfile{ - ID: "openshift-v4.16.0", + ID: "openshift-v4.17.0", ChannelGroup: "stable", }, DNS: api.DNSProfile{}, @@ -98,7 +98,7 @@ func CreateNodePool() error { ProvisioningState: arm.ProvisioningState(""), Spec: api.NodePoolSpec{ Version: api.VersionProfile{ - ID: "openshift-v4.16.0", + ID: "openshift-v4.17.0", ChannelGroup: "stable", }, Platform: api.NodePoolPlatformProfile{ diff --git a/go.work b/go.work index 57a3fa07b..1b94228a2 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,6 @@ -go 1.23.0 +go 1.23.3 -toolchain go1.23.0 +toolchain go1.23.3 use ( ./frontend diff --git a/go.work.sum b/go.work.sum index a4332a4ac..418848b21 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,8 +1,12 @@ bitbucket.org/creachadair/shell v0.0.8/go.mod h1:vINzudofoUXZSJ5tREgpy+Etyjsag3ait5WOWImEVZ0= cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cel.dev/expr v0.16.2/go.mod h1:gXngZQMkWJoSbE8mOzehJlXQyubn/Vg0vR9/F3W7iw8= chainguard.dev/go-grpc-kit v0.17.2 h1:WVYmCjDncj1MkEiU4qq7nIgzyqlCU+qyk0lJvTJ09bs= chainguard.dev/go-grpc-kit v0.17.2/go.mod h1:uZTFtFzAGyVFHhJexiHbna4N5rHQU7aUXPwytlGhqz4= +chainguard.dev/go-grpc-kit v0.17.5/go.mod h1:vQGcwZiX6jXwhyLPCZwVMvjITD+XcrSmQzuCTW/XcVc= +chainguard.dev/sdk v0.1.23/go.mod h1:TojPLtaHmy1TThjHjvPQbwKRDCusBPpQWSBZ2EkQFFk= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -21,6 +25,7 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= cloud.google.com/go/accessapproval v1.7.5 h1:uzmAMSgYcnlHa9X9YSQZ4Q1wlfl4NNkZyQgho1Z6p04= cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0= cloud.google.com/go/accesscontextmanager v1.8.5 h1:2GLNaNu9KRJhJBFTIVRoPwk6xE5mUDgD47abBq4Zp/I= @@ -48,6 +53,8 @@ cloud.google.com/go/asset v1.18.0 h1:lA0oLEsXEzKBV9LprEdeX3e9HHt8jFW2QafIhqG15JI cloud.google.com/go/asset v1.18.0/go.mod h1:JnuX7WLUc55AFKJOqF0n7gBPZostxZQCHPEu2WQ1980= cloud.google.com/go/assuredworkloads v1.11.5 h1:gCrN3IyvqY3cP0wh2h43d99CgH3G+WYs9CeuFVKChR8= cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= +cloud.google.com/go/auth v0.9.1/go.mod h1:Sw8ocT5mhhXxFklyhT12Eiy0ed6tTrPMCJjSI8KhYLk= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/automl v1.13.5 h1:ijiJy9sYWh75WrqImXsfWc1e3HR3iO+ef9fvW03Ig/4= cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y= cloud.google.com/go/baremetalsolution v1.2.4 h1:LFydisRmS7hQk9P/YhekwuZGqb45TW4QavcrMToWo5A= @@ -95,6 +102,8 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/contactcenterinsights v1.13.0 h1:6Vs/YnDG5STGjlWMEjN/xtmft7MrOTOnOZYUZtGTx0w= cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA= @@ -168,6 +177,7 @@ cloud.google.com/go/gsuiteaddons v1.6.5 h1:CZEbaBwmbYdhFw21Fwbo+C35HMe36fTE0FBSR cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.13/go.mod h1:K8mY0uSXwEXS30KrnVb+j54LB/ntfZu1dr+4zFMNbus= cloud.google.com/go/iap v1.9.4 h1:94zirc2r4t6KzhAMW0R6Dme005eTP6yf7g6vN4IhRrA= cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w= cloud.google.com/go/ids v1.4.5 h1:xd4U7pgl3GHV+MABnv1BF4/Vy/zBF7CYC8XngkOLzag= @@ -177,6 +187,7 @@ cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0Ys cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= cloud.google.com/go/kms v1.15.8 h1:szIeDCowID8th2i8XE4uRev5PMxQFqW+JjwYxL9h6xs= cloud.google.com/go/kms v1.15.8/go.mod h1:WoUHcDjD9pluCg7pNds131awnH429QGvRM3N/4MyoVs= +cloud.google.com/go/kms v1.18.5/go.mod h1:yXunGUGzabH8rjUPImp2ndHiGolHeWJJ0LODLedicIY= cloud.google.com/go/language v1.12.3 h1:iaJZg6K4j/2PvZZVcjeO/btcWWIllVRBhuTFjGO4LXs= cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8= cloud.google.com/go/lifesciences v0.9.5 h1:gXvN70m2p+4zgJFzaz6gMKaxTuF9WJ0USYoMLWAOm8g= @@ -185,6 +196,7 @@ cloud.google.com/go/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZ cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/longrunning v0.5.12/go.mod h1:S5hMV8CDJ6r50t2ubVJSKQVv5u0rmik5//KgLO3k4lU= cloud.google.com/go/managedidentities v1.6.5 h1:+bpih1piZVLxla/XBqeSUzJBp8gv9plGHIMAI7DLpDM= cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI= cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI= @@ -260,6 +272,7 @@ cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0Rdr cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc= cloud.google.com/go/security v1.15.6 h1:LYMj7ISEEjVQ0ub6E6ygGhjVbNQTH5CawKZz0bbPMVE= cloud.google.com/go/security v1.15.6/go.mod h1:UMEAGVBMqE6xZvkCR1FvUIeBEmGOCRIDwtwT357xmok= +cloud.google.com/go/security v1.18.0/go.mod h1:oS/kRVUNmkwEqzCgSmK2EaGd8SbDUvliEiADjSb/8Mo= cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU= cloud.google.com/go/securitycenter v1.27.0 h1:6aPV8eauNYC6kU69sMuuQSs6NXtgM9l85T4JqVPi7Yk= cloud.google.com/go/securitycenter v1.27.0/go.mod h1:J8BkC1KQ59pzVwFZ9OiqcKL57JwPNEv8SMxfVztjqD0= @@ -316,6 +329,7 @@ cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/I cloud.google.com/go/workflows v1.12.4 h1:uHNmUiatTbPQ4H1pabwfzpfEYD4BBnqDHqMm2IesOh4= cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= contrib.go.opencensus.io/exporter/stackdriver v0.13.14/go.mod h1:5pSSGY0Bhuk7waTHuDf4aQ8D2DrhgETRo9fy6k3Xlzc= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= @@ -338,20 +352,15 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= 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/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -375,6 +384,7 @@ github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIl github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= +github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -395,6 +405,7 @@ github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxk github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -418,68 +429,88 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/aws/aws-sdk-go v1.46.4/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.51.6 h1:Ld36dn9r7P9IjU8WZSaswQ8Y/XUCRpewim5980DwYiU= github.com/aws/aws-sdk-go v1.51.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA= github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= +github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0/go.mod h1:5zGj2eA85ClyedTDK+Whsu+w9yimnVIZvhvBKrDquM8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= github.com/aws/aws-sdk-go-v2/config v1.26.3/go.mod h1:Bxgi+DeeswYofcYO0XyGClwlrq3DZEXli0kLf4hkGA0= github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg= github.com/aws/aws-sdk-go-v2/config v1.27.9/go.mod h1:dK1FQfpwpql83kbD873E9vz4FyAxuJtR22wzoXn3qq0= +github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg= github.com/aws/aws-sdk-go-v2/credentials v1.16.14/go.mod h1:cniAUh3ErQPHtCQGPT5ouvSAQ0od8caTO9OOuufZOAE= github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao= github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ= +github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0/go.mod h1:D+duLy2ylgatV+yTlQ8JTuLfDD0BnFvnQRc+o6tbZ4M= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4/go.mod h1:84KyjNZdHC6QZW08nfHI6yZgPd+qRgaWcYsyLUo3QY8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0/go.mod h1:hL6BWM/d/qz113fVitZjbXR0E+RCTU1+x+1Idyn5NgE= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 h1:sHmMWWX5E7guWEFQ9SVo6A3S4xpPrWnd77a6y4WM6PU= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4/go.mod h1:WjpDrhWisWOIoS9n3nk67A3Ll1vfULJ9Kq6h29HTD48= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM= github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0/go.mod h1:T3/9xMKudHhnj8it5EqIrhvv11tVZqWYkKcot+BFStc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 h1:mDnFOE2sVkyphMWtTH+stv0eW3k0OTx94K63xpxHty4= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3/go.mod h1:V8MuRVcCRt5h1S+Fwu8KbC7l/gBGo3yBAyUbJM2IJOk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9/go.mod h1:z9VXZsWA2BvZNH1dT0ToUYwMu/CR9Skkj/TBX+mceZw= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0/go.mod h1:SxIkWpByiGbhbHYTo9CMTUnx2G4p4ZQMrDPcRRy//1c= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0/go.mod h1:l7kzl8n8DXoRyFz5cIMG70HnPauWa649TUhgw8Rq6lo= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 h1:mbWNpfRUTT6bnacmvOTKXZjR/HycibdWzNpfbrbLDIs= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5/go.mod h1:FCOPWGjsshkkICJIn9hq9xr6dLKtyaWpuUojiN3W1/8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11/go.mod h1:5jHR79Tv+Ccq6rwYh+W7Nptmw++WiFafMfR42XhwNl8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0/go.mod h1:l8gPU5RYGOFHJqWEpPMoRTP0VoaWQSkJdKo+hwWnnDA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0/go.mod h1:Oov79flWa/n7Ni+lQC3z+VM7PoRM47omRqbJU9B5Y7E= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 h1:4t+QEX7BsXz98W8W1lNvMAG+NX8qHz2CjLBxQKku40g= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3/go.mod h1:oFcjjUq5Hm09N9rpxTdeMeLeQcxS7mIkBkL8qUKng+A= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9/go.mod h1:9TzXX3MehQNGPwCZ3ka4CpwQsoAMWSF48/b+De9rfVM= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= +github.com/aws/aws-sdk-go-v2/service/kms v1.35.3/go.mod h1:gjDP16zn+WWalyaUqwCCioQ8gU8lzttCCc9jYsiQI/8= github.com/aws/aws-sdk-go-v2/service/s3 v1.50.2/go.mod h1:1o/W6JFUuREj2ExoQ21vHJgO7wakvjhol91M9eknFgs= github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4 h1:lW5xUzOPGAMY7HPuNF4FdyBwRc3UJ/e8KsapbesVeNU= github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4/go.mod h1:MGTaf3x/+z7ZGugCGvepnx2DS6+caCYYqKhzVoLNYPk= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1/go.mod h1:hWjsYGjVuqCgfoveVcVFPXIWgz0aByzwaxKlN1StKcM= github.com/aws/aws-sdk-go-v2/service/sso v1.18.6/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3/go.mod h1:5HFu51Elk+4oRBZVxmHrSds5jFXmFj8C3w7DVF2gnrs= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.6/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 h1:uLq0BKatTmDzWa/Nu4WO0M1AaQDaPpwTKAeByEc6WFM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3/go.mod h1:b+qdhjnxj8GSR6t5YfphOffeoQSQ1KmpoVVuBn+PWxs= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw= github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 h1:J/PpTf/hllOjx8Xu9DMflff3FajfLxqM5+tepvVXmxg= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5/go.mod h1:0ih0Z83YDH/QeQ6Ori2yGE2XvWYv/Xm+cZc01LC6oK0= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ= github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -520,6 +551,7 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chainguard-dev/slogctx v1.2.2/go.mod h1:+/TwogApSQPC+Umn9LF/T6my0KDml1XDAgpuSN/nwU4= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2 h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw= @@ -536,6 +568,10 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= +github.com/cjlapao/common-go-cryptorand v0.0.4 h1:M4hBZlxXJJ4yY3itQzDCGYJH0rmXYd1nOa8T97EPPpc= +github.com/cjlapao/common-go-cryptorand v0.0.4/go.mod h1:gUG7Bso/ZDD8tOoVmMvaYWMsglfAO9eg+p74OQH7Z2w= +github.com/cjlapao/common-go-identity v0.0.3 h1:0/lZ6Ke9KErhM4ZeJIfmETq+zUdf2jl0CH+Kn6v+HgQ= +github.com/cjlapao/common-go-identity v0.0.3/go.mod h1:xuNepNCHVI/51Q6DQgNPYvx3HS0VaeEhGnp8YcDO/+I= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= @@ -550,6 +586,9 @@ github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipa github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.3.5/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -567,22 +606,27 @@ github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5U github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= +github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/protobuild v0.3.0/go.mod h1:5mNMFKKAwCIAkFBPiOdtRx2KiQlyEJeMXnL5R1DsWu8= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= +github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= +github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -594,13 +638,15 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= +github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= @@ -633,6 +679,7 @@ github.com/eggsampler/acme/v3 v3.4.0 h1:LHWnB3wShVshK1+umL6ObCjnc0MM+D7TE8JINjk8 github.com/eggsampler/acme/v3 v3.4.0/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= github.com/eggsampler/acme/v3 v3.5.0 h1:tM8IXhS95HLm2LGxRDI3yzQrs7iZ9mKep1JjQhTIsUo= github.com/eggsampler/acme/v3 v3.5.0/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= +github.com/eggsampler/acme/v3 v3.6.0/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo= github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -643,9 +690,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= +github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= @@ -655,8 +705,6 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= @@ -674,8 +722,10 @@ github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyN github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= 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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= @@ -684,6 +734,7 @@ github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQr github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -696,19 +747,12 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/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-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= @@ -716,10 +760,12 @@ github.com/go-rod/rod v0.114.7 h1:h4pimzSOUnw7Eo41zdJA788XsawzHjJMyzCE3BrBww0= github.com/go-rod/rod v0.114.7/go.mod h1:aiedSEFg5DwG/fnNbUOTPMTTWX3MRj6vIs/a684Mthw= github.com/go-rod/rod v0.116.0 h1:ypRryjTys3EnqHskJ/TdgodFMvXV0EHvmy4bSkKZgHM= github.com/go-rod/rod v0.116.0/go.mod h1:aiedSEFg5DwG/fnNbUOTPMTTWX3MRj6vIs/a684Mthw= +github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= @@ -742,10 +788,15 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= @@ -794,6 +845,7 @@ github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u github.com/google/certificate-transparency-go v1.1.6/go.mod h1:0OJjOsOk+wj6aYQgP7FU0ioQ0AJUmnWPFMqTjQeazPQ= github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to= github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8= +github.com/google/certificate-transparency-go v1.2.1/go.mod h1:bvn/ytAccv+I6+DGkqpvSsEdiVGramgaSC6RD3tEmeE= github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= @@ -818,6 +870,7 @@ github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoG github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20210722185704-3043a050f148/go.mod h1:rq9F0RSpNKlrefnf6ZYMHKUnEJBCNzf6AcCXMYBeYvE= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= @@ -831,11 +884,13 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/rpmpack v0.6.0 h1:LoQuqlw6kHRwg25n3M0xtYrW+z2pTkR0ae1xx11hRw8= github.com/google/rpmpack v0.6.0/go.mod h1:uqVAUVQLq8UY2hCDfmJ/+rtO3aw7qyhc90rCVEabEfI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= 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/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= @@ -856,6 +911,7 @@ github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7 github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ= github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= @@ -886,6 +942,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0Q github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +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/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= @@ -923,6 +981,7 @@ github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE= github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE= +github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= @@ -943,6 +1002,7 @@ github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= @@ -953,7 +1013,9 @@ github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8 github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -973,6 +1035,8 @@ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgS github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b h1:ZGiXF8sz7PDk6RgkP+A/SFfUD0ZR/AgG6SpRNEDKZy8= github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b/go.mod h1:hQmNrgofl+IY/8L+n20H6E6PWBBTokdsv+q49j0QhsU= @@ -1001,6 +1065,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= @@ -1019,16 +1084,16 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= @@ -1062,6 +1127,7 @@ github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0U github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/lyft/protoc-gen-star/v2 v2.0.3 h1:/3+/2sWyXeMLzKd1bX+ixWKgEMsULrIivpDsuaF441o= github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1119,7 +1185,6 @@ github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5 h1:8Q0qkMVC/MmWkpIdlvZgcv2o2jrlF6zqVOh7W5YHdMA= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= 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/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU= @@ -1158,7 +1223,6 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1170,6 +1234,7 @@ github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/openshift-online/ocm-sdk-go v0.1.424 h1:fTNC0qs/s3IZWym3g7R4aS0YtyEkKuoasKvru18iKAs= github.com/openshift-online/ocm-sdk-go v0.1.424/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1180,6 +1245,8 @@ github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqw github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc= github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= +github.com/pascaldekloe/jwt v1.12.0 h1:imQSkPOtAIBAXoKKjL9ZVJuF/rVqJ+ntiLGpLyeqMUQ= +github.com/pascaldekloe/jwt v1.12.0/go.mod h1:LiIl7EwaglmH1hWThd/AmydNCnHf/mmfluBlNqHbk8U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -1198,6 +1265,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= @@ -1213,6 +1281,7 @@ github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1258,8 +1327,11 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= @@ -1275,6 +1347,7 @@ github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGq github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= @@ -1293,12 +1366,16 @@ github.com/sigstore/protobuf-specs v0.3.0 h1:E49qS++llp4psM+3NNVEb+C4AD422bT9VkO github.com/sigstore/protobuf-specs v0.3.0/go.mod h1:ynKzXpqr3dUj2Xk9O/5ZUhjnpi0F53DNi5AdH6pS3jc= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3 h1:LTfPadUAo+PDRUbbdqbeSl2OuoFQwUFTnJ4stu+nwWw= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3/go.mod h1:QV/Lxlxm0POyhfyBtIbTWxNeF18clMlkkyL9mu45y18= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.8/go.mod h1:OEhheBplZinUsm7W9BupafztVZV3ldkAxEHbpAeC0Pk= github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3 h1:xgbPRCr2npmmsuVVteJqi/ERw9+I13Wou7kq0Yk4D8g= github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3/go.mod h1:G4+I83FILPX6MtnoaUdmv/bRGEVtR3JdLeJa/kXdk/0= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8/go.mod h1:dMJdlBWKHMu2xf0wIKpbo7+QfG+RzVkBB3nHP8EMM5o= github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3 h1:vDl2fqPT0h3D/k6NZPlqnKFd1tz3335wm39qjvpZNJc= github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3/go.mod h1:9uOJXbXEXj+M6QjMKH5PaL5WDMu43rHfbIMgXzA8eKI= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.8/go.mod h1:Wa4xn/H3pU/yW/6tHiMXTpObBtBSGC5q29KYFEPKN6o= github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3 h1:h9G8j+Ds21zqqulDbA/R/ft64oQQIyp8S7wJYABYSlg= github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3/go.mod h1:zgCeHOuqF6k7A7TTEvftcA9V3FRzB7mrPtHOhXAQBnc= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8/go.mod h1:j00crVw6ki4/WViXflw0zWgNALrAzZT+GbIK8v7Xlz4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1324,6 +1401,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spiffe/go-spiffe/v2 v2.1.7 h1:VUkM1yIyg/x8X7u1uXqSRVRCdMdfRIEdFBzpqoeASGk= github.com/spiffe/go-spiffe/v2 v2.1.7/go.mod h1:QJDGdhXllxjxvd5B+2XnhhXB/+rC8gr+lNrtOryiWeE= +github.com/spiffe/go-spiffe/v2 v2.3.0/go.mod h1:Oxsaio7DBgSNqhAO9i/9tLClaVlfRok7zvJnTV8ZyIY= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= @@ -1337,12 +1415,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/sylabs/sif/v2 v2.16.0 h1:2eqaBaQQsn5DZTzm3QZm0HupZQEjNXfxRnCmtyCihEU= github.com/sylabs/sif/v2 v2.16.0/go.mod h1:d5TxgD/mhMUU3kWLmZmWJQ99Wg0asaTP0bq3ezR1xpg= github.com/sylabs/sif/v2 v2.18.0 h1:eXugsS1qx7St2Wu/AJ21KnsQiVCpouPlTigABh+6KYI= github.com/sylabs/sif/v2 v2.18.0/go.mod h1:GOQj7LIBqp15fjqH5i8ZEbLp8SXJi9S+xbRO+QQAdRo= +github.com/sylabs/sif/v2 v2.19.1/go.mod h1:U1SUhvl8X1JIxAylC0DYz1fa/Xba6EMZD1dGPGBH83E= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= @@ -1361,6 +1439,7 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= +github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0= github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/vektah/gqlparser/v2 v2.4.5/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= github.com/veraison/go-cose v1.2.1 h1:Gj4x20D0YP79J2+cK3anjGEMwIkg2xX+TKVVGUXwNAc= @@ -1374,6 +1453,7 @@ github.com/weppos/publicsuffix-go v0.30.1-0.20230620154423-38c92ad2d5c6/go.mod h github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222/go.mod h1:s41lQh6dIsDWIC1OWh7ChWJXLH0zkJ9KHZVqA7vHyuQ= github.com/weppos/publicsuffix-go v0.30.3-0.20240411085455-21202160c2ed h1:2SVbw+/Q/si5J66tuM12841RSkH/3Q4TQpiUkUctBgY= github.com/weppos/publicsuffix-go v0.30.3-0.20240411085455-21202160c2ed/go.mod h1:L9gKhYxnlc2z0fQFyL/6Y9YLnObLkmErfCYMuwgXIX8= +github.com/weppos/publicsuffix-go v0.30.3-0.20240510084413-5f1d03393b3d/go.mod h1:vLdXKydr/OJssAXmjY0XBgLXUfivBMrNRIBljgtqCnw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -1391,6 +1471,8 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= +github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= +github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= @@ -1400,11 +1482,13 @@ github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfq github.com/ysmood/gop v0.0.2/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk= github.com/ysmood/got v0.34.1 h1:IrV2uWLs45VXNvZqhJ6g2nIhY+pgIG1CUoOcqfXFl1s= github.com/ysmood/got v0.34.1/go.mod h1:yddyjq/PmAf08RMLSwDjPyCvHvYed+WjHnQxpH851LM= +github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg= github.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak= github.com/ysmood/leakless v0.8.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= +github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= @@ -1421,6 +1505,7 @@ github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97 github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/zenazn/goji v0.9.0 h1:RSQQAbXGArQ0dIDEq+PI6WqN6if+5KHu6x2Cx/GXLTQ= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= @@ -1443,6 +1528,7 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= @@ -1483,6 +1569,7 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.0.0-rcv0014/go.mod h1:BRvDrx43kiSoUx3mr7SoA7h9B8+OY99mUK+CZSQFWW4= go.opentelemetry.io/collector/semconv v0.81.0/go.mod h1:TlYPtzvsXyHOgr5eATi43qEMqwSmIziivJB2uctKswo= +go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= @@ -1500,10 +1587,10 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1: go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.0 h1:ZSdnH1x5Gm/eUFNQquwSt4/LMCOqS6KPlI9qaTKx5Ho= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.0/go.mod h1:uOTV75+LOzV+ODmL8ahRLWkFA3eQcSC2aAsbxIu4duk= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= @@ -1511,6 +1598,7 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1K go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU= @@ -1524,32 +1612,35 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= -go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.step.sm/crypto v0.44.2 h1:t3p3uQ7raP2jp2ha9P6xkQF85TJZh+87xmjSLaib+jk= go.step.sm/crypto v0.44.2/go.mod h1:x1439EnFhadzhkuaGX7sz03LEMQ+jV4gRamf5LCZJQQ= +go.step.sm/crypto v0.51.1/go.mod h1:PdrhttNU/tG9/YsVd4fdlysBN+UV503p0o2irFZQlAw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1567,6 +1658,7 @@ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -1598,6 +1690,7 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1612,6 +1705,7 @@ golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZ golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1626,6 +1720,7 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7 golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= @@ -1641,8 +1736,10 @@ golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1698,6 +1795,9 @@ golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1712,6 +1812,9 @@ golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5H golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1727,6 +1830,7 @@ golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1792,6 +1896,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.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.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1804,6 +1909,9 @@ golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= @@ -1836,12 +1944,14 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1904,7 +2014,8 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= @@ -1939,6 +2050,7 @@ google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxm google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= +google.golang.org/api v0.195.0/go.mod h1:DOGRWuv3P8TU8Lnz7uQc4hyNqrBpMtD9ppW3wBJurgc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1986,6 +2098,8 @@ google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqt google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 h1:ImUcDPHjTrAqNhlOkSocDLfG9rrNHH7w7uoKWPaWZ8s= google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7/go.mod h1:/3XmxOjePkvmKrHuBy4zNFw7IzxJXtAgdpXi8Ll990U= +google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c h1:TYOEhrQMrNDTAd2rX9m+WgGr8Ku6YNuj1D7OX6rWSok= +google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c/go.mod h1:2rC5OendXvZ8wGEo/cSLheztrZDZaSoHanUcd1xtZnw= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= @@ -1998,8 +2112,13 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 h1: google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240314234333-6e1732d8331c/go.mod h1:IN9OQUXZ0xT+26MDwZL8fJcYw+y99b0eYPA2U15Jt8o= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240318140521-94a12d6c2237 h1:BGtl5+MtFriTFllRl3QPEPWZrD8nVhSTONzTkSin3+c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240318140521-94a12d6c2237/go.mod h1:IN9OQUXZ0xT+26MDwZL8fJcYw+y99b0eYPA2U15Jt8o= @@ -2014,10 +2133,16 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2038,12 +2163,13 @@ google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= @@ -2067,16 +2193,21 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCMMIYYEVcAR5MDsuHlVkaIPDAF+5Dehzg8L5A= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= @@ -2097,8 +2228,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2107,6 +2236,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069z honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c= k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM= @@ -2124,8 +2254,6 @@ k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kms v0.31.1 h1:cGLyV3cIwb0ovpP/jtyIe2mEuQ/MkbhmeBF2IYCA9Io= k8s.io/kms v0.31.1/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -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/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= @@ -2133,8 +2261,11 @@ knative.dev/pkg v0.0.0-20230612155445-74c4be5e935e h1:koM+NopG2Yw738NlJhQF3ZwpyS knative.dev/pkg v0.0.0-20230612155445-74c4be5e935e/go.mod h1:dqC6IrvyBE7E+oZocs5PkVhq1G59pDTA7r8U17EAKMk= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= @@ -2144,6 +2275,7 @@ sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrL sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/release-utils v0.7.7 h1:JKDOvhCk6zW8ipEOkpTGDH/mW3TI+XqtPp16aaQ79FU= sigs.k8s.io/release-utils v0.7.7/go.mod h1:iU7DGVNi3umZJ8q6aHyUFzsDUIaYwNnNKGHo3YE5E3s= +sigs.k8s.io/release-utils v0.8.4/go.mod h1:m1bHfscTemQp+z+pLCZnkXih9n0+WukIUU70n6nFnU0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= diff --git a/helm-cmd.mk b/helm-cmd.mk new file mode 100644 index 000000000..53dedfb56 --- /dev/null +++ b/helm-cmd.mk @@ -0,0 +1,5 @@ +ifdef DRY_RUN +HELM_CMD ?= helm diff upgrade --install --dry-run=server --suppress-secrets --three-way-merge +else +HELM_CMD ?= helm upgrade --install --wait --wait-for-jobs +endif diff --git a/hypershiftoperator/.gitignore b/hypershiftoperator/.gitignore index eb4d062d7..aee2e4ce1 100644 --- a/hypershiftoperator/.gitignore +++ b/hypershiftoperator/.gitignore @@ -1,7 +1 @@ -kubectl-slice -edo-azure-credentials.json -domain.txt -patch-serviceaccount-external-dns.json -test -deploy/overlays/dev/txt_owner_id.txt config.mk diff --git a/hypershiftoperator/Makefile b/hypershiftoperator/Makefile index 4cb127842..c9a1b915d 100644 --- a/hypershiftoperator/Makefile +++ b/hypershiftoperator/Makefile @@ -1,71 +1,18 @@ -SHELL := /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk - -HO_IMAGE ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io/acm-d/rhtap-hypershift-operator:${HO_IMAGE_TAG} -EDO_IMAGE ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io/external-dns/external-dns:${ED_IMAGE_TAG} - -create-edo-azure-creds: - @echo '{' > deploy/overlays/dev/edo-azure-credentials.json - @AZURE_TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ - echo " \"tenantId\": \"$$AZURE_TENANT_ID\"," >> deploy/overlays/dev/edo-azure-credentials.json - @AZURE_SUBSCRIPTION_ID=$(shell az account show --query id --output tsv) && \ - echo " \"subscriptionId\": \"$$AZURE_SUBSCRIPTION_ID\"," >> deploy/overlays/dev/edo-azure-credentials.json - @echo ' "resourceGroup": "${REGIONAL_RESOURCEGROUP}",' >> deploy/overlays/dev/edo-azure-credentials.json - @echo ' "useWorkloadIdentityExtension": true,' >> deploy/overlays/dev/edo-azure-credentials.json - @EXTERNAL_DNS_OPERATOR_MI_CLIENT_ID=$(shell az identity show -g ${RESOURCEGROUP} -n external-dns --query clientId -o tsv) && \ - echo " \"userAssignedIdentityID\": \"$$EXTERNAL_DNS_OPERATOR_MI_CLIENT_ID\"" >> deploy/overlays/dev/edo-azure-credentials.json - @echo '}' >> deploy/overlays/dev/edo-azure-credentials.json - -create-edo-sa-patch: - @EXTERNAL_DNS_OPERATOR_MI_CLIENT_ID=$(shell az identity show -g ${RESOURCEGROUP} -n external-dns --query clientId -o tsv) && \ - echo "[{\"op\": \"add\", \"path\": \"/metadata/annotations/azure.workload.identity~1client-id\", \"value\": \"$$EXTERNAL_DNS_OPERATOR_MI_CLIENT_ID\"}]" > deploy/overlays/dev/patch-serviceaccount-external-dns.json - -create-domain-file: - @echo "${ZONE_NAME}" > deploy/overlays/dev/domain.txt - -create-txt-owner-id-file: - @echo "${RESOURCEGROUP}" > deploy/overlays/dev/txt_owner_id.txt - -deploy: create-edo-azure-creds create-edo-sa-patch create-domain-file create-txt-owner-id-file - kubectl apply --server-side --force-conflicts -k deploy/crds - kubectl apply --server-side --force-conflicts -k deploy/overlays/dev - -# run this task whenever HO_IMAGE or EDO_IMAGE is updated -# commit the changes to deploy/base to the repo since we don't have podman or docker in CI -prepare-ho-manifests: - @curl -sfLo - "https://github.com/patrickdappollonio/kubectl-slice/releases/download/v1.3.1/kubectl-slice_${shell uname -s | tr '[:upper:]' '[:lower:]'}_${shell uname -m}.tar.gz" | tar xzf - kubectl-slice - @rm deploy/base/* - curl https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml -o deploy/base/customresourcedefinition-monitoring.coreos.com_servicemonitors.yaml - curl https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml -o deploy/base/customresourcedefinition-monitoring.coreos.com_prometheusrules.yaml - curl https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml -o deploy/base/customresourcedefinition-monitoring.coreos.com_podmonitors.yaml - curl https://raw.githubusercontent.com/openshift/api/master/route/v1/zz_generated.crd-manifests/routes-Default.crd.yaml -o deploy/base/customresourcedefinition-routes-default.crd.yaml - # Currently the hypershift install render command prints an error out to stdout if there is no available kubeconfig - # TODO: Get a fix into the hypershift install render command so we don't have to do this - @podman run -it --rm ${HO_IMAGE} install render \ - --hypershift-image ${HO_IMAGE} \ - --enable-conversion-webhook=false \ - --external-dns-provider azure \ - --external-dns-secret external-dns-azure \ - --external-dns-domain-filter \$$\(DOMAIN\) \ - --external-dns-image ${EDO_IMAGE} \ - --external-dns-txt-owner-id \$$\(TXT_OWNER_ID\) \ - --managed-service ARO-HCP \ - | tail -n +2 \ - | ./kubectl-slice -f - -o deploy/base - @rm deploy/crds/* - @mkdir -p deploy/crds - @mv deploy/base/customresourcedefinition*.yaml deploy/crds - - @echo "apiVersion: kustomize.config.k8s.io/v1beta1" > deploy/crds/kustomization.yml - @echo "kind: Kustomization" >> deploy/crds/kustomization.yml - @echo "resources:" >> deploy/crds/kustomization.yml - @find deploy/crds -type f -name "customresourcedefinition*.yaml" ! -name "kustomization.yml" | sed 's/^deploy\/crds\// - /' >> deploy/crds/kustomization.yml - - @echo "apiVersion: kustomize.config.k8s.io/v1beta1" > deploy/base/kustomization.yml - @echo "kind: Kustomization" >> deploy/base/kustomization.yml - @echo "resources:" >> deploy/base/kustomization.yml - @find deploy/base -type f -name "*.yaml" ! -name "kustomization.yml" | sed 's/^deploy\/base\// - /' >> deploy/base/kustomization.yml - -.PHONY: create-edo-azure-creds create-edo-sa-patch create-domain-file create-txt-owner-id-file deploy unpack-ho-manifests +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install + +deploy: + @kubectl create namespace ${HYPERSHIFT_NAMESPACE} --dry-run=client -o json | kubectl apply -f - && \ + AZURE_TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ + AZURE_SUBSCRIPTION_ID=$(shell az account show --query id --output tsv) && \ + CSI_SECRET_STORE_CLIENT_ID=$(shell az aks show -n ${AKS_NAME} -g ${RESOURCEGROUP} --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.clientId' -o tsv) && \ + ${HELM_CMD} hypershift deploy/helm \ + --namespace ${HYPERSHIFT_NAMESPACE} \ + --set image=${ARO_HCP_SVC_ACR}.azurecr.io/acm-d/rhtap-hypershift-operator \ + --set imageTag=${HO_IMAGE_TAG} \ + --set registryOverrides="quay.io/openshift-release-dev/ocp-v4.0-art-dev=${ARO_HCP_OCP_ACR}.azurecr.io/openshift/release\,quay.io/openshift-release-dev/ocp-release=${ARO_HCP_OCP_ACR}.azurecr.io/openshift/release-images\,registry.redhat.io/redhat=${ARO_HCP_OCP_ACR}.azurecr.io/redhat" \ + --set additionalArgs="${HO_ADDITIONAL_INSTALL_ARG}" \ + --set azureKeyVaultClientId=$${CSI_SECRET_STORE_CLIENT_ID} + +.PHONY: deploy diff --git a/hypershiftoperator/README.md b/hypershiftoperator/README.md index 141a3ab40..8560cec3c 100644 --- a/hypershiftoperator/README.md +++ b/hypershiftoperator/README.md @@ -1,3 +1,3 @@ # HyperShift Operator -To promote HyperShift Operator, increment the `HO_IMAGE` variable in the Makefile, then run `make prepare-ho-manifests` to generate the corresponding manifests for that image. \ No newline at end of file +To promote HyperShift Operator, increment the `hypershiftOperatorImageTag` parameter in the `config/config.yaml` file. diff --git a/hypershiftoperator/config.tmpl.mk b/hypershiftoperator/config.tmpl.mk deleted file mode 100644 index f08a8b411..000000000 --- a/hypershiftoperator/config.tmpl.mk +++ /dev/null @@ -1,6 +0,0 @@ -ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} -HO_IMAGE_TAG ?= {{ .hypershiftOperatorImageTag }} -ED_IMAGE_TAG ?= {{ .externalDNSImageTag }} -RESOURCEGROUP ?= {{ .managementClusterRG }} -REGIONAL_RESOURCEGROUP ?= {{ .regionRG }} -ZONE_NAME ?= {{ .regionalDNSSubdomain }}.{{ .baseDnsZoneName }} diff --git a/hypershiftoperator/deploy/base/clusterrole-external-dns.yaml b/hypershiftoperator/deploy/base/clusterrole-external-dns.yaml deleted file mode 100644 index 89747fe0b..000000000 --- a/hypershiftoperator/deploy/base/clusterrole-external-dns.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - name: external-dns -rules: -- apiGroups: - - route.openshift.io - resources: - - '*' - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - endpoints - - services - - nodes - - pods - verbs: - - get - - list - - watch diff --git a/hypershiftoperator/deploy/base/clusterrole-hypershift-operator.yaml b/hypershiftoperator/deploy/base/clusterrole-hypershift-operator.yaml deleted file mode 100644 index c2a4df432..000000000 --- a/hypershiftoperator/deploy/base/clusterrole-hypershift-operator.yaml +++ /dev/null @@ -1,296 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - name: hypershift-operator -rules: -- apiGroups: - - hypershift.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - certificates.hypershift.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - scheduling.hypershift.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - config.openshift.io - resources: - - '*' - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - '*' -- apiGroups: - - batch - resources: - - cronjobs - - jobs - verbs: - - '*' -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - '*' -- apiGroups: - - networking.k8s.io - resources: - - networkpolicies - verbs: - - '*' -- apiGroups: - - bootstrap.cluster.x-k8s.io - - controlplane.cluster.x-k8s.io - - infrastructure.cluster.x-k8s.io - - machines.cluster.x-k8s.io - - exp.infrastructure.cluster.x-k8s.io - - addons.cluster.x-k8s.io - - exp.cluster.x-k8s.io - - cluster.x-k8s.io - - monitoring.coreos.com - - monitoring.rhobs - resources: - - '*' - verbs: - - '*' -- apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - '*' -- apiGroups: - - operator.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - route.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - image.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - verbs: - - '*' -- apiGroups: - - rbac.authorization.k8s.io - resources: - - '*' - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - deletecollection -- apiGroups: - - "" - resources: - - events - - configmaps - - configmaps/finalizers - - persistentvolumeclaims - - pods - - pods/log - - secrets - - nodes - - namespaces - - serviceaccounts - - services - - endpoints - verbs: - - '*' -- apiGroups: - - apps - resources: - - deployments - - replicasets - - statefulsets - verbs: - - '*' -- apiGroups: - - etcd.database.coreos.com - resources: - - '*' - verbs: - - '*' -- apiGroups: - - machine.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - - monitoring.rhobs - resources: - - podmonitors - verbs: - - get - - list - - watch - - create - - update -- apiGroups: - - capi-provider.agent-install.openshift.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - operator.openshift.io - resources: - - ingresscontrollers - verbs: - - '*' -- apiGroups: - - kubevirt.io - resources: - - virtualmachineinstances - - virtualmachines - - virtualmachines/finalizers - verbs: - - '*' -- apiGroups: - - cdi.kubevirt.io - resources: - - datavolumes - verbs: - - get - - list - - watch -- apiGroups: - - ipam.cluster.x-k8s.io - resources: - - ipaddressclaims - - ipaddressclaims/status - verbs: - - '*' -- apiGroups: - - ipam.cluster.x-k8s.io - resources: - - ipaddresses - - ipaddresses/status - verbs: - - create - - delete - - get - - list - - update - - watch -- apiGroups: - - subresources.kubevirt.io - resources: - - virtualmachineinstances/addvolume - - virtualmachineinstances/removevolume - verbs: - - '*' -- apiGroups: - - cdi.kubevirt.io - resources: - - datavolumes - verbs: - - '*' -- apiGroups: - - agent-install.openshift.io - resources: - - agents - verbs: - - '*' -- apiGroups: - - snapshot.storage.k8s.io - resources: - - volumesnapshots - verbs: - - get - - create - - delete -- apiGroups: - - extensions.hive.openshift.io - resources: - - agentclusterinstalls - verbs: - - '*' -- apiGroups: - - hive.openshift.io - resources: - - clusterdeployments - verbs: - - '*' -- apiGroups: - - discovery.k8s.io - resources: - - endpointslices - - endpointslices/restricted - verbs: - - '*' -- apiGroups: - - admissionregistration.k8s.io - resourceNames: - - hypershift.openshift.io - resources: - - validatingwebhookconfigurations - verbs: - - delete -- apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests - verbs: - - get - - list - - watch -- apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests/status - verbs: - - patch -- apiGroups: - - certificates.k8s.io - resources: - - certificatesigningrequests/approval - verbs: - - update -- apiGroups: - - certificates.k8s.io - resources: - - signers - verbs: - - approve -- apiGroups: - - certificates.k8s.io - resources: - - signers - verbs: - - sign diff --git a/hypershiftoperator/deploy/base/clusterrolebinding-hypershift-operator.yaml b/hypershiftoperator/deploy/base/clusterrolebinding-hypershift-operator.yaml deleted file mode 100644 index c455db285..000000000 --- a/hypershiftoperator/deploy/base/clusterrolebinding-hypershift-operator.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - creationTimestamp: null - name: hypershift-operator -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: hypershift-operator -subjects: -- kind: ServiceAccount - name: operator - namespace: hypershift diff --git a/hypershiftoperator/deploy/base/configmap-openshift-config-managed-trusted-ca-bundle.yaml b/hypershiftoperator/deploy/base/configmap-openshift-config-managed-trusted-ca-bundle.yaml deleted file mode 100644 index bf945ef4e..000000000 --- a/hypershiftoperator/deploy/base/configmap-openshift-config-managed-trusted-ca-bundle.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - creationTimestamp: null - labels: - config.openshift.io/inject-trusted-cabundle: "true" - name: openshift-config-managed-trusted-ca-bundle - namespace: hypershift diff --git a/hypershiftoperator/deploy/base/deployment-external-dns.yaml b/hypershiftoperator/deploy/base/deployment-external-dns.yaml deleted file mode 100644 index fad296525..000000000 --- a/hypershiftoperator/deploy/base/deployment-external-dns.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - creationTimestamp: null - name: external-dns - namespace: hypershift -spec: - replicas: 1 - selector: - matchLabels: - name: external-dns - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: external-dns - hypershift.openshift.io/operator-component: external-dns - name: external-dns - spec: - containers: - - args: - - --source=service - - --source=openshift-route - - --domain-filter=$(DOMAIN) - - --provider=azure - - --registry=txt - - --txt-suffix=-external-dns - - --txt-owner-id=$(TXT_OWNER_ID) - - --label-filter=hypershift.openshift.io/route-visibility!=private - - --interval=1m - - --txt-cache-interval=1h - - --azure-config-file=/etc/provider/credentials - command: - - /external-dns - image: arohcpdev.azurecr.io/external-dns/external-dns:v0.14.2 - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 5 - httpGet: - path: /healthz - port: 7979 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - successThreshold: 1 - timeoutSeconds: 5 - name: external-dns - ports: - - containerPort: 7979 - name: metrics - resources: - requests: - cpu: 5m - memory: 20Mi - securityContext: - privileged: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /etc/provider - name: credentials - imagePullSecrets: - - name: pull-secret - priorityClassName: hypershift-operator - serviceAccountName: external-dns - volumes: - - name: credentials - secret: - secretName: external-dns-azure -status: {} diff --git a/hypershiftoperator/deploy/base/deployment-operator.yaml b/hypershiftoperator/deploy/base/deployment-operator.yaml deleted file mode 100644 index 3d4af41d0..000000000 --- a/hypershiftoperator/deploy/base/deployment-operator.yaml +++ /dev/null @@ -1,144 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - hypershift.openshift.io/install-cli-version: 'openshift/hypershift: 99a256fc978cf2bd7b4553e123816b46d96859ea. - Latest supported OCP: 4.18.0' - creationTimestamp: null - name: operator - namespace: hypershift -spec: - replicas: 1 - selector: - matchLabels: - name: operator - strategy: {} - template: - metadata: - creationTimestamp: null - labels: - app: operator - hypershift.openshift.io/operator-component: operator - name: operator - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: name - operator: In - values: - - operator - topologyKey: kubernetes.io/hostname - weight: 10 - containers: - - args: - - run - - --namespace=$(MY_NAMESPACE) - - --pod-name=$(MY_NAME) - - --metrics-addr=:9000 - - --enable-dedicated-request-serving-isolation=true - - --enable-ocp-cluster-monitoring=false - - --enable-ci-debug-output=false - - --private-platform=None - command: - - /usr/bin/hypershift-operator - env: - - name: MY_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: MY_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: METRICS_SET - value: Telemetry - - name: CERT_ROTATION_SCALE - value: 24h0m0s - - name: MANAGED_SERVICE - value: ARO-HCP - - name: ENABLE_ETCD_RECOVERY - value: "1" - image: arohcpdev.azurecr.io/acm-d/rhtap-hypershift-operator:99a256f - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 5 - httpGet: - path: /metrics - port: 9000 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 60 - successThreshold: 1 - timeoutSeconds: 5 - name: operator - ports: - - containerPort: 9000 - name: metrics - protocol: TCP - - containerPort: 9443 - name: manager - protocol: TCP - readinessProbe: - failureThreshold: 3 - httpGet: - path: /metrics - port: 9000 - scheme: HTTP - initialDelaySeconds: 15 - periodSeconds: 60 - successThreshold: 1 - timeoutSeconds: 5 - resources: - requests: - cpu: 10m - memory: 150Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsUser: 1000 - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /etc/pki/ca-trust/extracted/pem - name: trusted-ca-bundle - readOnly: true - initContainers: - - args: - - init - command: - - /usr/bin/hypershift-operator - image: arohcpdev.azurecr.io/acm-d/rhtap-hypershift-operator:99a256f - imagePullPolicy: IfNotPresent - name: init-environment - resources: {} - securityContext: - privileged: false - readOnlyRootFilesystem: true - runAsUser: 1000 - volumeMounts: - - mountPath: /var/run/ca-trust - name: openshift-config-managed-trusted-ca-bundle - readOnly: true - - mountPath: /trust-bundle - name: trusted-ca-bundle - priorityClassName: hypershift-operator - serviceAccountName: operator - volumes: - - configMap: - items: - - key: ca-bundle.crt - path: tls-ca-bundle.pem - name: openshift-config-managed-trusted-ca-bundle - optional: true - name: openshift-config-managed-trusted-ca-bundle - - emptyDir: {} - name: trusted-ca-bundle -status: {} diff --git a/hypershiftoperator/deploy/base/kustomization.yml b/hypershiftoperator/deploy/base/kustomization.yml deleted file mode 100644 index e0ca0f24b..000000000 --- a/hypershiftoperator/deploy/base/kustomization.yml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - clusterrole-external-dns.yaml - - configmap-openshift-config-managed-trusted-ca-bundle.yaml - - podmonitor-external-dns.yaml - - clusterrole-hypershift-operator.yaml - - priorityclass-hypershift-etcd.yaml - - role-prometheus.yaml - - deployment-operator.yaml - - rolebinding-authentication-reader-for-authenticated-users.yaml - - priorityclass-hypershift-api-critical.yaml - - clusterrolebinding-hypershift-operator.yaml - - servicemonitor-operator.yaml - - prometheusrule-metrics.yaml - - role-hypershift-operator.yaml - - priorityclass-hypershift-control-plane.yaml - - serviceaccount-external-dns.yaml - - rolebinding-prometheus.yaml - - clusterrolebinding-external-dns.yaml - - namespace-hypershift.yaml - - service-operator.yaml - - rolebinding-hypershift-operator.yaml - - deployment-external-dns.yaml - - serviceaccount-operator.yaml - - priorityclass-hypershift-operator.yaml diff --git a/hypershiftoperator/deploy/base/namespace-hypershift.yaml b/hypershiftoperator/deploy/base/namespace-hypershift.yaml deleted file mode 100644 index 4d1aecb69..000000000 --- a/hypershiftoperator/deploy/base/namespace-hypershift.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - creationTimestamp: null - labels: - hypershift.openshift.io/monitoring: "true" - openshift.io/cluster-monitoring: "true" - name: hypershift -spec: {} -status: {} diff --git a/hypershiftoperator/deploy/base/podmonitor-external-dns.yaml b/hypershiftoperator/deploy/base/podmonitor-external-dns.yaml deleted file mode 100644 index efdfc5bff..000000000 --- a/hypershiftoperator/deploy/base/podmonitor-external-dns.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: azmonitoring.coreos.com/v1 -kind: PodMonitor -metadata: - creationTimestamp: null - name: external-dns - namespace: hypershift -spec: - jobLabel: component - namespaceSelector: {} - podMetricsEndpoints: - - bearerTokenSecret: - key: "" - interval: 30s - port: metrics - selector: - matchLabels: - name: external-dns diff --git a/hypershiftoperator/deploy/base/priorityclass-hypershift-api-critical.yaml b/hypershiftoperator/deploy/base/priorityclass-hypershift-api-critical.yaml deleted file mode 100644 index 192d7cf78..000000000 --- a/hypershiftoperator/deploy/base/priorityclass-hypershift-api-critical.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: scheduling.k8s.io/v1 -description: This priority class should be used for hypershift control plane pods - critical to serving the API. -kind: PriorityClass -metadata: - creationTimestamp: null - name: hypershift-api-critical -preemptionPolicy: Never -value: 100001000 diff --git a/hypershiftoperator/deploy/base/priorityclass-hypershift-control-plane.yaml b/hypershiftoperator/deploy/base/priorityclass-hypershift-control-plane.yaml deleted file mode 100644 index 9fa693f44..000000000 --- a/hypershiftoperator/deploy/base/priorityclass-hypershift-control-plane.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: scheduling.k8s.io/v1 -description: This priority class should be used for hypershift control plane pods - not critical to serving the API. -kind: PriorityClass -metadata: - creationTimestamp: null - name: hypershift-control-plane -preemptionPolicy: Never -value: 100000000 diff --git a/hypershiftoperator/deploy/base/priorityclass-hypershift-etcd.yaml b/hypershiftoperator/deploy/base/priorityclass-hypershift-etcd.yaml deleted file mode 100644 index 860817a3c..000000000 --- a/hypershiftoperator/deploy/base/priorityclass-hypershift-etcd.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: scheduling.k8s.io/v1 -description: This priority class should be used for hypershift etcd pods. -kind: PriorityClass -metadata: - creationTimestamp: null - name: hypershift-etcd -preemptionPolicy: Never -value: 100002000 diff --git a/hypershiftoperator/deploy/base/priorityclass-hypershift-operator.yaml b/hypershiftoperator/deploy/base/priorityclass-hypershift-operator.yaml deleted file mode 100644 index 216863ad3..000000000 --- a/hypershiftoperator/deploy/base/priorityclass-hypershift-operator.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: scheduling.k8s.io/v1 -description: This priority class is used for hypershift operator pods -kind: PriorityClass -metadata: - creationTimestamp: null - name: hypershift-operator -value: 100003000 diff --git a/hypershiftoperator/deploy/base/prometheusrule-metrics.yaml b/hypershiftoperator/deploy/base/prometheusrule-metrics.yaml deleted file mode 100644 index c44290511..000000000 --- a/hypershiftoperator/deploy/base/prometheusrule-metrics.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - creationTimestamp: null - name: metrics - namespace: hypershift -spec: - groups: - - interval: 30s - name: hypershift.rules - rules: - - expr: sum by (namespace) (rate(apiserver_request_total{verb=~"LIST|GET|WATCH"}[2m])) - record: hypershift:apiserver_request_total:read - - expr: sum by (namespace) (rate(apiserver_request_total{verb=~"POST|PUT|PATCH|UPDATE|DELETE|APPLY"}[2m])) - record: hypershift:apiserver_request_total:write - - expr: sum by (namespace, system_client) (rate(apiserver_request_total{}[2m])) - record: hypershift:apiserver_request_total:client - - expr: sort_desc(sum(rate(apiserver_request_aborts_total[1m])) by (resource, - verb)) - record: hypershift:apiserver_request_aborts_total - - expr: sum by (app, namespace, code, method, pod) ( sum(rest_client_requests_total) - by (pod, namespace, code, method) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_api_requests_total - - expr: sum by (app, namespace, pod) ( sum(container_memory_usage_bytes{container!="POD",container!=""}) - by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_memory_usage - - expr: sum by (app, namespace, pod) ( sum(container_memory_rss{container!="POD",container!=""}) - by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_memory_rss - - expr: sum by (app, namespace, pod) ( sum(kube_pod_container_resource_requests{resource="memory"}) - by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_memory_request - - expr: histogram_quantile(0.9, sum by (namespace, le) (rate(ign_server_payload_generation_seconds_bucket{container="ignition-server"}[3m]))) - record: hypershift:controlplane:ign_payload_generation_seconds_p90 - - expr: avg by (app, namespace, pod) ( sum( rate( container_cpu_usage_seconds_total{container_name!="POD",container!=""}[2m] - ) ) by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) / count by (app, namespace, pod) ( sum( - rate( container_cpu_usage_seconds_total{container_name!="POD",container!=""}[2m] - ) ) by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_cpu_usage_seconds - - expr: sum by (app, namespace, pod) ( sum(kube_pod_container_resource_requests{resource="cpu"}) - by (pod, namespace) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_control_plane_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:controlplane:component_cpu_request - - expr: sum by (app, namespace, code, method) ( sum(rest_client_requests_total) - by (pod, namespace, code, method) * on (pod, namespace) group_left(app) label_replace(kube_pod_labels{label_hypershift_openshift_io_operator_component!=""}, - "app", "$1", "label_app", "(.*)") ) - record: hypershift:operator:component_api_requests_total - - expr: max by(platform) (hypershift_hostedclusters) - record: platform:hypershift_hostedclusters:max - - expr: max by(platform) (hypershift_nodepools) - record: platform:hypershift_nodepools:max - - expr: sum by(cluster_name, exported_namespace) (max by(name, exported_namespace, - platform, cluster_name) (hypershift_nodepools_size)) - record: cluster_name:hypershift_nodepools_size:sum - - expr: sum by(cluster_name, exported_namespace) (max by(name, exported_namespace, - platform, cluster_name) (hypershift_nodepools_available_replicas)) - record: cluster_name:hypershift_nodepools_available_replicas:sum diff --git a/hypershiftoperator/deploy/base/role-hypershift-operator.yaml b/hypershiftoperator/deploy/base/role-hypershift-operator.yaml deleted file mode 100644 index f0e9c7aad..000000000 --- a/hypershiftoperator/deploy/base/role-hypershift-operator.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - creationTimestamp: null - name: hypershift-operator - namespace: hypershift -rules: -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - '*' diff --git a/hypershiftoperator/deploy/base/role-prometheus.yaml b/hypershiftoperator/deploy/base/role-prometheus.yaml deleted file mode 100644 index c2100527a..000000000 --- a/hypershiftoperator/deploy/base/role-prometheus.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - creationTimestamp: null - name: prometheus - namespace: hypershift -rules: -- apiGroups: - - "" - resources: - - services - - endpoints - - pods - verbs: - - get - - list - - watch diff --git a/hypershiftoperator/deploy/base/rolebinding-authentication-reader-for-authenticated-users.yaml b/hypershiftoperator/deploy/base/rolebinding-authentication-reader-for-authenticated-users.yaml deleted file mode 100644 index d24d33117..000000000 --- a/hypershiftoperator/deploy/base/rolebinding-authentication-reader-for-authenticated-users.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - creationTimestamp: null - name: authentication-reader-for-authenticated-users - namespace: kube-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: extension-apiserver-authentication-reader -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated diff --git a/hypershiftoperator/deploy/base/rolebinding-hypershift-operator.yaml b/hypershiftoperator/deploy/base/rolebinding-hypershift-operator.yaml deleted file mode 100644 index bc2ef6d20..000000000 --- a/hypershiftoperator/deploy/base/rolebinding-hypershift-operator.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - creationTimestamp: null - name: hypershift-operator - namespace: hypershift -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: hypershift-operator -subjects: -- kind: ServiceAccount - name: operator - namespace: hypershift diff --git a/hypershiftoperator/deploy/base/rolebinding-prometheus.yaml b/hypershiftoperator/deploy/base/rolebinding-prometheus.yaml deleted file mode 100644 index a250e573e..000000000 --- a/hypershiftoperator/deploy/base/rolebinding-prometheus.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - creationTimestamp: null - name: prometheus - namespace: hypershift -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: prometheus -subjects: -- kind: ServiceAccount - name: prometheus-k8s - namespace: openshift-monitoring diff --git a/hypershiftoperator/deploy/base/service-operator.yaml b/hypershiftoperator/deploy/base/service-operator.yaml deleted file mode 100644 index 31b081376..000000000 --- a/hypershiftoperator/deploy/base/service-operator.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - service.beta.openshift.io/serving-cert-secret-name: manager-serving-cert - creationTimestamp: null - labels: - name: operator - name: operator - namespace: hypershift -spec: - ports: - - name: metrics - port: 9393 - protocol: TCP - targetPort: metrics - - name: manager - port: 443 - protocol: TCP - targetPort: manager - selector: - name: operator - type: ClusterIP -status: - loadBalancer: {} diff --git a/hypershiftoperator/deploy/base/serviceaccount-external-dns.yaml b/hypershiftoperator/deploy/base/serviceaccount-external-dns.yaml deleted file mode 100644 index 1f6c9e39c..000000000 --- a/hypershiftoperator/deploy/base/serviceaccount-external-dns.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - creationTimestamp: null - name: external-dns - namespace: hypershift diff --git a/hypershiftoperator/deploy/base/serviceaccount-operator.yaml b/hypershiftoperator/deploy/base/serviceaccount-operator.yaml deleted file mode 100644 index 0702b7a69..000000000 --- a/hypershiftoperator/deploy/base/serviceaccount-operator.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - creationTimestamp: null - name: operator - namespace: hypershift diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-agentclusters.capi-provider.agent-install.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-agentclusters.capi-provider.agent-install.openshift.io.yaml deleted file mode 100644 index 6b333cf72..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-agentclusters.capi-provider.agent-install.openshift.io.yaml +++ /dev/null @@ -1,340 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: agentclusters.capi-provider.agent-install.openshift.io -spec: - group: capi-provider.agent-install.openshift.io - names: - kind: AgentCluster - listKind: AgentClusterList - plural: agentclusters - singular: agentcluster - scope: Namespaced - versions: - - deprecated: true - deprecationWarning: v1alpha1 is a deprecated version for AgentCluster - name: v1alpha1 - schema: - openAPIV3Schema: - description: AgentCluster is the Schema for the agentclusters API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentClusterSpec defines the desired state of AgentCluster - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - ignitionEndpoint: - description: IgnitionEndpoint store the data to of the custom ignition - endpoint. - properties: - caCertificateReference: - description: |- - CaCertificateReference is a reference to the secret containing CA certificate to be used - when contacting the URL via HTTPS. - properties: - name: - description: Name is the name of the secret containing the - CA certificate. - type: string - namespace: - description: Namespace is the namespace of the secret containing - the CA certificate. - type: string - required: - - name - - namespace - type: object - url: - description: Url store the URL of the custom ignition endpoint. - type: string - type: object - type: object - status: - description: AgentClusterStatus defines the observed state of AgentCluster - properties: - clusterDeploymentReference: - description: ClusterDeploymentRef is a reference to the associated - Hive ClusterDeployment. - properties: - name: - description: Name is unique within a namespace to reference a - clusterDeployment resource. - type: string - namespace: - description: Namespace defines the space within which the clusterDeployment - name must be unique. - type: string - type: object - conditions: - description: Conditions defines current service state of the ClusterDeployment. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains is a list of failure domain objects synced - from the infrastructure provider. - type: object - ready: - type: boolean - required: - - clusterDeploymentReference - type: object - type: object - served: true - storage: false - subresources: - status: {} - - name: v1beta1 - schema: - openAPIV3Schema: - description: AgentCluster is the Schema for the agentclusters API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentClusterSpec defines the desired state of AgentCluster - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - ignitionEndpoint: - description: IgnitionEndpoint store the data to of the custom ignition - endpoint. - properties: - caCertificateReference: - description: |- - CaCertificateReference is a reference to the secret containing CA certificate to be used - when contacting the URL via HTTPS. - properties: - name: - description: Name is the name of the secret containing the - CA certificate. - type: string - namespace: - description: Namespace is the namespace of the secret containing - the CA certificate. - type: string - required: - - name - - namespace - type: object - url: - description: Url store the URL of the custom ignition endpoint. - type: string - type: object - type: object - status: - description: AgentClusterStatus defines the observed state of AgentCluster - properties: - clusterDeploymentReference: - description: ClusterDeploymentRef is a reference to the associated - Hive ClusterDeployment. - properties: - name: - description: Name is unique within a namespace to reference a - clusterDeployment resource. - type: string - namespace: - description: Namespace defines the space within which the clusterDeployment - name must be unique. - type: string - type: object - conditions: - description: Conditions defines current service state of the ClusterDeployment. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains is a list of failure domain objects synced - from the infrastructure provider. - type: object - ready: - type: boolean - required: - - clusterDeploymentReference - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachines.capi-provider.agent-install.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachines.capi-provider.agent-install.openshift.io.yaml deleted file mode 100644 index 0616a2574..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachines.capi-provider.agent-install.openshift.io.yaml +++ /dev/null @@ -1,440 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: agentmachines.capi-provider.agent-install.openshift.io -spec: - group: capi-provider.agent-install.openshift.io - names: - kind: AgentMachine - listKind: AgentMachineList - plural: agentmachines - singular: agentmachine - scope: Namespaced - versions: - - deprecated: true - deprecationWarning: v1alpha1 is a deprecated version for AgentMachine - name: v1alpha1 - schema: - openAPIV3Schema: - description: AgentMachine is the Schema for the agentmachines API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentMachineSpec defines the desired state of AgentMachine - properties: - agentLabelSelector: - description: AgentLabelSelector contains the labels that must be set - on an Agent in order to be selected for this Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - providerID: - description: |- - ProviderID is the host's motherboard serial formatted as - agent://12345678-1234-1234-1234-123456789abc - type: string - type: object - status: - description: AgentMachineStatus defines the observed state of AgentMachine - properties: - addresses: - description: Addresses contains the Agent's associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - agentRef: - description: AgentRef is a reference to the Agent matched to the Machine. - properties: - name: - description: Name is unique within a namespace to reference an - agent resource. - type: string - namespace: - description: Namespace defines the space within which the agent - name must be unique. - type: string - type: object - conditions: - description: Conditions defines current service state of the AgentMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: false - subresources: - status: {} - - name: v1beta1 - schema: - openAPIV3Schema: - description: AgentMachine is the Schema for the agentmachines API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentMachineSpec defines the desired state of AgentMachine - properties: - agentLabelSelector: - description: AgentLabelSelector contains the labels that must be set - on an Agent in order to be selected for this Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - providerID: - description: |- - ProviderID is the host's motherboard serial formatted as - agent://12345678-1234-1234-1234-123456789abc - type: string - type: object - status: - description: AgentMachineStatus defines the observed state of AgentMachine - properties: - addresses: - description: Addresses contains the Agent's associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - agentRef: - description: AgentRef is a reference to the Agent matched to the Machine. - properties: - name: - description: Name is unique within a namespace to reference an - agent resource. - type: string - namespace: - description: Namespace defines the space within which the agent - name must be unique. - type: string - type: object - conditions: - description: Conditions defines current service state of the AgentMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachinetemplates.capi-provider.agent-install.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachinetemplates.capi-provider.agent-install.openshift.io.yaml deleted file mode 100644 index a0ea3c850..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-agentmachinetemplates.capi-provider.agent-install.openshift.io.yaml +++ /dev/null @@ -1,222 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: agentmachinetemplates.capi-provider.agent-install.openshift.io -spec: - group: capi-provider.agent-install.openshift.io - names: - categories: - - cluster-api - kind: AgentMachineTemplate - listKind: AgentMachineTemplateList - plural: agentmachinetemplates - shortNames: - - agentmt - singular: agentmachinetemplate - scope: Namespaced - versions: - - deprecated: true - deprecationWarning: v1alpha1 is a deprecated version for AgentMachineTemplate - name: v1alpha1 - schema: - openAPIV3Schema: - description: AgentMachineTemplate is the Schema for the agentmachinetemplates - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentMachineTemplateSpec defines the desired state of AgentMachineTemplate - properties: - template: - description: AgentMachineTemplateResource describes the data needed - to create an AgentMachine from a template - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - agentLabelSelector: - description: AgentLabelSelector contains the labels that must - be set on an Agent in order to be selected for this Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - providerID: - description: |- - ProviderID is the host's motherboard serial formatted as - agent://12345678-1234-1234-1234-123456789abc - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: false - - name: v1beta1 - schema: - openAPIV3Schema: - description: AgentMachineTemplate is the Schema for the agentmachinetemplates - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AgentMachineTemplateSpec defines the desired state of AgentMachineTemplate - properties: - template: - description: AgentMachineTemplateResource describes the data needed - to create an AgentMachine from a template - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - agentLabelSelector: - description: AgentLabelSelector contains the labels that must - be set on an Agent in order to be selected for this Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - providerID: - description: |- - ProviderID is the host's motherboard serial formatted as - agent://12345678-1234-1234-1234-123456789abc - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 413c7a003..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,218 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSClusterControllerIdentity - listKind: AWSClusterControllerIdentityList - plural: awsclustercontrolleridentities - shortNames: - - awsci - singular: awsclustercontrolleridentity - scope: Cluster - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - AWSClusterControllerIdentity is the Schema for the awsclustercontrolleridentities API - It is used to grant access to use Cluster API Provider AWS Controller credentials. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterControllerIdentity. - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - type: object - type: object - served: false - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: |- - AWSClusterControllerIdentity is the Schema for the awsclustercontrolleridentities API - It is used to grant access to use Cluster API Provider AWS Controller credentials. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterControllerIdentity. - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterroleidentities.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterroleidentities.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 629cb4b2a..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterroleidentities.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,336 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsclusterroleidentities.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSClusterRoleIdentity - listKind: AWSClusterRoleIdentityList - plural: awsclusterroleidentities - shortNames: - - awsri - singular: awsclusterroleidentity - scope: Cluster - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - AWSClusterRoleIdentity is the Schema for the awsclusterroleidentities API - It is used to assume a role using the provided sourceRef. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterRoleIdentity. - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - durationSeconds: - description: The duration, in seconds, of the role session before - it is renewed. - format: int32 - maximum: 43200 - minimum: 900 - type: integer - externalID: - description: |- - A unique identifier that might be required when you assume a role in another account. - If the administrator of the account to which the role belongs provided you with an - external ID, then provide that value in the ExternalId parameter. This value can be - any string, such as a passphrase or account number. A cross-account role is usually - set up to trust everyone in an account. Therefore, the administrator of the trusting - account might send an external ID to the administrator of the trusted account. That - way, only someone with the ID can assume the role, rather than everyone in the - account. For more information about the external ID, see How to Use an External ID - When Granting Access to Your AWS Resources to a Third Party in the IAM User Guide. - type: string - inlinePolicy: - description: An IAM policy as a JSON-encoded string that you want - to use as an inline session policy. - type: string - policyARNs: - description: |- - The Amazon Resource Names (ARNs) of the IAM managed policies that you want - to use as managed session policies. - The policies must exist in the same account as the role. - items: - type: string - type: array - roleARN: - description: The Amazon Resource Name (ARN) of the role to assume. - type: string - sessionName: - description: An identifier for the assumed role session - type: string - sourceIdentityRef: - description: |- - SourceIdentityRef is a reference to another identity which will be chained to do - role assumption. All identity types are accepted. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - required: - - roleARN - type: object - type: object - served: false - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: |- - AWSClusterRoleIdentity is the Schema for the awsclusterroleidentities API - It is used to assume a role using the provided sourceRef. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterRoleIdentity. - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - durationSeconds: - description: The duration, in seconds, of the role session before - it is renewed. - format: int32 - maximum: 43200 - minimum: 900 - type: integer - externalID: - description: |- - A unique identifier that might be required when you assume a role in another account. - If the administrator of the account to which the role belongs provided you with an - external ID, then provide that value in the ExternalId parameter. This value can be - any string, such as a passphrase or account number. A cross-account role is usually - set up to trust everyone in an account. Therefore, the administrator of the trusting - account might send an external ID to the administrator of the trusted account. That - way, only someone with the ID can assume the role, rather than everyone in the - account. For more information about the external ID, see How to Use an External ID - When Granting Access to Your AWS Resources to a Third Party in the IAM User Guide. - type: string - inlinePolicy: - description: An IAM policy as a JSON-encoded string that you want - to use as an inline session policy. - type: string - policyARNs: - description: |- - The Amazon Resource Names (ARNs) of the IAM managed policies that you want - to use as managed session policies. - The policies must exist in the same account as the role. - items: - type: string - type: array - roleARN: - description: The Amazon Resource Name (ARN) of the role to assume. - type: string - sessionName: - description: An identifier for the assumed role session - type: string - sourceIdentityRef: - description: |- - SourceIdentityRef is a reference to another identity which will be chained to do - role assumption. All identity types are accepted. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - required: - - roleARN - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 66b9e40a6..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,2918 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: awsclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSCluster - listKind: AWSClusterList - plural: awsclusters - shortNames: - - awsc - singular: awscluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AWSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for EC2 instances - jsonPath: .status.ready - name: Ready - type: string - - description: AWS VPC the cluster is using - jsonPath: .spec.network.vpc.id - name: VPC - type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint - name: Endpoint - priority: 1 - type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSCluster is the schema for Amazon EC2 based Kubernetes Cluster - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to AWS resources managed by the AWS provider, in addition to the - ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is a list of CIDR blocks allowed to access the bastion host. - They are set as ingress rules for the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: |- - AMI will use the specified AMI to boot the bastion. If not specified, - the AMI will default to one picked out in public space. - type: string - disableIngressRules: - description: |- - DisableIngressRules will ensure there are no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: |- - Enabled allows this provider to create a bastion host instance - with a public ip to access the VPC private network. - type: boolean - instanceType: - description: |- - InstanceType will use the specified instance type for the bastion. If not specified, - Cluster API Provider AWS will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for classic ELB health check target - default value is ClassicELBProtocolSSL - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer (defaults - to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied to - the control plane load balancer (defaults to discovered subnets - for managed VPCs or an empty set for unmanaged VPCs) - items: - type: string - type: array - type: object - identityRef: - description: |- - IdentityRef is a reference to an identity to be used when reconciling the managed control plane. - If no identity is specified, the default identity for this controller will be used. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system used to look - up machine images when a machine does not specify an AMI. When set, this - will be used for all cluster machines unless a machine specifies a - different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up machine images when - a machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base - OS and kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: |- - ImageLookupOrg is the AWS Organization ID to look up machine images when a - machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - cni: - description: CNI configuration - properties: - cniIngressRules: - description: |- - CNIIngressRules specify rules to apply to control plane and worker node security groups. - The source for the rule will be set to control plane and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for cluster instances - This is optional - if not provided new security groups will be created for the cluster - type: object - subnets: - description: Subnets configuration. - items: - description: SubnetSpec configures an AWS Subnet. - properties: - availabilityZone: - description: AvailabilityZone defines the availability zone - to use for this subnet in the cluster's region. - type: string - cidrBlock: - description: CidrBlock is the CIDR block to be used when - the provider creates a managed VPC. - type: string - id: - description: ID defines a unique identifier to reference - this resource. - type: string - ipv6CidrBlock: - description: |- - IPv6CidrBlock is the IPv6 CIDR block to be used when the provider creates a managed VPC. - A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: string - isIpv6: - description: |- - IsIPv6 defines the subnet as an IPv6 subnet. A subnet is IPv6 when it is associated with a VPC that has IPv6 enabled. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: boolean - isPublic: - description: IsPublic defines the subnet as a public subnet. - A subnet is public when it is associated with a route - table that has a route to an internet gateway. - type: boolean - natGatewayId: - description: |- - NatGatewayID is the NAT gateway id associated with the subnet. - Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet. - type: string - routeTableId: - description: RouteTableID is the routing table id associated - with the subnet. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the - resource. - type: object - type: object - type: array - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: |- - AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes: - Ordered - selects based on alphabetical order - Random - selects AZs randomly in a region - Defaults to Ordered - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: |- - AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that - should be used in a region when automatically creating subnets. If a region has more - than this number of AZs then this number of AZs will be picked randomly when creating - default subnets. Defaults to 3 - minimum: 1 - type: integer - cidrBlock: - description: |- - CidrBlock is the CIDR block to be used when the provider creates a managed VPC. - Defaults to 10.0.0.0/16. - type: string - id: - description: ID is the vpc-id of the VPC this provider should - use to create resources. - type: string - internetGatewayId: - description: InternetGatewayID is the id of the internet gateway - associated with the VPC. - type: string - ipv6: - description: |- - IPv6 contains ipv6 specific settings for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided by Amazon - when VPC has enabled IPv6. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - poolId: - description: PoolID is the IP pool which must be defined - in case of BYO IP is defined. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - region: - description: The AWS Region the cluster lives in. - type: string - s3Bucket: - description: |- - S3Bucket contains options to configure a supporting S3 bucket for this - cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: |- - ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, which will be allowed - to read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: |- - NodesIAMInstanceProfiles is a list of IAM instance profiles, which will be allowed to read - worker nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - required: - - controlPlaneIAMInstanceProfile - - name - - nodesIAMInstanceProfiles - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) - type: string - type: object - status: - description: AWSClusterStatus defines the observed state of AWSCluster. - properties: - bastion: - description: Instance describes an AWS instance. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - ebsOptimized: - description: Indicates whether the instance is optimized for Amazon - EBS I/O. - type: boolean - enaSupport: - description: Specifies whether enhanced networking with ENA is - enabled. - type: boolean - iamProfile: - description: The name of the IAM instance profile associated with - the instance, if applicable. - type: string - id: - type: string - imageId: - description: The ID of the AMI used to launch the instance. - type: string - instanceState: - description: The current state of the instance. - type: string - networkInterfaces: - description: Specifies ENIs attached to instance - items: - type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for - the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - privateIp: - description: The private IPv4 address assigned to the instance. - type: string - publicIp: - description: The public IPv4 address assigned to the instance, - if applicable. - type: string - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - subnetId: - description: The ID of the subnet of the instance. - type: string - tags: - additionalProperties: - type: string - description: The tags associated with the instance. - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - type: string - type: - description: The instance type. - type: string - userData: - description: |- - UserData is the raw data script passed to the instance which is run upon bootstrap. - This field must not be base64 encoded and should only be used when running a new instance. - type: string - volumeIDs: - description: IDs of the instance's volumes - items: - type: string - type: array - required: - - id - type: object - conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains is a slice of FailureDomains. - type: object - networkStatus: - description: NetworkStatus encapsulates AWS networking resources. - properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server classic - load balancer. - properties: - attributes: - description: Attributes defines extra attributes associated - with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - idleTimeout: - description: |- - IdleTimeout is time that the connection is allowed to be idle (no data - has been sent over the connection) before it is closed by the load balancer. - format: int64 - type: integer - type: object - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - healthChecks: - description: HealthCheck is the classic elb health check associated - with the load balancer. - properties: - healthyThreshold: - format: int64 - type: integer - interval: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - target: - type: string - timeout: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - unhealthyThreshold: - format: int64 - type: integer - required: - - healthyThreshold - - interval - - target - - timeout - - unhealthyThreshold - type: object - listeners: - description: Listeners is an array of classic elb listeners - associated with the load balancer. There must be at least - one. - items: - description: ClassicELBListener defines an AWS classic load - balancer listener. - properties: - instancePort: - format: int64 - type: integer - instanceProtocol: - description: ClassicELBProtocol defines listener protocols - for a classic load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ClassicELBProtocol defines listener protocols - for a classic load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - name: - description: |- - The name of the load balancer. It must be unique within the set of load balancers - defined in the region. It also serves as identifier. - type: string - scheme: - description: Scheme is the load balancer scheme, either internet-facing - or private. - type: string - securityGroupIds: - description: SecurityGroupIDs is an array of security groups - assigned to the load balancer. - items: - type: string - type: array - subnetIds: - description: SubnetIDs is an array of subnets in the VPC attached - to the load balancer. - items: - type: string - type: array - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the load - balancer. - type: object - type: object - securityGroups: - additionalProperties: - description: SecurityGroup defines an AWS security group. - properties: - id: - description: ID is a unique identifier. - type: string - ingressRule: - description: IngressRules is the inbound rules associated - with the security group. - items: - description: IngressRule defines an AWS ingress rule for - security groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - type: string - fromPort: - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - name: - description: Name is the security group name. - type: string - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the security - group. - type: object - required: - - id - - name - type: object - description: SecurityGroups is a map from the role/kind of the - security group to its unique name, if any. - type: object - type: object - ready: - default: false - type: boolean - required: - - ready - type: object - type: object - served: false - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster to which this AWSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for EC2 instances - jsonPath: .status.ready - name: Ready - type: string - - description: AWS VPC the cluster is using - jsonPath: .spec.network.vpc.id - name: VPC - type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint - name: Endpoint - priority: 1 - type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSCluster is the schema for Amazon EC2 based Kubernetes Cluster - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to AWS resources managed by the AWS provider, in addition to the - ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is a list of CIDR blocks allowed to access the bastion host. - They are set as ingress rules for the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: |- - AMI will use the specified AMI to boot the bastion. If not specified, - the AMI will default to one picked out in public space. - type: string - disableIngressRules: - description: |- - DisableIngressRules will ensure there are no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: |- - Enabled allows this provider to create a bastion host instance - with a public ip to access the VPC private network. - type: boolean - instanceType: - description: |- - InstanceType will use the specified instance type for the bastion. If not specified, - Cluster API Provider AWS will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. - properties: - additionalListeners: - description: |- - AdditionalListeners sets the additional listeners for the control plane load balancer. - This is only applicable to Network Load Balancer (NLB) types for the time being. - items: - description: |- - AdditionalListenerSpec defines the desired state of an - additional listener on an AWS load balancer. - properties: - healthCheck: - description: HealthCheck sets the optional custom health - check configuration to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - path: - description: |- - The destination for health checks on the targets when using the protocol HTTP or HTTPS, - otherwise the path will be ignored. - type: string - port: - description: |- - The port the load balancer uses when performing health checks for additional target groups. When - not specified this value will be set for the same of listener port. - type: string - protocol: - description: |- - The protocol to use to health check connect with the target. When not specified the Protocol - will be the same of the listener. - enum: - - TCP - - HTTP - - HTTPS - type: string - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - port: - description: Port sets the port for the additional listener. - format: int64 - maximum: 65535 - minimum: 1 - type: integer - protocol: - default: TCP - description: |- - Protocol sets the protocol for the additional listener. - Currently only TCP is supported. - enum: - - TCP - type: string - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - disableHostsRewrite: - description: |- - DisableHostsRewrite disabled the hair pinning issue solution that adds the NLB's address as 127.0.0.1 to the hosts - file of each instance. This is by default, false. - type: boolean - healthCheck: - description: HealthCheck sets custom health check configuration - to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for ELB health check target - default value is ELBProtocolSSL - enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the control - plane load balancer. - items: - description: IngressRule defines an AWS ingress rule for security - groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. Cannot - be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - - disabled - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: |- - PreserveClientIP lets the user control if preservation of client ips must be retained or not. - If this is enabled 6443 will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer (defaults - to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied to - the control plane load balancer (defaults to discovered subnets - for managed VPCs or an empty set for unmanaged VPCs) - items: - type: string - type: array - type: object - identityRef: - description: |- - IdentityRef is a reference to an identity to be used when reconciling the managed control plane. - If no identity is specified, the default identity for this controller will be used. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system used to look - up machine images when a machine does not specify an AMI. When set, this - will be used for all cluster machines unless a machine specifies a - different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up machine images when - a machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base - OS and kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: |- - ImageLookupOrg is the AWS Organization ID to look up machine images when a - machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an optional - set of ingress rules to add to the control plane - items: - description: IngressRule defines an AWS ingress rule for security - groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. Cannot - be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: |- - CNIIngressRules specify rules to apply to control plane and worker node security groups. - The source for the rule will be set to control plane and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for cluster instances - This is optional - if not provided new security groups will be created for the cluster - type: object - subnets: - description: Subnets configuration. - items: - description: SubnetSpec configures an AWS Subnet. - properties: - availabilityZone: - description: AvailabilityZone defines the availability zone - to use for this subnet in the cluster's region. - type: string - cidrBlock: - description: CidrBlock is the CIDR block to be used when - the provider creates a managed VPC. - type: string - id: - description: |- - ID defines a unique identifier to reference this resource. - If you're bringing your subnet, set the AWS subnet-id here, it must start with `subnet-`. - - - When the VPC is managed by CAPA, and you'd like the provider to create a subnet for you, - the id can be set to any placeholder value that does not start with `subnet-`; - upon creation, the subnet AWS identifier will be populated in the `ResourceID` field and - the `id` field is going to be used as the subnet name. If you specify a tag - called `Name`, it takes precedence. - type: string - ipv6CidrBlock: - description: |- - IPv6CidrBlock is the IPv6 CIDR block to be used when the provider creates a managed VPC. - A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: string - isIpv6: - description: |- - IsIPv6 defines the subnet as an IPv6 subnet. A subnet is IPv6 when it is associated with a VPC that has IPv6 enabled. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: boolean - isPublic: - description: IsPublic defines the subnet as a public subnet. - A subnet is public when it is associated with a route - table that has a route to an internet gateway. - type: boolean - natGatewayId: - description: |- - NatGatewayID is the NAT gateway id associated with the subnet. - Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet. - type: string - parentZoneName: - description: |- - ParentZoneName is the zone name where the current subnet's zone is tied when - the zone is a Local Zone. - - - The subnets in Local Zone or Wavelength Zone locations consume the ParentZoneName - to select the correct private route table to egress traffic to the internet. - type: string - resourceID: - description: |- - ResourceID is the subnet identifier from AWS, READ ONLY. - This field is populated when the provider manages the subnet. - type: string - routeTableId: - description: RouteTableID is the routing table id associated - with the subnet. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the - resource. - type: object - zoneType: - description: |- - ZoneType defines the type of the zone where the subnet is created. - - - The valid values are availability-zone, local-zone, and wavelength-zone. - - - Subnet with zone type availability-zone (regular) is always selected to create cluster - resources, like Load Balancers, NAT Gateways, Contol Plane nodes, etc. - - - Subnet with zone type local-zone or wavelength-zone is not eligible to automatically create - regular cluster resources. - - - The public subnet in availability-zone or local-zone is associated with regular public - route table with default route entry to a Internet Gateway. - - - The public subnet in wavelength-zone is associated with a carrier public - route table with default route entry to a Carrier Gateway. - - - The private subnet in the availability-zone is associated with a private route table with - the default route entry to a NAT Gateway created in that zone. - - - The private subnet in the local-zone or wavelength-zone is associated with a private route table with - the default route entry re-using the NAT Gateway in the Region (preferred from the - parent zone, the zone type availability-zone in the region, or first table available). - enum: - - availability-zone - - local-zone - - wavelength-zone - type: string - required: - - id - type: object - type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: |- - AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes: - Ordered - selects based on alphabetical order - Random - selects AZs randomly in a region - Defaults to Ordered - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: |- - AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that - should be used in a region when automatically creating subnets. If a region has more - than this number of AZs then this number of AZs will be picked randomly when creating - default subnets. Defaults to 3 - minimum: 1 - type: integer - carrierGatewayId: - description: |- - CarrierGatewayID is the id of the internet gateway associated with the VPC, - for carrier network (Wavelength Zones). - type: string - x-kubernetes-validations: - - message: Carrier Gateway ID must start with 'cagw-' - rule: self.startsWith('cagw-') - cidrBlock: - description: |- - CidrBlock is the CIDR block to be used when the provider creates a managed VPC. - Defaults to 10.0.0.0/16. - Mutually exclusive with IPAMPool. - type: string - emptyRoutesDefaultVPCSecurityGroup: - description: |- - EmptyRoutesDefaultVPCSecurityGroup specifies whether the default VPC security group ingress - and egress rules should be removed. - - - By default, when creating a VPC, AWS creates a security group called `default` with ingress and egress - rules that allow traffic from anywhere. The group could be used as a potential surface attack and - it's generally suggested that the group rules are removed or modified appropriately. - - - NOTE: This only applies when the VPC is managed by the Cluster API AWS controller. - type: boolean - id: - description: ID is the vpc-id of the VPC this provider should - use to create resources. - type: string - internetGatewayId: - description: InternetGatewayID is the id of the internet gateway - associated with the VPC. - type: string - ipamPool: - description: |- - IPAMPool defines the IPAMv4 pool to be used for VPC. - Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this provider - should use to create VPC. - type: string - netmaskLength: - description: |- - The netmask length of the IPv4 CIDR you want to allocate to VPC from - an Amazon VPC IP Address Manager (IPAM) pool. - Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: |- - IPv6 contains ipv6 specific settings for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: |- - CidrBlock is the CIDR block provided by Amazon when VPC has enabled IPv6. - Mutually exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - ipamPool: - description: |- - IPAMPool defines the IPAMv6 pool to be used for VPC. - Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this - provider should use to create VPC. - type: string - netmaskLength: - description: |- - The netmask length of the IPv4 CIDR you want to allocate to VPC from - an Amazon VPC IP Address Manager (IPAM) pool. - Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - poolId: - description: |- - PoolID is the IP pool which must be defined in case of BYO IP is defined. - Must be specified if CidrBlock is set. - Mutually exclusive with IPAMPool. - type: string - type: object - privateDnsHostnameTypeOnLaunch: - description: |- - PrivateDNSHostnameTypeOnLaunch is the type of hostname to assign to instances in the subnet at launch. - For IPv4-only and dual-stack (IPv4 and IPv6) subnets, an instance DNS name can be based on the instance IPv4 address (ip-name) - or the instance ID (resource-name). For IPv6 only subnets, an instance DNS name must be based on the instance ID (resource-name). - enum: - - ip-name - - resource-name - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - partition: - description: Partition is the AWS security partition being used. Defaults - to "aws" - type: string - region: - description: The AWS Region the cluster lives in. - type: string - s3Bucket: - description: |- - S3Bucket contains options to configure a supporting S3 bucket for this - cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - bestEffortDeleteObjects: - description: BestEffortDeleteObjects defines whether access/permission - errors during object deletion should be ignored. - type: boolean - controlPlaneIAMInstanceProfile: - description: |- - ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, which will be allowed - to read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: |- - NodesIAMInstanceProfiles is a list of IAM instance profiles, which will be allowed to read - worker nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - presignedURLDuration: - description: |- - PresignedURLDuration defines the duration for which presigned URLs are valid. - - - This is used to generate presigned URLs for S3 Bucket objects, which are used by - control-plane and worker nodes to fetch bootstrap data. - - - When enabled, the IAM instance profiles specified are not used. - type: string - required: - - name - type: object - secondaryControlPlaneLoadBalancer: - description: |- - SecondaryControlPlaneLoadBalancer is an additional load balancer that can be used for the control plane. - - - An example use case is to have a separate internal load balancer for internal traffic, - and a separate external load balancer for external traffic. - properties: - additionalListeners: - description: |- - AdditionalListeners sets the additional listeners for the control plane load balancer. - This is only applicable to Network Load Balancer (NLB) types for the time being. - items: - description: |- - AdditionalListenerSpec defines the desired state of an - additional listener on an AWS load balancer. - properties: - healthCheck: - description: HealthCheck sets the optional custom health - check configuration to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - path: - description: |- - The destination for health checks on the targets when using the protocol HTTP or HTTPS, - otherwise the path will be ignored. - type: string - port: - description: |- - The port the load balancer uses when performing health checks for additional target groups. When - not specified this value will be set for the same of listener port. - type: string - protocol: - description: |- - The protocol to use to health check connect with the target. When not specified the Protocol - will be the same of the listener. - enum: - - TCP - - HTTP - - HTTPS - type: string - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - port: - description: Port sets the port for the additional listener. - format: int64 - maximum: 65535 - minimum: 1 - type: integer - protocol: - default: TCP - description: |- - Protocol sets the protocol for the additional listener. - Currently only TCP is supported. - enum: - - TCP - type: string - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - disableHostsRewrite: - description: |- - DisableHostsRewrite disabled the hair pinning issue solution that adds the NLB's address as 127.0.0.1 to the hosts - file of each instance. This is by default, false. - type: boolean - healthCheck: - description: HealthCheck sets custom health check configuration - to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for ELB health check target - default value is ELBProtocolSSL - enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the control - plane load balancer. - items: - description: IngressRule defines an AWS ingress rule for security - groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. Cannot - be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - - disabled - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: |- - PreserveClientIP lets the user control if preservation of client ips must be retained or not. - If this is enabled 6443 will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer (defaults - to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied to - the control plane load balancer (defaults to discovered subnets - for managed VPCs or an empty set for unmanaged VPCs) - items: - type: string - type: array - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) - type: string - type: object - status: - description: AWSClusterStatus defines the observed state of AWSCluster. - properties: - bastion: - description: Instance describes an AWS instance. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - ebsOptimized: - description: Indicates whether the instance is optimized for Amazon - EBS I/O. - type: boolean - enaSupport: - description: Specifies whether enhanced networking with ENA is - enabled. - type: boolean - iamProfile: - description: The name of the IAM instance profile associated with - the instance, if applicable. - type: string - id: - type: string - imageId: - description: The ID of the AMI used to launch the instance. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for - the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: |- - Enables or disables the HTTP metadata endpoint on your instances. - - - If you specify a value of disabled, you cannot access your instance metadata. - - - Default: enabled - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: |- - The desired HTTP PUT response hop limit for instance metadata requests. The - larger the number, the further instance metadata requests can travel. - - - Default: 1 - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: |- - The state of token usage for your instance metadata requests. - - - If the state is optional, you can choose to retrieve instance metadata with - or without a session token on your request. If you retrieve the IAM role - credentials without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session token, the - version 2.0 role credentials are returned. - - - If the state is required, you must send a session token with any instance - metadata retrieval requests. In this state, retrieving the IAM role credentials - always returns the version 2.0 credentials; the version 1.0 credentials are - not available. - - - Default: optional - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: |- - Set to enabled to allow access to instance tags from the instance metadata. - Set to disabled to turn off access to instance tags from the instance metadata. - For more information, see Work with instance tags using the instance metadata - (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - - - Default: disabled - enum: - - enabled - - disabled - type: string - type: object - instanceState: - description: The current state of the instance. - type: string - networkInterfaces: - description: Specifies ENIs attached to instance - items: - type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for - the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - type: string - placementGroupPartition: - description: |- - PlacementGroupPartition is the partition number within the placement group in which to launch the instance. - This value is only valid if the placement group, referred in `PlacementGroupName`, was created with - strategy set to partition. - format: int64 - maximum: 7 - minimum: 1 - type: integer - privateDnsName: - description: PrivateDNSName is the options for the instance hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - AAAA records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object - privateIp: - description: The private IPv4 address assigned to the instance. - type: string - publicIPOnLaunch: - description: PublicIPOnLaunch is the option to associate a public - IP on instance launch - type: boolean - publicIp: - description: The public IPv4 address assigned to the instance, - if applicable. - type: string - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - subnetId: - description: The ID of the subnet of the instance. - type: string - tags: - additionalProperties: - type: string - description: The tags associated with the instance. - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - type: string - type: - description: The instance type. - type: string - userData: - description: |- - UserData is the raw data script passed to the instance which is run upon bootstrap. - This field must not be base64 encoded and should only be used when running a new instance. - type: string - volumeIDs: - description: IDs of the instance's volumes - items: - type: string - type: array - required: - - id - type: object - conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains is a slice of FailureDomains. - type: object - networkStatus: - description: NetworkStatus encapsulates AWS networking resources. - properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server load balancer. - properties: - arn: - description: |- - ARN of the load balancer. Unlike the ClassicLB, ARN is used mostly - to define and get it. - type: string - attributes: - description: ClassicElbAttributes defines extra attributes - associated with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - idleTimeout: - description: |- - IdleTimeout is time that the connection is allowed to be idle (no data - has been sent over the connection) before it is closed by the load balancer. - format: int64 - type: integer - type: object - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - elbAttributes: - additionalProperties: - type: string - description: ELBAttributes defines extra attributes associated - with v2 load balancers. - type: object - elbListeners: - description: ELBListeners is an array of listeners associated - with the load balancer. There must be at least one. - items: - description: Listener defines an AWS network load balancer - listener. - properties: - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - targetGroup: - description: |- - TargetGroupSpec specifies target group settings for a given listener. - This is created first, and the ARN is then passed to the listener. - properties: - name: - description: Name of the TargetGroup. Must be unique - over the same group of listeners. - maxLength: 32 - type: string - port: - description: Port is the exposed port - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - enum: - - tcp - - tls - - udp - - TCP - - TLS - - UDP - type: string - targetGroupHealthCheck: - description: HealthCheck is the elb health check - associated with the load balancer. - properties: - intervalSeconds: - format: int64 - type: integer - path: - type: string - port: - type: string - protocol: - type: string - thresholdCount: - format: int64 - type: integer - timeoutSeconds: - format: int64 - type: integer - unhealthyThresholdCount: - format: int64 - type: integer - type: object - vpcId: - type: string - required: - - name - - port - - protocol - - vpcId - type: object - required: - - port - - protocol - - targetGroup - type: object - type: array - healthChecks: - description: HealthCheck is the classic elb health check associated - with the load balancer. - properties: - healthyThreshold: - format: int64 - type: integer - interval: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - target: - type: string - timeout: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - unhealthyThreshold: - format: int64 - type: integer - required: - - healthyThreshold - - interval - - target - - timeout - - unhealthyThreshold - type: object - listeners: - description: ClassicELBListeners is an array of classic elb - listeners associated with the load balancer. There must - be at least one. - items: - description: ClassicELBListener defines an AWS classic load - balancer listener. - properties: - instancePort: - format: int64 - type: integer - instanceProtocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - loadBalancerType: - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - name: - description: |- - The name of the load balancer. It must be unique within the set of load balancers - defined in the region. It also serves as identifier. - type: string - scheme: - description: Scheme is the load balancer scheme, either internet-facing - or private. - type: string - securityGroupIds: - description: SecurityGroupIDs is an array of security groups - assigned to the load balancer. - items: - type: string - type: array - subnetIds: - description: SubnetIDs is an array of subnets in the VPC attached - to the load balancer. - items: - type: string - type: array - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the load - balancer. - type: object - type: object - natGatewaysIPs: - description: NatGatewaysIPs contains the public IPs of the NAT - Gateways - items: - type: string - type: array - secondaryAPIServerELB: - description: SecondaryAPIServerELB is the secondary Kubernetes - api server load balancer. - properties: - arn: - description: |- - ARN of the load balancer. Unlike the ClassicLB, ARN is used mostly - to define and get it. - type: string - attributes: - description: ClassicElbAttributes defines extra attributes - associated with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - idleTimeout: - description: |- - IdleTimeout is time that the connection is allowed to be idle (no data - has been sent over the connection) before it is closed by the load balancer. - format: int64 - type: integer - type: object - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - elbAttributes: - additionalProperties: - type: string - description: ELBAttributes defines extra attributes associated - with v2 load balancers. - type: object - elbListeners: - description: ELBListeners is an array of listeners associated - with the load balancer. There must be at least one. - items: - description: Listener defines an AWS network load balancer - listener. - properties: - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - targetGroup: - description: |- - TargetGroupSpec specifies target group settings for a given listener. - This is created first, and the ARN is then passed to the listener. - properties: - name: - description: Name of the TargetGroup. Must be unique - over the same group of listeners. - maxLength: 32 - type: string - port: - description: Port is the exposed port - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - enum: - - tcp - - tls - - udp - - TCP - - TLS - - UDP - type: string - targetGroupHealthCheck: - description: HealthCheck is the elb health check - associated with the load balancer. - properties: - intervalSeconds: - format: int64 - type: integer - path: - type: string - port: - type: string - protocol: - type: string - thresholdCount: - format: int64 - type: integer - timeoutSeconds: - format: int64 - type: integer - unhealthyThresholdCount: - format: int64 - type: integer - type: object - vpcId: - type: string - required: - - name - - port - - protocol - - vpcId - type: object - required: - - port - - protocol - - targetGroup - type: object - type: array - healthChecks: - description: HealthCheck is the classic elb health check associated - with the load balancer. - properties: - healthyThreshold: - format: int64 - type: integer - interval: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - target: - type: string - timeout: - description: |- - A Duration represents the elapsed time between two instants - as an int64 nanosecond count. The representation limits the - largest representable duration to approximately 290 years. - format: int64 - type: integer - unhealthyThreshold: - format: int64 - type: integer - required: - - healthyThreshold - - interval - - target - - timeout - - unhealthyThreshold - type: object - listeners: - description: ClassicELBListeners is an array of classic elb - listeners associated with the load balancer. There must - be at least one. - items: - description: ClassicELBListener defines an AWS classic load - balancer listener. - properties: - instancePort: - format: int64 - type: integer - instanceProtocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - loadBalancerType: - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - name: - description: |- - The name of the load balancer. It must be unique within the set of load balancers - defined in the region. It also serves as identifier. - type: string - scheme: - description: Scheme is the load balancer scheme, either internet-facing - or private. - type: string - securityGroupIds: - description: SecurityGroupIDs is an array of security groups - assigned to the load balancer. - items: - type: string - type: array - subnetIds: - description: SubnetIDs is an array of subnets in the VPC attached - to the load balancer. - items: - type: string - type: array - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the load - balancer. - type: object - type: object - securityGroups: - additionalProperties: - description: SecurityGroup defines an AWS security group. - properties: - id: - description: ID is a unique identifier. - type: string - ingressRule: - description: IngressRules is the inbound rules associated - with the security group. - items: - description: IngressRule defines an AWS ingress rule for - security groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP in - IP),"tcp", "udp", "icmp", and "58" (ICMPv6), "50" - (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - name: - description: Name is the security group name. - type: string - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the security - group. - type: object - required: - - id - - name - type: object - description: SecurityGroups is a map from the role/kind of the - security group to its unique name, if any. - type: object - type: object - ready: - default: false - type: boolean - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterstaticidentities.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterstaticidentities.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 23a262166..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclusterstaticidentities.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,238 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsclusterstaticidentities.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSClusterStaticIdentity - listKind: AWSClusterStaticIdentityList - plural: awsclusterstaticidentities - shortNames: - - awssi - singular: awsclusterstaticidentity - scope: Cluster - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - AWSClusterStaticIdentity is the Schema for the awsclusterstaticidentities API - It represents a reference to an AWS access key ID and secret access key, stored in a secret. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterStaticIdentity - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - secretRef: - description: |- - Reference to a secret containing the credentials. The secret should - contain the following data keys: - AccessKeyID: AKIAIOSFODNN7EXAMPLE - SecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - SessionToken: Optional - type: string - required: - - secretRef - type: object - type: object - served: false - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: |- - AWSClusterStaticIdentity is the Schema for the awsclusterstaticidentities API - It represents a reference to an AWS access key ID and secret access key, stored in a secret. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec for this AWSClusterStaticIdentity - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify which namespaces are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AWSClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - An empty selector indicates that AWSClusters cannot use this - AWSClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - secretRef: - description: |- - Reference to a secret containing the credentials. The secret should - contain the following data keys: - AccessKeyID: AKIAIOSFODNN7EXAMPLE - SecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY - SessionToken: Optional - type: string - required: - - secretRef - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index ce19c154c..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1625 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSClusterTemplate - listKind: AWSClusterTemplateList - plural: awsclustertemplates - shortNames: - - awsct - singular: awsclustertemplate - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of AWSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSClusterTemplate is the schema for Amazon EC2 based Kubernetes - Cluster Templates. - 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: AWSClusterTemplateSpec defines the desired state of AWSClusterTemplate. - properties: - template: - description: AWSClusterTemplateResource defines the desired state - of AWSClusterTemplate. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to AWS resources managed by the AWS provider, in addition to the - ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion - host. - properties: - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is a list of CIDR blocks allowed to access the bastion host. - They are set as ingress rules for the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: |- - AMI will use the specified AMI to boot the bastion. If not specified, - the AMI will default to one picked out in public space. - type: string - disableIngressRules: - description: |- - DisableIngressRules will ensure there are no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: |- - Enabled allows this provider to create a bastion host instance - with a public ip to access the VPC private network. - type: boolean - instanceType: - description: |- - InstanceType will use the specified instance type for the bastion. If not specified, - Cluster API Provider AWS will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for classic ELB health check target - default value is ClassicELBProtocolSSL - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer - (defaults to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied - to the control plane load balancer (defaults to discovered - subnets for managed VPCs or an empty set for unmanaged - VPCs) - items: - type: string - type: array - type: object - identityRef: - description: |- - IdentityRef is a reference to an identity to be used when reconciling the managed control plane. - If no identity is specified, the default identity for this controller will be used. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system used to look - up machine images when a machine does not specify an AMI. When set, this - will be used for all cluster machines unless a machine specifies a - different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up machine images when - a machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base - OS and kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: |- - ImageLookupOrg is the AWS Organization ID to look up machine images when a - machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to - AWS network. - properties: - cni: - description: CNI configuration - properties: - cniIngressRules: - description: |- - CNIIngressRules specify rules to apply to control plane and worker node security groups. - The source for the rule will be set to control plane and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress - rule for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the - protocol type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for cluster instances - This is optional - if not provided new security groups will be created for the cluster - type: object - subnets: - description: Subnets configuration. - items: - description: SubnetSpec configures an AWS Subnet. - properties: - availabilityZone: - description: AvailabilityZone defines the availability - zone to use for this subnet in the cluster's region. - type: string - cidrBlock: - description: CidrBlock is the CIDR block to be used - when the provider creates a managed VPC. - type: string - id: - description: ID defines a unique identifier to reference - this resource. - type: string - ipv6CidrBlock: - description: |- - IPv6CidrBlock is the IPv6 CIDR block to be used when the provider creates a managed VPC. - A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: string - isIpv6: - description: |- - IsIPv6 defines the subnet as an IPv6 subnet. A subnet is IPv6 when it is associated with a VPC that has IPv6 enabled. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: boolean - isPublic: - description: IsPublic defines the subnet as a public - subnet. A subnet is public when it is associated - with a route table that has a route to an internet - gateway. - type: boolean - natGatewayId: - description: |- - NatGatewayID is the NAT gateway id associated with the subnet. - Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet. - type: string - routeTableId: - description: RouteTableID is the routing table id - associated with the subnet. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - type: object - type: array - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: |- - AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes: - Ordered - selects based on alphabetical order - Random - selects AZs randomly in a region - Defaults to Ordered - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: |- - AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that - should be used in a region when automatically creating subnets. If a region has more - than this number of AZs then this number of AZs will be picked randomly when creating - default subnets. Defaults to 3 - minimum: 1 - type: integer - cidrBlock: - description: |- - CidrBlock is the CIDR block to be used when the provider creates a managed VPC. - Defaults to 10.0.0.0/16. - type: string - id: - description: ID is the vpc-id of the VPC this provider - should use to create resources. - type: string - internetGatewayId: - description: InternetGatewayID is the id of the internet - gateway associated with the VPC. - type: string - ipv6: - description: |- - IPv6 contains ipv6 specific settings for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided - by Amazon when VPC has enabled IPv6. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the - id of the egress only internet gateway associated - with an IPv6 enabled VPC. - type: string - poolId: - description: PoolID is the IP pool which must - be defined in case of BYO IP is defined. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - type: object - type: object - region: - description: The AWS Region the cluster lives in. - type: string - s3Bucket: - description: |- - S3Bucket contains options to configure a supporting S3 bucket for this - cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: |- - ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, which will be allowed - to read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: |- - NodesIAMInstanceProfiles is a list of IAM instance profiles, which will be allowed to read - worker nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - required: - - controlPlaneIAMInstanceProfile - - name - - nodesIAMInstanceProfiles - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the bastion host. Valid values are empty string (do not - use SSH keys), a valid SSH key name, or omitted (use the - default SSH key name) - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: false - storage: false - subresources: {} - - additionalPrinterColumns: - - description: Time duration since creation of AWSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSClusterTemplate is the schema for Amazon EC2 based Kubernetes - Cluster Templates. - 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: AWSClusterTemplateSpec defines the desired state of AWSClusterTemplate. - properties: - template: - description: AWSClusterTemplateResource defines the desired state - of AWSClusterTemplateResource. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to AWS resources managed by the AWS provider, in addition to the - ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion - host. - properties: - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is a list of CIDR blocks allowed to access the bastion host. - They are set as ingress rules for the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: |- - AMI will use the specified AMI to boot the bastion. If not specified, - the AMI will default to one picked out in public space. - type: string - disableIngressRules: - description: |- - DisableIngressRules will ensure there are no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: |- - Enabled allows this provider to create a bastion host instance - with a public ip to access the VPC private network. - type: boolean - instanceType: - description: |- - InstanceType will use the specified instance type for the bastion. If not specified, - Cluster API Provider AWS will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. - properties: - additionalListeners: - description: |- - AdditionalListeners sets the additional listeners for the control plane load balancer. - This is only applicable to Network Load Balancer (NLB) types for the time being. - items: - description: |- - AdditionalListenerSpec defines the desired state of an - additional listener on an AWS load balancer. - properties: - healthCheck: - description: HealthCheck sets the optional custom - health check configuration to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - path: - description: |- - The destination for health checks on the targets when using the protocol HTTP or HTTPS, - otherwise the path will be ignored. - type: string - port: - description: |- - The port the load balancer uses when performing health checks for additional target groups. When - not specified this value will be set for the same of listener port. - type: string - protocol: - description: |- - The protocol to use to health check connect with the target. When not specified the Protocol - will be the same of the listener. - enum: - - TCP - - HTTP - - HTTPS - type: string - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - port: - description: Port sets the port for the additional - listener. - format: int64 - maximum: 65535 - minimum: 1 - type: integer - protocol: - default: TCP - description: |- - Protocol sets the protocol for the additional listener. - Currently only TCP is supported. - enum: - - TCP - type: string - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - disableHostsRewrite: - description: |- - DisableHostsRewrite disabled the hair pinning issue solution that adds the NLB's address as 127.0.0.1 to the hosts - file of each instance. This is by default, false. - type: boolean - healthCheck: - description: HealthCheck sets custom health check configuration - to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for ELB health check target - default value is ELBProtocolSSL - enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the - control plane load balancer. - items: - description: IngressRule defines an AWS ingress rule - for security groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP - in IP),"tcp", "udp", "icmp", and "58" (ICMPv6), - "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load - balancer. The default type is classic. - enum: - - classic - - elb - - alb - - nlb - - disabled - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: |- - PreserveClientIP lets the user control if preservation of client ips must be retained or not. - If this is enabled 6443 will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer - (defaults to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied - to the control plane load balancer (defaults to discovered - subnets for managed VPCs or an empty set for unmanaged - VPCs) - items: - type: string - type: array - type: object - identityRef: - description: |- - IdentityRef is a reference to an identity to be used when reconciling the managed control plane. - If no identity is specified, the default identity for this controller will be used. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system used to look - up machine images when a machine does not specify an AMI. When set, this - will be used for all cluster machines unless a machine specifies a - different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up machine images when - a machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base - OS and kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: |- - ImageLookupOrg is the AWS Organization ID to look up machine images when a - machine does not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to - AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an - optional set of ingress rules to add to the control - plane - items: - description: IngressRule defines an AWS ingress rule - for security groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP - in IP),"tcp", "udp", "icmp", and "58" (ICMPv6), - "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: |- - CNIIngressRules specify rules to apply to control plane and worker node security groups. - The source for the rule will be set to control plane and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress - rule for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the - protocol type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for cluster instances - This is optional - if not provided new security groups will be created for the cluster - type: object - subnets: - description: Subnets configuration. - items: - description: SubnetSpec configures an AWS Subnet. - properties: - availabilityZone: - description: AvailabilityZone defines the availability - zone to use for this subnet in the cluster's region. - type: string - cidrBlock: - description: CidrBlock is the CIDR block to be used - when the provider creates a managed VPC. - type: string - id: - description: |- - ID defines a unique identifier to reference this resource. - If you're bringing your subnet, set the AWS subnet-id here, it must start with `subnet-`. - - - When the VPC is managed by CAPA, and you'd like the provider to create a subnet for you, - the id can be set to any placeholder value that does not start with `subnet-`; - upon creation, the subnet AWS identifier will be populated in the `ResourceID` field and - the `id` field is going to be used as the subnet name. If you specify a tag - called `Name`, it takes precedence. - type: string - ipv6CidrBlock: - description: |- - IPv6CidrBlock is the IPv6 CIDR block to be used when the provider creates a managed VPC. - A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: string - isIpv6: - description: |- - IsIPv6 defines the subnet as an IPv6 subnet. A subnet is IPv6 when it is associated with a VPC that has IPv6 enabled. - IPv6 is only supported in managed clusters, this field cannot be set on AWSCluster object. - type: boolean - isPublic: - description: IsPublic defines the subnet as a public - subnet. A subnet is public when it is associated - with a route table that has a route to an internet - gateway. - type: boolean - natGatewayId: - description: |- - NatGatewayID is the NAT gateway id associated with the subnet. - Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet. - type: string - parentZoneName: - description: |- - ParentZoneName is the zone name where the current subnet's zone is tied when - the zone is a Local Zone. - - - The subnets in Local Zone or Wavelength Zone locations consume the ParentZoneName - to select the correct private route table to egress traffic to the internet. - type: string - resourceID: - description: |- - ResourceID is the subnet identifier from AWS, READ ONLY. - This field is populated when the provider manages the subnet. - type: string - routeTableId: - description: RouteTableID is the routing table id - associated with the subnet. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - zoneType: - description: |- - ZoneType defines the type of the zone where the subnet is created. - - - The valid values are availability-zone, local-zone, and wavelength-zone. - - - Subnet with zone type availability-zone (regular) is always selected to create cluster - resources, like Load Balancers, NAT Gateways, Contol Plane nodes, etc. - - - Subnet with zone type local-zone or wavelength-zone is not eligible to automatically create - regular cluster resources. - - - The public subnet in availability-zone or local-zone is associated with regular public - route table with default route entry to a Internet Gateway. - - - The public subnet in wavelength-zone is associated with a carrier public - route table with default route entry to a Carrier Gateway. - - - The private subnet in the availability-zone is associated with a private route table with - the default route entry to a NAT Gateway created in that zone. - - - The private subnet in the local-zone or wavelength-zone is associated with a private route table with - the default route entry re-using the NAT Gateway in the Region (preferred from the - parent zone, the zone type availability-zone in the region, or first table available). - enum: - - availability-zone - - local-zone - - wavelength-zone - type: string - required: - - id - type: object - type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: |- - AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes: - Ordered - selects based on alphabetical order - Random - selects AZs randomly in a region - Defaults to Ordered - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: |- - AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that - should be used in a region when automatically creating subnets. If a region has more - than this number of AZs then this number of AZs will be picked randomly when creating - default subnets. Defaults to 3 - minimum: 1 - type: integer - carrierGatewayId: - description: |- - CarrierGatewayID is the id of the internet gateway associated with the VPC, - for carrier network (Wavelength Zones). - type: string - x-kubernetes-validations: - - message: Carrier Gateway ID must start with 'cagw-' - rule: self.startsWith('cagw-') - cidrBlock: - description: |- - CidrBlock is the CIDR block to be used when the provider creates a managed VPC. - Defaults to 10.0.0.0/16. - Mutually exclusive with IPAMPool. - type: string - emptyRoutesDefaultVPCSecurityGroup: - description: |- - EmptyRoutesDefaultVPCSecurityGroup specifies whether the default VPC security group ingress - and egress rules should be removed. - - - By default, when creating a VPC, AWS creates a security group called `default` with ingress and egress - rules that allow traffic from anywhere. The group could be used as a potential surface attack and - it's generally suggested that the group rules are removed or modified appropriately. - - - NOTE: This only applies when the VPC is managed by the Cluster API AWS controller. - type: boolean - id: - description: ID is the vpc-id of the VPC this provider - should use to create resources. - type: string - internetGatewayId: - description: InternetGatewayID is the id of the internet - gateway associated with the VPC. - type: string - ipamPool: - description: |- - IPAMPool defines the IPAMv4 pool to be used for VPC. - Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this - provider should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool - this provider should use to create VPC. - type: string - netmaskLength: - description: |- - The netmask length of the IPv4 CIDR you want to allocate to VPC from - an Amazon VPC IP Address Manager (IPAM) pool. - Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: |- - IPv6 contains ipv6 specific settings for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: |- - CidrBlock is the CIDR block provided by Amazon when VPC has enabled IPv6. - Mutually exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the - id of the egress only internet gateway associated - with an IPv6 enabled VPC. - type: string - ipamPool: - description: |- - IPAMPool defines the IPAMv6 pool to be used for VPC. - Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool - this provider should use to create VPC. - type: string - name: - description: Name is the name of the IPAM - pool this provider should use to create - VPC. - type: string - netmaskLength: - description: |- - The netmask length of the IPv4 CIDR you want to allocate to VPC from - an Amazon VPC IP Address Manager (IPAM) pool. - Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - poolId: - description: |- - PoolID is the IP pool which must be defined in case of BYO IP is defined. - Must be specified if CidrBlock is set. - Mutually exclusive with IPAMPool. - type: string - type: object - privateDnsHostnameTypeOnLaunch: - description: |- - PrivateDNSHostnameTypeOnLaunch is the type of hostname to assign to instances in the subnet at launch. - For IPv4-only and dual-stack (IPv4 and IPv6) subnets, an instance DNS name can be based on the instance IPv4 address (ip-name) - or the instance ID (resource-name). For IPv6 only subnets, an instance DNS name must be based on the instance ID (resource-name). - enum: - - ip-name - - resource-name - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - type: object - type: object - partition: - description: Partition is the AWS security partition being - used. Defaults to "aws" - type: string - region: - description: The AWS Region the cluster lives in. - type: string - s3Bucket: - description: |- - S3Bucket contains options to configure a supporting S3 bucket for this - cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - bestEffortDeleteObjects: - description: BestEffortDeleteObjects defines whether access/permission - errors during object deletion should be ignored. - type: boolean - controlPlaneIAMInstanceProfile: - description: |- - ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, which will be allowed - to read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: |- - NodesIAMInstanceProfiles is a list of IAM instance profiles, which will be allowed to read - worker nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - presignedURLDuration: - description: |- - PresignedURLDuration defines the duration for which presigned URLs are valid. - - - This is used to generate presigned URLs for S3 Bucket objects, which are used by - control-plane and worker nodes to fetch bootstrap data. - - - When enabled, the IAM instance profiles specified are not used. - type: string - required: - - name - type: object - secondaryControlPlaneLoadBalancer: - description: |- - SecondaryControlPlaneLoadBalancer is an additional load balancer that can be used for the control plane. - - - An example use case is to have a separate internal load balancer for internal traffic, - and a separate external load balancer for external traffic. - properties: - additionalListeners: - description: |- - AdditionalListeners sets the additional listeners for the control plane load balancer. - This is only applicable to Network Load Balancer (NLB) types for the time being. - items: - description: |- - AdditionalListenerSpec defines the desired state of an - additional listener on an AWS load balancer. - properties: - healthCheck: - description: HealthCheck sets the optional custom - health check configuration to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - path: - description: |- - The destination for health checks on the targets when using the protocol HTTP or HTTPS, - otherwise the path will be ignored. - type: string - port: - description: |- - The port the load balancer uses when performing health checks for additional target groups. When - not specified this value will be set for the same of listener port. - type: string - protocol: - description: |- - The protocol to use to health check connect with the target. When not specified the Protocol - will be the same of the listener. - enum: - - TCP - - HTTP - - HTTPS - type: string - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - port: - description: Port sets the port for the additional - listener. - format: int64 - maximum: 65535 - minimum: 1 - type: integer - protocol: - default: TCP - description: |- - Protocol sets the protocol for the additional listener. - Currently only TCP is supported. - enum: - - TCP - type: string - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups sets the security groups used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: |- - CrossZoneLoadBalancing enables the classic ELB cross availability zone balancing. - - - With cross-zone load balancing, each load balancer node for your Classic Load Balancer - distributes requests evenly across the registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load balancer node distributes requests evenly across - the registered instances in its Availability Zone only. - - - Defaults to false. - type: boolean - disableHostsRewrite: - description: |- - DisableHostsRewrite disabled the hair pinning issue solution that adds the NLB's address as 127.0.0.1 to the hosts - file of each instance. This is by default, false. - type: boolean - healthCheck: - description: HealthCheck sets custom health check configuration - to the API target group. - properties: - intervalSeconds: - description: |- - The approximate amount of time, in seconds, between health checks of an individual - target. - format: int64 - maximum: 300 - minimum: 5 - type: integer - thresholdCount: - description: |- - The number of consecutive health check successes required before considering - a target healthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - timeoutSeconds: - description: |- - The amount of time, in seconds, during which no response from a target means - a failed health check. - format: int64 - maximum: 120 - minimum: 2 - type: integer - unhealthyThresholdCount: - description: |- - The number of consecutive health check failures required before considering - a target unhealthy. - format: int64 - maximum: 10 - minimum: 2 - type: integer - type: object - healthCheckProtocol: - description: |- - HealthCheckProtocol sets the protocol type for ELB health check target - default value is ELBProtocolSSL - enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the - control plane load balancer. - items: - description: IngressRule defines an AWS ingress rule - for security groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP - in IP),"tcp", "udp", "icmp", and "58" (ICMPv6), - "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: |- - The security group role to allow access from. Cannot be specified with CidrBlocks. - The field will be combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load - balancer. The default type is classic. - enum: - - classic - - elb - - alb - - nlb - - disabled - type: string - name: - description: |- - Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique - within your set of load balancers for the region, must have a maximum of 32 characters, must - contain only alphanumeric characters or hyphens, and cannot begin or end with a hyphen. Once - set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: |- - PreserveClientIP lets the user control if preservation of client ips must be retained or not. - If this is enabled 6443 will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer - (defaults to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied - to the control plane load balancer (defaults to discovered - subnets for managed VPCs or an empty set for unmanaged - VPCs) - items: - type: string - type: array - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the bastion host. Valid values are empty string (do not - use SSH keys), a valid SSH key name, or omitted (use the - default SSH key name) - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsendpointservices.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsendpointservices.hypershift.openshift.io.yaml deleted file mode 100644 index 0c689109b..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsendpointservices.hypershift.openshift.io.yaml +++ /dev/null @@ -1,375 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsendpointservices.hypershift.openshift.io -spec: - group: hypershift.openshift.io - names: - kind: AWSEndpointService - listKind: AWSEndpointServiceList - plural: awsendpointservices - singular: awsendpointservice - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: AWSEndpointService specifies a request for an Endpoint Service - in AWS - 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: AWSEndpointServiceSpec defines the desired state of AWSEndpointService - properties: - networkLoadBalancerName: - description: The name of the NLB for which an Endpoint Service should - be configured - type: string - resourceTags: - description: Tags to apply to the EndpointService - items: - description: AWSResourceTag is a tag to apply to AWS resources created - for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - type: array - subnetIDs: - description: SubnetIDs is the list of subnet IDs to which guest nodes - can attach - items: - type: string - type: array - required: - - networkLoadBalancerName - type: object - status: - description: AWSEndpointServiceStatus defines the observed state of AWSEndpointService - properties: - conditions: - description: |- - Conditions contains details for the current state of the Endpoint Service - request If there is an error processing the request e.g. the NLB doesn't - exist, then the Available condition will be false, reason AWSErrorReason, - and the error reported in the message. - - - Current condition types are: "Available" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - dnsName: - description: 'Deprecated: Use DNSNames instead' - type: string - dnsNames: - description: DNSName are the names for the records created in the - hypershift private zone - items: - type: string - type: array - dnsZoneID: - description: DNSZoneID is ID for the hypershift private zone - type: string - endpointID: - description: EndpointID is the ID of the Endpoint created in the guest - VPC - type: string - endpointServiceName: - description: |- - EndpointServiceName is the name of the Endpoint Service created in the - management VPC - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSEndpointService specifies a request for an Endpoint Service - in AWS - 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: AWSEndpointServiceSpec defines the desired state of AWSEndpointService - properties: - networkLoadBalancerName: - description: The name of the NLB for which an Endpoint Service should - be configured - type: string - resourceTags: - description: Tags to apply to the EndpointService - items: - description: AWSResourceTag is a tag to apply to AWS resources created - for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - type: array - subnetIDs: - description: SubnetIDs is the list of subnet IDs to which guest nodes - can attach - items: - type: string - type: array - required: - - networkLoadBalancerName - type: object - status: - description: AWSEndpointServiceStatus defines the observed state of AWSEndpointService - properties: - conditions: - description: |- - Conditions contains details for the current state of the Endpoint Service - request If there is an error processing the request e.g. the NLB doesn't - exist, then the Available condition will be false, reason AWSErrorReason, - and the error reported in the message. - - - Current condition types are: "Available" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - dnsNames: - description: DNSName are the names for the records created in the - hypershift private zone - items: - type: string - type: array - dnsZoneID: - description: DNSZoneID is ID for the hypershift private zone - type: string - endpointID: - description: EndpointID is the ID of the Endpoint created in the guest - VPC - type: string - endpointServiceName: - description: |- - EndpointServiceName is the name of the Endpoint Service created in the - management VPC - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinepools.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinepools.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 68e3640fd..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinepools.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1147 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: awsmachinepools.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSMachinePool - listKind: AWSMachinePoolList - plural: awsmachinepools - shortNames: - - awsmp - singular: awsmachinepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Machine ready status - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Minimum instanes in ASG - jsonPath: .spec.minSize - name: MinSize - type: integer - - description: Maximum instanes in ASG - jsonPath: .spec.maxSize - name: MaxSize - type: integer - - description: Launch Template ID - jsonPath: .status.launchTemplateID - name: LaunchTemplate ID - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSMachinePool is the Schema for the awsmachinepools API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSMachinePoolSpec defines the desired state of AWSMachinePool. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. - type: object - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template and version - to use when an instance is launched. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instances. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS - resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - iamInstanceProfile: - description: |- - The name or the Amazon Resource Name (ARN) of the instance profile associated - with the IAM role for the instance. The instance profile contains the IAM - role. - type: string - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: |- - SSHKeyName is the name of the ssh key to attach to the instance. Valid values are empty string - (do not use SSH keys), a valid SSH key name, or omitted (use the default SSH key name) - type: string - versionNumber: - description: |- - VersionNumber is the version of the launch template that is applied. - Typically a new version is created when at least one of the following happens: - 1) A new launch template spec is applied. - 2) One or more parameters in an existing template is changed. - 3) A new AMI is discovered. - format: int64 - type: integer - type: object - capacityRebalance: - description: Enable or disable the capacity rebalance autoscaling - group feature - type: boolean - defaultCoolDown: - description: |- - The amount of time, in seconds, after a scaling activity completes before another scaling activity can start. - If no value is supplied by user a default value of 300 seconds is set - type: string - maxSize: - default: 1 - description: MaxSize defines the maximum size of the group. - format: int32 - minimum: 1 - type: integer - minSize: - default: 1 - description: MinSize defines the minimum size of the group. - format: int32 - minimum: 0 - type: integer - mixedInstancesPolicy: - description: MixedInstancesPolicy describes how multiple instance - types will be used by the ASG. - properties: - instancesDistribution: - description: InstancesDistribution to configure distribution of - On-Demand Instances and Spot Instances. - properties: - onDemandAllocationStrategy: - default: prioritized - description: OnDemandAllocationStrategy indicates how to allocate - instance types to fulfill On-Demand capacity. - enum: - - prioritized - type: string - onDemandBaseCapacity: - default: 0 - format: int64 - type: integer - onDemandPercentageAboveBaseCapacity: - default: 100 - format: int64 - type: integer - spotAllocationStrategy: - default: lowest-price - description: SpotAllocationStrategy indicates how to allocate - instances across Spot Instance pools. - enum: - - lowest-price - - capacity-optimized - type: string - type: object - overrides: - items: - description: |- - Overrides are used to override the instance type specified by the launch template with multiple - instance types that can be used to launch On-Demand Instances and Spot Instances. - properties: - instanceType: - type: string - required: - - instanceType - type: object - type: array - type: object - providerID: - description: ProviderID is the ARN of the associated ASG - type: string - providerIDList: - description: |- - ProviderIDList are the identification IDs of machine instances provided by the provider. - This field must match the provider IDs as seen on the node objects corresponding to a machine pool's machine instances. - items: - type: string - type: array - refreshPreferences: - description: RefreshPreferences describes set of preferences associated - with the instance refresh request. - properties: - instanceWarmup: - description: |- - The number of seconds until a newly launched instance is configured and ready - to use. During this time, the next replacement will not be initiated. - The default is to use the value for the health check grace period defined for the group. - format: int64 - type: integer - minHealthyPercentage: - description: |- - The amount of capacity as a percentage in ASG that must remain healthy - during an instance refresh. The default is 90. - format: int64 - type: integer - strategy: - description: |- - The strategy to use for the instance refresh. The only valid value is Rolling. - A rolling update is an update that is applied to all instances in an Auto - Scaling group until all instances have been updated. - type: string - type: object - subnets: - description: Subnets is an array of subnet configurations - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - required: - - awsLaunchTemplate - - maxSize - - minSize - type: object - status: - description: AWSMachinePoolStatus defines the observed state of AWSMachinePool. - properties: - asgStatus: - description: ASGStatus is a status string returned by the autoscaling - API. - type: string - conditions: - description: Conditions defines current service state of the AWSMachinePool. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - instances: - description: Instances contains the status for each instance in the - pool - items: - description: AWSMachinePoolInstanceStatus defines the status of - the AWSMachinePoolInstance. - properties: - instanceID: - description: InstanceID is the identification of the Machine - Instance within ASG - type: string - version: - description: Version defines the Kubernetes version for the - Machine Instance - type: string - type: object - type: array - launchTemplateID: - description: The ID of the launch template - type: string - launchTemplateVersion: - description: The version of the launch template - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas - format: int32 - type: integer - type: object - type: object - served: false - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Machine ready status - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Minimum instanes in ASG - jsonPath: .spec.minSize - name: MinSize - type: integer - - description: Maximum instanes in ASG - jsonPath: .spec.maxSize - name: MaxSize - type: integer - - description: Launch Template ID - jsonPath: .status.launchTemplateID - name: LaunchTemplate ID - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSMachinePool is the Schema for the awsmachinepools API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSMachinePoolSpec defines the desired state of AWSMachinePool. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. - type: object - availabilityZoneSubnetType: - description: AvailabilityZoneSubnetType specifies which type of subnets - to use when an availability zone is specified. - enum: - - public - - private - - all - type: string - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template and version - to use when an instance is launched. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instances. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS - resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - iamInstanceProfile: - description: |- - The name or the Amazon Resource Name (ARN) of the instance profile associated - with the IAM role for the instance. The instance profile contains the IAM - role. - type: string - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions defines the behavior for - applying metadata to instances. - properties: - httpEndpoint: - default: enabled - description: |- - Enables or disables the HTTP metadata endpoint on your instances. - - - If you specify a value of disabled, you cannot access your instance metadata. - - - Default: enabled - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: |- - The desired HTTP PUT response hop limit for instance metadata requests. The - larger the number, the further instance metadata requests can travel. - - - Default: 1 - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: |- - The state of token usage for your instance metadata requests. - - - If the state is optional, you can choose to retrieve instance metadata with - or without a session token on your request. If you retrieve the IAM role - credentials without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session token, the - version 2.0 role credentials are returned. - - - If the state is required, you must send a session token with any instance - metadata retrieval requests. In this state, retrieving the IAM role credentials - always returns the version 2.0 credentials; the version 1.0 credentials are - not available. - - - Default: optional - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: |- - Set to enabled to allow access to instance tags from the instance metadata. - Set to disabled to turn off access to instance tags from the instance metadata. - For more information, see Work with instance tags using the instance metadata - (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - - - Default: disabled - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - privateDnsName: - description: PrivateDNSName is the options for the instance hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - AAAA records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: |- - SSHKeyName is the name of the ssh key to attach to the instance. Valid values are empty string - (do not use SSH keys), a valid SSH key name, or omitted (use the default SSH key name) - type: string - versionNumber: - description: |- - VersionNumber is the version of the launch template that is applied. - Typically a new version is created when at least one of the following happens: - 1) A new launch template spec is applied. - 2) One or more parameters in an existing template is changed. - 3) A new AMI is discovered. - format: int64 - type: integer - type: object - capacityRebalance: - description: Enable or disable the capacity rebalance autoscaling - group feature - type: boolean - defaultCoolDown: - description: |- - The amount of time, in seconds, after a scaling activity completes before another scaling activity can start. - If no value is supplied by user a default value of 300 seconds is set - type: string - defaultInstanceWarmup: - description: |- - The amount of time, in seconds, until a new instance is considered to - have finished initializing and resource consumption to become stable - after it enters the InService state. - If no value is supplied by user a default value of 300 seconds is set - type: string - maxSize: - default: 1 - description: MaxSize defines the maximum size of the group. - format: int32 - minimum: 1 - type: integer - minSize: - default: 1 - description: MinSize defines the minimum size of the group. - format: int32 - minimum: 0 - type: integer - mixedInstancesPolicy: - description: MixedInstancesPolicy describes how multiple instance - types will be used by the ASG. - properties: - instancesDistribution: - description: InstancesDistribution to configure distribution of - On-Demand Instances and Spot Instances. - properties: - onDemandAllocationStrategy: - default: prioritized - description: OnDemandAllocationStrategy indicates how to allocate - instance types to fulfill On-Demand capacity. - enum: - - prioritized - - lowest-price - type: string - onDemandBaseCapacity: - default: 0 - format: int64 - type: integer - onDemandPercentageAboveBaseCapacity: - default: 100 - format: int64 - type: integer - spotAllocationStrategy: - default: lowest-price - description: SpotAllocationStrategy indicates how to allocate - instances across Spot Instance pools. - enum: - - lowest-price - - capacity-optimized - - capacity-optimized-prioritized - - price-capacity-optimized - type: string - type: object - overrides: - items: - description: |- - Overrides are used to override the instance type specified by the launch template with multiple - instance types that can be used to launch On-Demand Instances and Spot Instances. - properties: - instanceType: - type: string - required: - - instanceType - type: object - type: array - type: object - providerID: - description: ProviderID is the ARN of the associated ASG - type: string - providerIDList: - description: |- - ProviderIDList are the identification IDs of machine instances provided by the provider. - This field must match the provider IDs as seen on the node objects corresponding to a machine pool's machine instances. - items: - type: string - type: array - refreshPreferences: - description: RefreshPreferences describes set of preferences associated - with the instance refresh request. - properties: - disable: - description: |- - Disable, if true, disables instance refresh from triggering when new launch templates are detected. - This is useful in scenarios where ASG nodes are externally managed. - type: boolean - instanceWarmup: - description: |- - The number of seconds until a newly launched instance is configured and ready - to use. During this time, the next replacement will not be initiated. - The default is to use the value for the health check grace period defined for the group. - format: int64 - type: integer - minHealthyPercentage: - description: |- - The amount of capacity as a percentage in ASG that must remain healthy - during an instance refresh. The default is 90. - format: int64 - type: integer - strategy: - description: |- - The strategy to use for the instance refresh. The only valid value is Rolling. - A rolling update is an update that is applied to all instances in an Auto - Scaling group until all instances have been updated. - type: string - type: object - subnets: - description: Subnets is an array of subnet configurations - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - suspendProcesses: - description: |- - SuspendProcesses defines a list of processes to suspend for the given ASG. This is constantly reconciled. - If a process is removed from this list it will automatically be resumed. - properties: - all: - type: boolean - processes: - description: Processes defines the processes which can be enabled - or disabled individually. - properties: - addToLoadBalancer: - type: boolean - alarmNotification: - type: boolean - azRebalance: - type: boolean - healthCheck: - type: boolean - instanceRefresh: - type: boolean - launch: - type: boolean - replaceUnhealthy: - type: boolean - scheduledActions: - type: boolean - terminate: - type: boolean - type: object - type: object - required: - - awsLaunchTemplate - - maxSize - - minSize - type: object - status: - description: AWSMachinePoolStatus defines the observed state of AWSMachinePool. - properties: - asgStatus: - description: ASGStatus is a status string returned by the autoscaling - API. - type: string - conditions: - description: Conditions defines current service state of the AWSMachinePool. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - instances: - description: Instances contains the status for each instance in the - pool - items: - description: AWSMachinePoolInstanceStatus defines the status of - the AWSMachinePoolInstance. - properties: - instanceID: - description: InstanceID is the identification of the Machine - Instance within ASG - type: string - version: - description: Version defines the Kubernetes version for the - Machine Instance - type: string - type: object - type: array - launchTemplateID: - description: The ID of the launch template - type: string - launchTemplateVersion: - description: The version of the launch template - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 2242963cb..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1202 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: awsmachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSMachine - listKind: AWSMachineList - plural: awsmachines - shortNames: - - awsm - singular: awsmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AWSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: EC2 instance state - jsonPath: .status.instanceState - name: State - type: string - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EC2 instance ID - jsonPath: .spec.providerID - name: InstanceID - type: string - - description: Machine object which owns with this AWSMachine - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSMachine is the schema for Amazon EC2 machines. - 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: AWSMachineSpec defines the desired state of an Amazon EC2 - instance. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instance. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change the attached security groups might change too. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - arn: - description: |- - ARN of resource. - Deprecated: This field has no function and is going to be removed in the next release. - type: string - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. If both the AWSCluster and the AWSMachine specify the same tag name with different values, the - AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look up - an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: |- - CloudInit defines options related to the bootstrapping systems where - CloudInit is used. - properties: - insecureSkipSecretsManager: - description: |- - InsecureSkipSecretsManager, when set to true will not use AWS Secrets Manager - or AWS Systems Manager Parameter Store to ensure privacy of userdata. - By default, a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used to form - the complete secret - format: int32 - type: integer - secretPrefix: - description: |- - SecretPrefix is the prefix for the secret name. This is stored - temporarily, and deleted when the machine registers as a node against - the workload cluster. - type: string - secureSecretsBackend: - description: |- - SecureSecretsBackend, when set to parameter-store will utilize the AWS Systems Manager - Parameter Storage to distribute secrets. By default or with the value of secrets-manager, - will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - failureDomain: - description: |- - FailureDomain is the failure domain unique identifier this Machine should be attached to, as defined in Cluster API. - For this infrastructure provider, the ID is equivalent to an AWS Availability Zone. - If multiple subnets are matched for the availability zone, the first one returned is picked. - type: string - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance profile - to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition will be - used to generate bootstrap data. - enum: - - "2.3" - type: string - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use for - image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. Example: - m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: |- - NetworkInterfaces is a list of ENIs to associate with the instance. - A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for the - storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - publicIP: - description: |- - PublicIP specifies whether the instance should get a public IP. - Precedence for this setting is as follows: - 1. This field if set - 2. Cluster/flavor setting - 3. Subnet default - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options for - the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for the - volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is willing - to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - instance. Valid values are empty string (do not use SSH keys), a - valid SSH key name, or omitted (use the default SSH key name) - type: string - subnet: - description: |- - Subnet is a reference to the subnet to use for this instance. If not specified, - the cluster subnet will be used. - properties: - arn: - description: |- - ARN of resource. - Deprecated: This field has no function and is going to be removed in the next release. - type: string - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared or - single-tenant hardware. - enum: - - default - - dedicated - - host - type: string - uncompressedUserData: - description: |- - UncompressedUserData specify whether the user data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user data - user data stored in aws secret manager is always gzip-compressed. - type: boolean - required: - - instanceType - type: object - status: - description: AWSMachineStatus defines the observed state of AWSMachine. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the AWSMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - instanceState: - description: InstanceState is the state of the AWS instance for this - machine. - type: string - interruptible: - description: |- - Interruptible reports that this machine is using spot instances and can therefore be interrupted by CAPI when it receives a notice that the spot instance is to be terminated by AWS. - This will be set to true when SpotMarketOptions is not nil (i.e. this machine is using a spot instance). - type: boolean - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: false - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster to which this AWSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: EC2 instance state - jsonPath: .status.instanceState - name: State - type: string - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EC2 instance ID - jsonPath: .spec.providerID - name: InstanceID - type: string - - description: Machine object which owns with this AWSMachine - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSMachine is the schema for Amazon EC2 machines. - 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: AWSMachineSpec defines the desired state of an Amazon EC2 - instance. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instance. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change the attached security groups might change too. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. If both the AWSCluster and the AWSMachine specify the same tag name with different values, the - AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look up - an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: |- - CloudInit defines options related to the bootstrapping systems where - CloudInit is used. - properties: - insecureSkipSecretsManager: - description: |- - InsecureSkipSecretsManager, when set to true will not use AWS Secrets Manager - or AWS Systems Manager Parameter Store to ensure privacy of userdata. - By default, a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used to form - the complete secret - format: int32 - type: integer - secretPrefix: - description: |- - SecretPrefix is the prefix for the secret name. This is stored - temporarily, and deleted when the machine registers as a node against - the workload cluster. - type: string - secureSecretsBackend: - description: |- - SecureSecretsBackend, when set to parameter-store will utilize the AWS Systems Manager - Parameter Storage to distribute secrets. By default or with the value of secrets-manager, - will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance profile - to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - proxy: - description: |- - Proxy defines proxy settings for Ignition. - Only valid for Ignition versions 3.1 and above. - properties: - httpProxy: - description: |- - HTTPProxy is the HTTP proxy to use for Ignition. - A single URL that specifies the proxy server to use for HTTP and HTTPS requests, - unless overridden by the HTTPSProxy or NoProxy options. - type: string - httpsProxy: - description: |- - HTTPSProxy is the HTTPS proxy to use for Ignition. - A single URL that specifies the proxy server to use for HTTPS requests, - unless overridden by the NoProxy option. - type: string - noProxy: - description: |- - NoProxy is the list of domains to not proxy for Ignition. - Specifies a list of strings to hosts that should be excluded from proxying. - - - Each value is represented by: - - An IP address prefix (1.2.3.4) - - An IP address prefix in CIDR notation (1.2.3.4/8) - - A domain name - - A domain name matches that name and all subdomains - - A domain name with a leading . matches subdomains only - - A special DNS label (*), indicates that no proxying should be done - - - An IP address prefix and domain name can also include a literal port number (1.2.3.4:80). - items: - description: IgnitionNoProxy defines the list of domains - to not proxy for Ignition. - maxLength: 2048 - type: string - maxItems: 64 - type: array - type: object - storageType: - default: ClusterObjectStore - description: |- - StorageType defines how to store the boostrap user data for Ignition. - This can be used to instruct Ignition from where to fetch the user data to bootstrap an instance. - - - When omitted, the storage option will default to ClusterObjectStore. - - - When set to "ClusterObjectStore", if the capability is available and a Cluster ObjectStore configuration - is correctly provided in the Cluster object (under .spec.s3Bucket), - an object store will be used to store bootstrap user data. - - - When set to "UnencryptedUserData", EC2 Instance User Data will be used to store the machine bootstrap user data, unencrypted. - This option is considered less secure than others as user data may contain sensitive informations (keys, certificates, etc.) - and users with ec2:DescribeInstances permission or users running pods - that can access the ec2 metadata service have access to this sensitive information. - So this is only to be used at ones own risk, and only when other more secure options are not viable. - enum: - - ClusterObjectStore - - UnencryptedUserData - type: string - tls: - description: |- - TLS defines TLS settings for Ignition. - Only valid for Ignition versions 3.1 and above. - properties: - certificateAuthorities: - description: |- - CASources defines the list of certificate authorities to use for Ignition. - The value is the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. - Supported schemes are http, https, tftp, s3, arn, gs, and `data` (RFC 2397) URL scheme. - items: - description: IgnitionCASource defines the source of the - certificate authority to use for Ignition. - maxLength: 65536 - type: string - maxItems: 64 - type: array - type: object - version: - default: "2.3" - description: Version defines which version of Ignition will be - used to generate bootstrap data. - enum: - - "2.3" - - "3.0" - - "3.1" - - "3.2" - - "3.3" - - "3.4" - type: string - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use for - image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for the - EC2 instance. - properties: - httpEndpoint: - default: enabled - description: |- - Enables or disables the HTTP metadata endpoint on your instances. - - - If you specify a value of disabled, you cannot access your instance metadata. - - - Default: enabled - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: |- - The desired HTTP PUT response hop limit for instance metadata requests. The - larger the number, the further instance metadata requests can travel. - - - Default: 1 - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: |- - The state of token usage for your instance metadata requests. - - - If the state is optional, you can choose to retrieve instance metadata with - or without a session token on your request. If you retrieve the IAM role - credentials without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session token, the - version 2.0 role credentials are returned. - - - If the state is required, you must send a session token with any instance - metadata retrieval requests. In this state, retrieving the IAM role credentials - always returns the version 2.0 credentials; the version 1.0 credentials are - not available. - - - Default: optional - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: |- - Set to enabled to allow access to instance tags from the instance metadata. - Set to disabled to turn off access to instance tags from the instance metadata. - For more information, see Work with instance tags using the instance metadata - (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - - - Default: disabled - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. Example: - m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: |- - NetworkInterfaces is a list of ENIs to associate with the instance. - A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for the - storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - type: string - placementGroupPartition: - description: |- - PlacementGroupPartition is the partition number within the placement group in which to launch the instance. - This value is only valid if the placement group, referred in `PlacementGroupName`, was created with - strategy set to partition. - format: int64 - maximum: 7 - minimum: 1 - type: integer - privateDnsName: - description: PrivateDNSName is the options for the instance hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates whether - to respond to DNS queries for instance hostnames with DNS AAAA - records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether to - respond to DNS queries for instance hostnames with DNS A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - publicIP: - description: |- - PublicIP specifies whether the instance should get a public IP. - Precedence for this setting is as follows: - 1. This field if set - 2. Cluster/flavor setting - 3. Subnet default - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options for - the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for the - volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, etc...). - type: string - required: - - size - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for the node. - This is optional - if not provided security groups from the cluster will be used. - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is willing - to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - instance. Valid values are empty string (do not use SSH keys), a - valid SSH key name, or omitted (use the default SSH key name) - type: string - subnet: - description: |- - Subnet is a reference to the subnet to use for this instance. If not specified, - the cluster subnet will be used. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared or - single-tenant hardware. - enum: - - default - - dedicated - - host - type: string - uncompressedUserData: - description: |- - UncompressedUserData specify whether the user data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user data - user data stored in aws secret manager is always gzip-compressed. - type: boolean - required: - - instanceType - type: object - status: - description: AWSMachineStatus defines the observed state of AWSMachine. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the AWSMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - instanceState: - description: InstanceState is the state of the AWS instance for this - machine. - type: string - interruptible: - description: |- - Interruptible reports that this machine is using spot instances and can therefore be interrupted by CAPI when it receives a notice that the spot instance is to be terminated by AWS. - This will be set to true when SpotMarketOptions is not nil (i.e. this machine is using a spot instance). - type: boolean - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index d30c52c4c..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-awsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1038 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: awsmachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSMachineTemplate - listKind: AWSMachineTemplateList - plural: awsmachinetemplates - shortNames: - - awsmt - singular: awsmachinetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSMachineTemplate is the schema for the Amazon EC2 Machine Templates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSMachineTemplateSpec defines the desired state of AWSMachineTemplate. - properties: - template: - description: AWSMachineTemplateResource describes the data needed - to create am AWSMachine from a template. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instance. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change the attached security groups might change too. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - arn: - description: |- - ARN of resource. - Deprecated: This field has no function and is going to be removed in the next release. - type: string - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. If both the AWSCluster and the AWSMachine specify the same tag name with different values, the - AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to - create the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will - look up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: |- - CloudInit defines options related to the bootstrapping systems where - CloudInit is used. - properties: - insecureSkipSecretsManager: - description: |- - InsecureSkipSecretsManager, when set to true will not use AWS Secrets Manager - or AWS Systems Manager Parameter Store to ensure privacy of userdata. - By default, a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used - to form the complete secret - format: int32 - type: integer - secretPrefix: - description: |- - SecretPrefix is the prefix for the secret name. This is stored - temporarily, and deleted when the machine registers as a node against - the workload cluster. - type: string - secureSecretsBackend: - description: |- - SecureSecretsBackend, when set to parameter-store will utilize the AWS Systems Manager - Parameter Storage to distribute secrets. By default or with the value of secrets-manager, - will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - failureDomain: - description: |- - FailureDomain is the failure domain unique identifier this Machine should be attached to, as defined in Cluster API. - For this infrastructure provider, the ID is equivalent to an AWS Availability Zone. - If multiple subnets are matched for the availability zone, the first one returned is picked. - type: string - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance - profile to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition - will be used to generate bootstrap data. - enum: - - "2.3" - type: string - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - use for image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: |- - NetworkInterfaces is a list of ENIs to associate with the instance. - A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage - volumes. - items: - description: Volume encapsulates the configuration options - for the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should - be encrypted or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - publicIP: - description: |- - PublicIP specifies whether the instance should get a public IP. - Precedence for this setting is as follows: - 1. This field if set - 2. Cluster/flavor setting - 3. Subnet default - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user - is willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the instance. Valid values are empty string (do not use - SSH keys), a valid SSH key name, or omitted (use the default - SSH key name) - type: string - subnet: - description: |- - Subnet is a reference to the subnet to use for this instance. If not specified, - the cluster subnet will be used. - properties: - arn: - description: |- - ARN of resource. - Deprecated: This field has no function and is going to be removed in the next release. - type: string - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - enum: - - default - - dedicated - - host - type: string - uncompressedUserData: - description: |- - UncompressedUserData specify whether the user data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user data - user data stored in aws secret manager is always gzip-compressed. - type: boolean - required: - - instanceType - type: object - required: - - spec - type: object - required: - - template - type: object - status: - description: AWSMachineTemplateStatus defines a status for an AWSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined in: - https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md - type: object - type: object - type: object - served: false - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSMachineTemplate is the schema for the Amazon EC2 Machine Templates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AWSMachineTemplateSpec defines the desired state of AWSMachineTemplate. - properties: - template: - description: AWSMachineTemplateResource describes the data needed - to create am AWSMachine from a template. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - additionalSecurityGroups: - description: |- - AdditionalSecurityGroups is an array of references to security groups that should be applied to the - instance. These security groups would be set in addition to any security groups defined - at the cluster level or in the actuator. It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change the attached security groups might change too. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - AWS provider. If both the AWSCluster and the AWSMachine specify the same tag name with different values, the - AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to - create the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will - look up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: |- - CloudInit defines options related to the bootstrapping systems where - CloudInit is used. - properties: - insecureSkipSecretsManager: - description: |- - InsecureSkipSecretsManager, when set to true will not use AWS Secrets Manager - or AWS Systems Manager Parameter Store to ensure privacy of userdata. - By default, a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used - to form the complete secret - format: int32 - type: integer - secretPrefix: - description: |- - SecretPrefix is the prefix for the secret name. This is stored - temporarily, and deleted when the machine registers as a node against - the workload cluster. - type: string - secureSecretsBackend: - description: |- - SecureSecretsBackend, when set to parameter-store will utilize the AWS Systems Manager - Parameter Storage to distribute secrets. By default or with the value of secrets-manager, - will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance - profile to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - proxy: - description: |- - Proxy defines proxy settings for Ignition. - Only valid for Ignition versions 3.1 and above. - properties: - httpProxy: - description: |- - HTTPProxy is the HTTP proxy to use for Ignition. - A single URL that specifies the proxy server to use for HTTP and HTTPS requests, - unless overridden by the HTTPSProxy or NoProxy options. - type: string - httpsProxy: - description: |- - HTTPSProxy is the HTTPS proxy to use for Ignition. - A single URL that specifies the proxy server to use for HTTPS requests, - unless overridden by the NoProxy option. - type: string - noProxy: - description: |- - NoProxy is the list of domains to not proxy for Ignition. - Specifies a list of strings to hosts that should be excluded from proxying. - - - Each value is represented by: - - An IP address prefix (1.2.3.4) - - An IP address prefix in CIDR notation (1.2.3.4/8) - - A domain name - - A domain name matches that name and all subdomains - - A domain name with a leading . matches subdomains only - - A special DNS label (*), indicates that no proxying should be done - - - An IP address prefix and domain name can also include a literal port number (1.2.3.4:80). - items: - description: IgnitionNoProxy defines the list of - domains to not proxy for Ignition. - maxLength: 2048 - type: string - maxItems: 64 - type: array - type: object - storageType: - default: ClusterObjectStore - description: |- - StorageType defines how to store the boostrap user data for Ignition. - This can be used to instruct Ignition from where to fetch the user data to bootstrap an instance. - - - When omitted, the storage option will default to ClusterObjectStore. - - - When set to "ClusterObjectStore", if the capability is available and a Cluster ObjectStore configuration - is correctly provided in the Cluster object (under .spec.s3Bucket), - an object store will be used to store bootstrap user data. - - - When set to "UnencryptedUserData", EC2 Instance User Data will be used to store the machine bootstrap user data, unencrypted. - This option is considered less secure than others as user data may contain sensitive informations (keys, certificates, etc.) - and users with ec2:DescribeInstances permission or users running pods - that can access the ec2 metadata service have access to this sensitive information. - So this is only to be used at ones own risk, and only when other more secure options are not viable. - enum: - - ClusterObjectStore - - UnencryptedUserData - type: string - tls: - description: |- - TLS defines TLS settings for Ignition. - Only valid for Ignition versions 3.1 and above. - properties: - certificateAuthorities: - description: |- - CASources defines the list of certificate authorities to use for Ignition. - The value is the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. - Supported schemes are http, https, tftp, s3, arn, gs, and `data` (RFC 2397) URL scheme. - items: - description: IgnitionCASource defines the source - of the certificate authority to use for Ignition. - maxLength: 65536 - type: string - maxItems: 64 - type: array - type: object - version: - default: "2.3" - description: Version defines which version of Ignition - will be used to generate bootstrap data. - enum: - - "2.3" - - "3.0" - - "3.1" - - "3.2" - - "3.3" - - "3.4" - type: string - type: object - imageLookupBaseOS: - description: |- - ImageLookupBaseOS is the name of the base operating system to use for - image lookup the AMI is not set. - type: string - imageLookupFormat: - description: |- - ImageLookupFormat is the AMI naming format to look up the image for this - machine It will be ignored if an explicit AMI is set. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the base OS and - kubernetes version, respectively. The BaseOS will be the value in - ImageLookupBaseOS or ubuntu (the default), and the kubernetes version as - defined by the packages produced by kubernetes/release without v as a - prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, the default - image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* will end up - searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* for a - Machine that is targeting kubernetes v1.18.0 and the ubuntu base OS. See - also: https://golang.org/pkg/text/template/ - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - use for image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options - for the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: |- - Enables or disables the HTTP metadata endpoint on your instances. - - - If you specify a value of disabled, you cannot access your instance metadata. - - - Default: enabled - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: |- - The desired HTTP PUT response hop limit for instance metadata requests. The - larger the number, the further instance metadata requests can travel. - - - Default: 1 - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: |- - The state of token usage for your instance metadata requests. - - - If the state is optional, you can choose to retrieve instance metadata with - or without a session token on your request. If you retrieve the IAM role - credentials without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session token, the - version 2.0 role credentials are returned. - - - If the state is required, you must send a session token with any instance - metadata retrieval requests. In this state, retrieving the IAM role credentials - always returns the version 2.0 credentials; the version 1.0 credentials are - not available. - - - Default: optional - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: |- - Set to enabled to allow access to instance tags from the instance metadata. - Set to disabled to turn off access to instance tags from the instance metadata. - For more information, see Work with instance tags using the instance metadata - (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - - - Default: disabled - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: |- - NetworkInterfaces is a list of ENIs to associate with the instance. - A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage - volumes. - items: - description: Volume encapsulates the configuration options - for the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should - be encrypted or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the - placement group in which to launch the instance. - type: string - placementGroupPartition: - description: |- - PlacementGroupPartition is the partition number within the placement group in which to launch the instance. - This value is only valid if the placement group, referred in `PlacementGroupName`, was created with - strategy set to partition. - format: int64 - maximum: 7 - minimum: 1 - type: integer - privateDnsName: - description: PrivateDNSName is the options for the instance - hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates - whether to respond to DNS queries for instance hostnames - with DNS AAAA records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether - to respond to DNS queries for instance hostnames with - DNS A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - publicIP: - description: |- - PublicIP specifies whether the instance should get a public IP. - Precedence for this setting is as follows: - 1. This field if set - 2. Cluster/flavor setting - 3. Subnet default - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: |- - SecurityGroupOverrides is an optional set of security groups to use for the node. - This is optional - if not provided security groups from the cluster will be used. - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user - is willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the instance. Valid values are empty string (do not use - SSH keys), a valid SSH key name, or omitted (use the default - SSH key name) - type: string - subnet: - description: |- - Subnet is a reference to the subnet to use for this instance. If not specified, - the cluster subnet will be used. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - enum: - - default - - dedicated - - host - type: string - uncompressedUserData: - description: |- - UncompressedUserData specify whether the user data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user data - user data stored in aws secret manager is always gzip-compressed. - type: boolean - required: - - instanceType - type: object - required: - - spec - type: object - required: - - template - type: object - status: - description: AWSMachineTemplateStatus defines a status for an AWSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined in: - https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md - type: object - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusteridentities.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusteridentities.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index c72d23012..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusteridentities.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,229 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azureclusteridentities.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureClusterIdentity - listKind: AzureClusterIdentityList - plural: azureclusteridentities - singular: azureclusteridentity - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Type of AzureClusterIdentity - jsonPath: .spec.type - name: Type - type: string - - description: Time duration since creation of this AzureClusterIdentity - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureClusterIdentity is the Schema for the azureclustersidentities - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureClusterIdentitySpec defines the parameters that are - used to create an AzureIdentity. - properties: - allowedNamespaces: - description: |- - AllowedNamespaces is used to identify the namespaces the clusters are allowed to use the identity from. - Namespaces can be selected either using an array of namespaces or with label selector. - An empty allowedNamespaces object indicates that AzureClusters can use this identity from any namespace. - If this object is nil, no namespaces will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with Selector to use the identity. - nullable: true - properties: - list: - description: A nil or empty list indicates that AzureCluster cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: |- - Selector is a selector of namespaces that AzureCluster can - use this Identity from. This is a standard Kubernetes LabelSelector, - a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. - - - A nil or empty selector indicates that AzureCluster cannot use this - AzureClusterIdentity from any namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - clientID: - description: |- - ClientID is the service principal client ID. - Both User Assigned MSI and SP can use this field. - type: string - clientSecret: - description: ClientSecret is a secret reference which should contain - either a Service Principal password or certificate secret. - properties: - name: - description: name is unique within a namespace to reference a - secret resource. - type: string - namespace: - description: namespace defines the space within which the secret - name must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - resourceID: - description: |- - ResourceID is the Azure resource ID for the User Assigned MSI resource. - Only applicable when type is UserAssignedMSI. - type: string - tenantID: - description: TenantID is the service principal primary tenant id. - type: string - type: - description: |- - Type is the type of Azure Identity used. - ServicePrincipal, ServicePrincipalCertificate, UserAssignedMSI, ManualServicePrincipal or WorkloadIdentity. - enum: - - ServicePrincipal - - UserAssignedMSI - - ManualServicePrincipal - - ServicePrincipalCertificate - - WorkloadIdentity - type: string - required: - - clientID - - tenantID - - type - type: object - status: - description: AzureClusterIdentityStatus defines the observed state of - AzureClusterIdentity. - properties: - conditions: - description: Conditions defines current service state of the AzureClusterIdentity. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index edc81e05d..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1457 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: azureclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureCluster - listKind: AzureClusterList - plural: azureclusters - singular: azurecluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AzureCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].message - name: Message - priority: 1 - type: string - - jsonPath: .spec.resourceGroup - name: Resource Group - priority: 1 - type: string - - jsonPath: .spec.subscriptionID - name: SubscriptionID - priority: 1 - type: string - - jsonPath: .spec.location - name: Location - priority: 1 - type: string - - description: Control Plane Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint - priority: 1 - type: string - - description: Time duration since creation of this AzureCluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureCluster is the Schema for the azureclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureClusterSpec defines the desired state of AzureCluster. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the Azure provider, in addition to the - ones added by default. - type: object - azureEnvironment: - description: |- - AzureEnvironment is the name of the AzureCloud to be used. - The default value that would be used by most users is "AzurePublicCloud", other values are: - - ChinaCloud: "AzureChinaCloud" - - GermanCloud: "AzureGermanCloud" - - PublicCloud: "AzurePublicCloud" - - USGovernmentCloud: "AzureUSGovernmentCloud" - - - Note that values other than the default must also be accompanied by corresponding changes to the - aso-controller-settings Secret to configure ASO to refer to the non-Public cloud. ASO currently does - not support referring to multiple different clouds in a single installation. The following fields must - be defined in the Secret: - - AZURE_AUTHORITY_HOST - - AZURE_RESOURCE_MANAGER_ENDPOINT - - AZURE_RESOURCE_MANAGER_AUDIENCE - - - See the [ASO docs] for more details. - - - [ASO docs]: https://azure.github.io/azure-service-operator/guide/aso-controller-settings-options/ - type: string - bastionSpec: - description: BastionSpec encapsulates all things related to the Bastions - in the cluster. - properties: - azureBastion: - description: AzureBastion specifies how the Azure Bastion cloud - component should be configured. - properties: - enableTunneling: - default: false - description: EnableTunneling enables the native client support - feature for the Azure Bastion Host. Defaults to false. - type: boolean - name: - type: string - publicIP: - description: PublicIPSpec defines the inputs to create an - Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated with - the object. - properties: - tag: - description: 'Tag specifies the value of the IP - tag associated with the public IP. Example: SQL.' - type: string - type: - description: 'Type specifies the IP tag type. Example: - FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - sku: - default: Basic - description: BastionHostSkuName configures the tier of the - Azure Bastion Host. Can be either Basic or Standard. Defaults - to Basic. - enum: - - Basic - - Standard - type: string - subnet: - description: SubnetSpec configures an Azure subnet. - properties: - cidrBlocks: - description: CIDRBlocks defines the subnet's address space, - specified as one or more address prefixes in CIDR notation. - items: - type: string - type: array - id: - description: |- - ID is the Azure resource ID of the subnet. - READ-ONLY - type: string - name: - description: Name defines a name for the subnet resource. - type: string - natGateway: - description: NatGateway associated with this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the NAT gateway. - READ-ONLY - type: string - ip: - description: PublicIPSpec defines the inputs to create - an Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated - with the object. - properties: - tag: - description: 'Tag specifies the value of - the IP tag associated with the public - IP. Example: SQL.' - type: string - type: - description: 'Type specifies the IP tag - type. Example: FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - name: - type: string - required: - - name - type: object - privateEndpoints: - description: PrivateEndpoints defines a list of private - endpoints that should be attached to this subnet. - items: - description: PrivateEndpointSpec configures an Azure - Private Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies - the Application security group in which the private - endpoint IP configuration is included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName specifies - the network interface name associated with the - private endpoint. - type: string - location: - description: Location specifies the region to create - the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of the private - endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections specifies - Private Link Service Connections of the private - endpoint. - items: - description: PrivateLinkServiceConnection defines - the specification for a private link service - connection associated with a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the ID(s) - of the group(s) obtained from the remote - resource that this private endpoint should - connect to. - items: - type: string - type: array - name: - description: Name specifies the name of the - private link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID specifies - the resource ID of the private link service. - type: string - requestMessage: - description: RequestMessage specifies a message - passed to the owner of the remote resource - with the private endpoint connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - role: - description: Role defines the subnet role (eg. Node, ControlPlane) - enum: - - node - - control-plane - - bastion - - all - type: string - routeTable: - description: RouteTable defines the route table that should - be attached to this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the route table. - READ-ONLY - type: string - name: - type: string - required: - - name - type: object - securityGroup: - description: SecurityGroup defines the NSG (network security - group) that should be attached to this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the security group. - READ-ONLY - type: string - name: - type: string - securityRules: - description: SecurityRules is a slice of Azure security - rules for security groups. - items: - description: SecurityRule defines an Azure security - rule for security groups. - properties: - action: - default: Allow - description: Action specifies whether network - traffic is allowed or denied. Can either be - "Allow" or "Deny". Defaults to "Allow". - enum: - - Allow - - Deny - type: string - description: - description: A description for this rule. Restricted - to 140 chars. - type: string - destination: - description: Destination is the destination - address prefix. CIDR or destination IP range. - Asterix '*' can also be used to match all - source IPs. Default tags such as 'VirtualNetwork', - 'AzureLoadBalancer' and 'Internet' can also - be used. - type: string - destinationPorts: - description: DestinationPorts specifies the - destination port or range. Integer or range - between 0 and 65535. Asterix '*' can also - be used to match all ports. - type: string - direction: - description: Direction indicates whether the - rule applies to inbound, or outbound traffic. - "Inbound" or "Outbound". - enum: - - Inbound - - Outbound - type: string - name: - description: Name is a unique name within the - network security group. - type: string - priority: - description: Priority is a number between 100 - and 4096. Each rule should have a unique value - for priority. Rules are processed in priority - order, with lower numbers processed before - higher numbers. Once traffic matches a rule, - processing stops. - format: int32 - type: integer - protocol: - description: Protocol specifies the protocol - type. "Tcp", "Udp", "Icmp", or "*". - enum: - - Tcp - - Udp - - Icmp - - '*' - type: string - source: - description: Source specifies the CIDR or source - IP range. Asterix '*' can also be used to - match all source IPs. Default tags such as - 'VirtualNetwork', 'AzureLoadBalancer' and - 'Internet' can also be used. If this is an - ingress rule, specifies where network traffic - originates from. - type: string - sourcePorts: - description: SourcePorts specifies source port - or range. Integer or range between 0 and 65535. - Asterix '*' can also be used to match all - ports. - type: string - sources: - description: Sources specifies The CIDR or source - IP ranges. - items: - type: string - type: array - required: - - description - - direction - - name - - protocol - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - tags: - additionalProperties: - type: string - description: Tags defines a map of tags. - type: object - required: - - name - type: object - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual Network - service endpoints to enable for the subnets. - items: - description: ServiceEndpointSpec configures an Azure - Service Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - name - - role - type: object - type: object - type: object - cloudProviderConfigOverrides: - description: |- - CloudProviderConfigOverrides is an optional set of configuration values that can be overridden in azure cloud provider config. - This is only a subset of options that are available in azure cloud provider config. - Some values for the cloud provider config are inferred from other parts of cluster api provider azure spec, and may not be available for overrides. - See: https://cloud-provider-azure.sigs.k8s.io/install/configs - Note: All cloud provider config values can be customized by creating the secret beforehand. CloudProviderConfigOverrides is only used when the secret is managed by the Azure Provider. - properties: - backOffs: - description: BackOffConfig indicates the back-off config options. - properties: - cloudProviderBackoff: - type: boolean - cloudProviderBackoffDuration: - type: integer - cloudProviderBackoffExponent: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderBackoffJitter: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderBackoffRetries: - type: integer - type: object - rateLimits: - items: - description: |- - RateLimitSpec represents the rate limit configuration for a particular kind of resource. - Eg. loadBalancerRateLimit is used to configure rate limits for load balancers. - This eventually gets converted to CloudProviderRateLimitConfig that cloud-provider-azure expects. - See: https://github.com/kubernetes-sigs/cloud-provider-azure/blob/d585c2031925b39c925624302f22f8856e29e352/pkg/provider/azure_ratelimit.go#L25 - We cannot use CloudProviderRateLimitConfig directly because floating point values are not supported in controller-tools. - See: https://github.com/kubernetes-sigs/controller-tools/issues/245 - properties: - config: - description: RateLimitConfig indicates the rate limit config - options. - properties: - cloudProviderRateLimit: - type: boolean - cloudProviderRateLimitBucket: - type: integer - cloudProviderRateLimitBucketWrite: - type: integer - cloudProviderRateLimitQPS: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderRateLimitQPSWrite: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - name: - description: Name is the name of the rate limit spec. - enum: - - defaultRateLimit - - routeRateLimit - - subnetsRateLimit - - interfaceRateLimit - - routeTableRateLimit - - loadBalancerRateLimit - - publicIPAddressRateLimit - - securityGroupRateLimit - - virtualMachineRateLimit - - storageAccountRateLimit - - diskRateLimit - - snapshotRateLimit - - virtualMachineScaleSetRateLimit - - virtualMachineSizesRateLimit - - availabilitySetRateLimit - type: string - required: - - name - type: object - type: array - type: object - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. It is not recommended to set - this when creating an AzureCluster as CAPZ will set this for you. However, if it is set, CAPZ will not change it. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - extendedLocation: - description: ExtendedLocation is an optional set of ExtendedLocation - properties for clusters on Azure public MEC. - properties: - name: - description: Name defines the name for the extended location. - type: string - type: - description: Type defines the type for the extended location. - enum: - - EdgeZone - type: string - required: - - name - - type - type: object - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: |- - FailureDomains is a list of failure domains in the cluster's region, used to restrict - eligibility to host the control plane. A FailureDomain maps to an availability zone, - which is a separated group of datacenters within a region. - See: https://learn.microsoft.com/azure/reliability/availability-zones-overview - type: object - identityRef: - description: IdentityRef is a reference to an AzureIdentity to be - used when reconciling this cluster - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - location: - type: string - networkSpec: - description: NetworkSpec encapsulates all things related to Azure - network. - properties: - apiServerLB: - description: APIServerLB is the configuration for the control-plane - load balancer. - properties: - backendPool: - description: BackendPool describes the backend pool of the - load balancer. - properties: - name: - description: |- - Name specifies the name of backend pool for the load balancer. If not specified, the default name will - be set, depending on the load balancer role. - type: string - type: object - frontendIPs: - items: - description: FrontendIP defines a load balancer frontend - IP configuration. - properties: - name: - minLength: 1 - type: string - privateIP: - type: string - publicIP: - description: PublicIPSpec defines the inputs to create - an Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated - with the object. - properties: - tag: - description: 'Tag specifies the value of the - IP tag associated with the public IP. Example: - SQL.' - type: string - type: - description: 'Type specifies the IP tag type. - Example: FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - required: - - name - type: object - type: array - frontendIPsCount: - description: FrontendIPsCount specifies the number of frontend - IP addresses for the load balancer. - format: int32 - type: integer - id: - description: |- - ID is the Azure resource ID of the load balancer. - READ-ONLY - type: string - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout for - the TCP idle connection. - format: int32 - type: integer - name: - type: string - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer Type. - type: string - type: object - controlPlaneOutboundLB: - description: |- - ControlPlaneOutboundLB is the configuration for the control-plane outbound load balancer. - This is different from APIServerLB, and is used only in private clusters (optionally) for enabling outbound traffic. - properties: - backendPool: - description: BackendPool describes the backend pool of the - load balancer. - properties: - name: - description: |- - Name specifies the name of backend pool for the load balancer. If not specified, the default name will - be set, depending on the load balancer role. - type: string - type: object - frontendIPs: - items: - description: FrontendIP defines a load balancer frontend - IP configuration. - properties: - name: - minLength: 1 - type: string - privateIP: - type: string - publicIP: - description: PublicIPSpec defines the inputs to create - an Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated - with the object. - properties: - tag: - description: 'Tag specifies the value of the - IP tag associated with the public IP. Example: - SQL.' - type: string - type: - description: 'Type specifies the IP tag type. - Example: FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - required: - - name - type: object - type: array - frontendIPsCount: - description: FrontendIPsCount specifies the number of frontend - IP addresses for the load balancer. - format: int32 - type: integer - id: - description: |- - ID is the Azure resource ID of the load balancer. - READ-ONLY - type: string - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout for - the TCP idle connection. - format: int32 - type: integer - name: - type: string - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer Type. - type: string - type: object - nodeOutboundLB: - description: NodeOutboundLB is the configuration for the node - outbound load balancer. - properties: - backendPool: - description: BackendPool describes the backend pool of the - load balancer. - properties: - name: - description: |- - Name specifies the name of backend pool for the load balancer. If not specified, the default name will - be set, depending on the load balancer role. - type: string - type: object - frontendIPs: - items: - description: FrontendIP defines a load balancer frontend - IP configuration. - properties: - name: - minLength: 1 - type: string - privateIP: - type: string - publicIP: - description: PublicIPSpec defines the inputs to create - an Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated - with the object. - properties: - tag: - description: 'Tag specifies the value of the - IP tag associated with the public IP. Example: - SQL.' - type: string - type: - description: 'Type specifies the IP tag type. - Example: FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - required: - - name - type: object - type: array - frontendIPsCount: - description: FrontendIPsCount specifies the number of frontend - IP addresses for the load balancer. - format: int32 - type: integer - id: - description: |- - ID is the Azure resource ID of the load balancer. - READ-ONLY - type: string - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout for - the TCP idle connection. - format: int32 - type: integer - name: - type: string - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer Type. - type: string - type: object - privateDNSZoneName: - description: PrivateDNSZoneName defines the zone name for the - Azure Private DNS. - type: string - subnets: - description: Subnets is the configuration for the control-plane - subnet and the node subnet. - items: - description: SubnetSpec configures an Azure subnet. - properties: - cidrBlocks: - description: CIDRBlocks defines the subnet's address space, - specified as one or more address prefixes in CIDR notation. - items: - type: string - type: array - id: - description: |- - ID is the Azure resource ID of the subnet. - READ-ONLY - type: string - name: - description: Name defines a name for the subnet resource. - type: string - natGateway: - description: NatGateway associated with this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the NAT gateway. - READ-ONLY - type: string - ip: - description: PublicIPSpec defines the inputs to create - an Azure public IP address. - properties: - dnsName: - type: string - ipTags: - items: - description: IPTag contains the IpTag associated - with the object. - properties: - tag: - description: 'Tag specifies the value of the - IP tag associated with the public IP. Example: - SQL.' - type: string - type: - description: 'Type specifies the IP tag type. - Example: FirstPartyUsage.' - type: string - required: - - tag - - type - type: object - type: array - name: - type: string - required: - - name - type: object - name: - type: string - required: - - name - type: object - privateEndpoints: - description: PrivateEndpoints defines a list of private - endpoints that should be attached to this subnet. - items: - description: PrivateEndpointSpec configures an Azure Private - Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies the - Application security group in which the private - endpoint IP configuration is included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName specifies - the network interface name associated with the private - endpoint. - type: string - location: - description: Location specifies the region to create - the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of the private - endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections specifies - Private Link Service Connections of the private - endpoint. - items: - description: PrivateLinkServiceConnection defines - the specification for a private link service connection - associated with a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the ID(s) of - the group(s) obtained from the remote resource - that this private endpoint should connect - to. - items: - type: string - type: array - name: - description: Name specifies the name of the - private link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID specifies - the resource ID of the private link service. - type: string - requestMessage: - description: RequestMessage specifies a message - passed to the owner of the remote resource - with the private endpoint connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - role: - description: Role defines the subnet role (eg. Node, ControlPlane) - enum: - - node - - control-plane - - bastion - - all - type: string - routeTable: - description: RouteTable defines the route table that should - be attached to this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the route table. - READ-ONLY - type: string - name: - type: string - required: - - name - type: object - securityGroup: - description: SecurityGroup defines the NSG (network security - group) that should be attached to this subnet. - properties: - id: - description: |- - ID is the Azure resource ID of the security group. - READ-ONLY - type: string - name: - type: string - securityRules: - description: SecurityRules is a slice of Azure security - rules for security groups. - items: - description: SecurityRule defines an Azure security - rule for security groups. - properties: - action: - default: Allow - description: Action specifies whether network - traffic is allowed or denied. Can either be - "Allow" or "Deny". Defaults to "Allow". - enum: - - Allow - - Deny - type: string - description: - description: A description for this rule. Restricted - to 140 chars. - type: string - destination: - description: Destination is the destination address - prefix. CIDR or destination IP range. Asterix - '*' can also be used to match all source IPs. - Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' - and 'Internet' can also be used. - type: string - destinationPorts: - description: DestinationPorts specifies the destination - port or range. Integer or range between 0 and - 65535. Asterix '*' can also be used to match - all ports. - type: string - direction: - description: Direction indicates whether the rule - applies to inbound, or outbound traffic. "Inbound" - or "Outbound". - enum: - - Inbound - - Outbound - type: string - name: - description: Name is a unique name within the - network security group. - type: string - priority: - description: Priority is a number between 100 - and 4096. Each rule should have a unique value - for priority. Rules are processed in priority - order, with lower numbers processed before higher - numbers. Once traffic matches a rule, processing - stops. - format: int32 - type: integer - protocol: - description: Protocol specifies the protocol type. - "Tcp", "Udp", "Icmp", or "*". - enum: - - Tcp - - Udp - - Icmp - - '*' - type: string - source: - description: Source specifies the CIDR or source - IP range. Asterix '*' can also be used to match - all source IPs. Default tags such as 'VirtualNetwork', - 'AzureLoadBalancer' and 'Internet' can also - be used. If this is an ingress rule, specifies - where network traffic originates from. - type: string - sourcePorts: - description: SourcePorts specifies source port - or range. Integer or range between 0 and 65535. - Asterix '*' can also be used to match all ports. - type: string - sources: - description: Sources specifies The CIDR or source - IP ranges. - items: - type: string - type: array - required: - - description - - direction - - name - - protocol - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - tags: - additionalProperties: - type: string - description: Tags defines a map of tags. - type: object - required: - - name - type: object - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual Network - service endpoints to enable for the subnets. - items: - description: ServiceEndpointSpec configures an Azure Service - Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - name - - role - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnet: - description: Vnet is the configuration for the Azure virtual network. - properties: - cidrBlocks: - description: CIDRBlocks defines the virtual network's address - space, specified as one or more address prefixes in CIDR - notation. - items: - type: string - type: array - id: - description: |- - ID is the Azure resource ID of the virtual network. - READ-ONLY - type: string - name: - description: Name defines a name for the virtual network resource. - type: string - peerings: - description: Peerings defines a list of peerings of the newly - created virtual network with existing virtual networks. - items: - description: VnetPeeringSpec specifies an existing remote - virtual network to peer with the AzureCluster's virtual - network. - properties: - forwardPeeringProperties: - description: |- - ForwardPeeringProperties specifies VnetPeeringProperties for peering from the cluster's virtual network to the - remote virtual network. - properties: - allowForwardedTraffic: - description: |- - AllowForwardedTraffic specifies whether the forwarded traffic from the VMs in the local virtual network will be - allowed/disallowed in remote virtual network. - type: boolean - allowGatewayTransit: - description: |- - AllowGatewayTransit specifies if gateway links can be used in remote virtual networking to link to this virtual - network. - type: boolean - allowVirtualNetworkAccess: - description: |- - AllowVirtualNetworkAccess specifies whether the VMs in the local virtual network space would be able to access - the VMs in remote virtual network space. - type: boolean - useRemoteGateways: - description: |- - UseRemoteGateways specifies if remote gateways can be used on this virtual network. - If the flag is set to true, and allowGatewayTransit on remote peering is also set to true, the virtual network - will use the gateways of the remote virtual network for transit. Only one peering can have this flag set to true. - This flag cannot be set if virtual network already has a gateway. - type: boolean - type: object - remoteVnetName: - description: RemoteVnetName defines name of the remote - virtual network. - type: string - resourceGroup: - description: ResourceGroup is the resource group name - of the remote virtual network. - type: string - reversePeeringProperties: - description: |- - ReversePeeringProperties specifies VnetPeeringProperties for peering from the remote virtual network to the - cluster's virtual network. - properties: - allowForwardedTraffic: - description: |- - AllowForwardedTraffic specifies whether the forwarded traffic from the VMs in the local virtual network will be - allowed/disallowed in remote virtual network. - type: boolean - allowGatewayTransit: - description: |- - AllowGatewayTransit specifies if gateway links can be used in remote virtual networking to link to this virtual - network. - type: boolean - allowVirtualNetworkAccess: - description: |- - AllowVirtualNetworkAccess specifies whether the VMs in the local virtual network space would be able to access - the VMs in remote virtual network space. - type: boolean - useRemoteGateways: - description: |- - UseRemoteGateways specifies if remote gateways can be used on this virtual network. - If the flag is set to true, and allowGatewayTransit on remote peering is also set to true, the virtual network - will use the gateways of the remote virtual network for transit. Only one peering can have this flag set to true. - This flag cannot be set if virtual network already has a gateway. - type: boolean - type: object - required: - - remoteVnetName - type: object - type: array - resourceGroup: - description: |- - ResourceGroup is the name of the resource group of the existing virtual network - or the resource group where a managed virtual network should be created. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - required: - - name - type: object - type: object - resourceGroup: - type: string - subscriptionID: - type: string - required: - - location - type: object - status: - description: AzureClusterStatus defines the observed state of AzureCluster. - properties: - conditions: - description: Conditions defines current service state of the AzureCluster. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: |- - FailureDomains specifies the list of unique failure domains for the location/region of the cluster. - A FailureDomain maps to Availability Zone with an Azure Region (if the region support them). An - Availability Zone is a separate data center within a region and they can be used to ensure - the cluster is more resilient to failure. - See: https://learn.microsoft.com/azure/reliability/availability-zones-overview - This list will be used by Cluster API to try and spread the machines across the failure domains. - type: object - longRunningOperationStates: - description: |- - LongRunningOperationStates saves the states for Azure long-running operations so they can be continued on the - next reconciliation loop. - items: - description: Future contains the data needed for an Azure long-running - operation to continue across reconcile loops. - properties: - data: - description: Data is the base64 url encoded json Azure AutoRest - Future. - type: string - name: - description: |- - Name is the name of the Azure resource. - Together with the service name, this forms the unique identifier for the future. - type: string - resourceGroup: - description: ResourceGroup is the Azure resource group for the - resource. - type: string - serviceName: - description: |- - ServiceName is the name of the Azure service. - Together with the name of the resource, this forms the unique identifier for the future. - type: string - type: - description: Type describes the type of future, such as update, - create, delete, etc. - type: string - required: - - data - - name - - serviceName - - type - type: object - type: array - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azureclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index dd75a83ea..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azureclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,955 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azureclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureClusterTemplate - listKind: AzureClusterTemplateList - plural: azureclustertemplates - singular: azureclustertemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureClusterTemplate is the Schema for the azureclustertemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureClusterTemplateSpec defines the desired state of AzureClusterTemplate. - properties: - template: - description: AzureClusterTemplateResource describes the data needed - to create an AzureCluster from a template. - properties: - spec: - description: AzureClusterTemplateResourceSpec specifies an Azure - cluster template resource. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the Azure provider, in addition to the - ones added by default. - type: object - azureEnvironment: - description: |- - AzureEnvironment is the name of the AzureCloud to be used. - The default value that would be used by most users is "AzurePublicCloud", other values are: - - ChinaCloud: "AzureChinaCloud" - - GermanCloud: "AzureGermanCloud" - - PublicCloud: "AzurePublicCloud" - - USGovernmentCloud: "AzureUSGovernmentCloud" - - - Note that values other than the default must also be accompanied by corresponding changes to the - aso-controller-settings Secret to configure ASO to refer to the non-Public cloud. ASO currently does - not support referring to multiple different clouds in a single installation. The following fields must - be defined in the Secret: - - AZURE_AUTHORITY_HOST - - AZURE_RESOURCE_MANAGER_ENDPOINT - - AZURE_RESOURCE_MANAGER_AUDIENCE - - - See the [ASO docs] for more details. - - - [ASO docs]: https://azure.github.io/azure-service-operator/guide/aso-controller-settings-options/ - type: string - bastionSpec: - description: BastionSpec encapsulates all things related to - the Bastions in the cluster. - properties: - azureBastion: - description: AzureBastionTemplateSpec specifies a template - for an Azure Bastion host. - properties: - subnet: - description: SubnetTemplateSpec specifies a template - for a subnet. - properties: - cidrBlocks: - description: CIDRBlocks defines the subnet's address - space, specified as one or more address prefixes - in CIDR notation. - items: - type: string - type: array - name: - description: Name defines a name for the subnet - resource. - type: string - natGateway: - description: NatGateway associated with this subnet. - properties: - name: - type: string - required: - - name - type: object - privateEndpoints: - description: PrivateEndpoints defines a list of - private endpoints that should be attached to - this subnet. - items: - description: PrivateEndpointSpec configures - an Azure Private Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies - the Application security group in which - the private endpoint IP configuration - is included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName - specifies the network interface name associated - with the private endpoint. - type: string - location: - description: Location specifies the region - to create the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of - the private endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections - specifies Private Link Service Connections - of the private endpoint. - items: - description: PrivateLinkServiceConnection - defines the specification for a private - link service connection associated with - a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the - ID(s) of the group(s) obtained from - the remote resource that this private - endpoint should connect to. - items: - type: string - type: array - name: - description: Name specifies the name - of the private link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID - specifies the resource ID of the - private link service. - type: string - requestMessage: - description: RequestMessage specifies - a message passed to the owner of - the remote resource with the private - endpoint connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - role: - description: Role defines the subnet role (eg. - Node, ControlPlane) - enum: - - node - - control-plane - - bastion - - all - type: string - securityGroup: - description: SecurityGroup defines the NSG (network - security group) that should be attached to this - subnet. - properties: - securityRules: - description: SecurityRules is a slice of Azure - security rules for security groups. - items: - description: SecurityRule defines an Azure - security rule for security groups. - properties: - action: - default: Allow - description: Action specifies whether - network traffic is allowed or denied. - Can either be "Allow" or "Deny". Defaults - to "Allow". - enum: - - Allow - - Deny - type: string - description: - description: A description for this - rule. Restricted to 140 chars. - type: string - destination: - description: Destination is the destination - address prefix. CIDR or destination - IP range. Asterix '*' can also be - used to match all source IPs. Default - tags such as 'VirtualNetwork', 'AzureLoadBalancer' - and 'Internet' can also be used. - type: string - destinationPorts: - description: DestinationPorts specifies - the destination port or range. Integer - or range between 0 and 65535. Asterix - '*' can also be used to match all - ports. - type: string - direction: - description: Direction indicates whether - the rule applies to inbound, or outbound - traffic. "Inbound" or "Outbound". - enum: - - Inbound - - Outbound - type: string - name: - description: Name is a unique name within - the network security group. - type: string - priority: - description: Priority is a number between - 100 and 4096. Each rule should have - a unique value for priority. Rules - are processed in priority order, with - lower numbers processed before higher - numbers. Once traffic matches a rule, - processing stops. - format: int32 - type: integer - protocol: - description: Protocol specifies the - protocol type. "Tcp", "Udp", "Icmp", - or "*". - enum: - - Tcp - - Udp - - Icmp - - '*' - type: string - source: - description: Source specifies the CIDR - or source IP range. Asterix '*' can - also be used to match all source IPs. - Default tags such as 'VirtualNetwork', - 'AzureLoadBalancer' and 'Internet' - can also be used. If this is an ingress - rule, specifies where network traffic - originates from. - type: string - sourcePorts: - description: SourcePorts specifies source - port or range. Integer or range between - 0 and 65535. Asterix '*' can also - be used to match all ports. - type: string - sources: - description: Sources specifies The CIDR - or source IP ranges. - items: - type: string - type: array - required: - - description - - direction - - name - - protocol - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - tags: - additionalProperties: - type: string - description: Tags defines a map of tags. - type: object - type: object - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual - Network service endpoints to enable for the - subnets. - items: - description: ServiceEndpointSpec configures - an Azure Service Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - name - - role - type: object - type: object - type: object - cloudProviderConfigOverrides: - description: |- - CloudProviderConfigOverrides is an optional set of configuration values that can be overridden in azure cloud provider config. - This is only a subset of options that are available in azure cloud provider config. - Some values for the cloud provider config are inferred from other parts of cluster api provider azure spec, and may not be available for overrides. - See: https://cloud-provider-azure.sigs.k8s.io/install/configs - Note: All cloud provider config values can be customized by creating the secret beforehand. CloudProviderConfigOverrides is only used when the secret is managed by the Azure Provider. - properties: - backOffs: - description: BackOffConfig indicates the back-off config - options. - properties: - cloudProviderBackoff: - type: boolean - cloudProviderBackoffDuration: - type: integer - cloudProviderBackoffExponent: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderBackoffJitter: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderBackoffRetries: - type: integer - type: object - rateLimits: - items: - description: |- - RateLimitSpec represents the rate limit configuration for a particular kind of resource. - Eg. loadBalancerRateLimit is used to configure rate limits for load balancers. - This eventually gets converted to CloudProviderRateLimitConfig that cloud-provider-azure expects. - See: https://github.com/kubernetes-sigs/cloud-provider-azure/blob/d585c2031925b39c925624302f22f8856e29e352/pkg/provider/azure_ratelimit.go#L25 - We cannot use CloudProviderRateLimitConfig directly because floating point values are not supported in controller-tools. - See: https://github.com/kubernetes-sigs/controller-tools/issues/245 - properties: - config: - description: RateLimitConfig indicates the rate - limit config options. - properties: - cloudProviderRateLimit: - type: boolean - cloudProviderRateLimitBucket: - type: integer - cloudProviderRateLimitBucketWrite: - type: integer - cloudProviderRateLimitQPS: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - cloudProviderRateLimitQPSWrite: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - name: - description: Name is the name of the rate limit - spec. - enum: - - defaultRateLimit - - routeRateLimit - - subnetsRateLimit - - interfaceRateLimit - - routeTableRateLimit - - loadBalancerRateLimit - - publicIPAddressRateLimit - - securityGroupRateLimit - - virtualMachineRateLimit - - storageAccountRateLimit - - diskRateLimit - - snapshotRateLimit - - virtualMachineScaleSetRateLimit - - virtualMachineSizesRateLimit - - availabilitySetRateLimit - type: string - required: - - name - type: object - type: array - type: object - extendedLocation: - description: ExtendedLocation is an optional set of ExtendedLocation - properties for clusters on Azure public MEC. - properties: - name: - description: Name defines the name for the extended location. - type: string - type: - description: Type defines the type for the extended location. - enum: - - EdgeZone - type: string - required: - - name - - type - type: object - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes - an infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure - domain is suitable for use by control plane machines. - type: boolean - type: object - description: |- - FailureDomains is a list of failure domains in the cluster's region, used to restrict - eligibility to host the control plane. A FailureDomain maps to an availability zone, - which is a separated group of datacenters within a region. - See: https://learn.microsoft.com/azure/reliability/availability-zones-overview - type: object - identityRef: - description: IdentityRef is a reference to an AzureIdentity - to be used when reconciling this cluster - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - location: - type: string - networkSpec: - description: NetworkSpec encapsulates all things related to - Azure network. - properties: - apiServerLB: - description: APIServerLB is the configuration for the - control-plane load balancer. - properties: - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout - for the TCP idle connection. - format: int32 - type: integer - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer - Type. - type: string - type: object - controlPlaneOutboundLB: - description: |- - ControlPlaneOutboundLB is the configuration for the control-plane outbound load balancer. - This is different from APIServerLB, and is used only in private clusters (optionally) for enabling outbound traffic. - properties: - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout - for the TCP idle connection. - format: int32 - type: integer - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer - Type. - type: string - type: object - nodeOutboundLB: - description: NodeOutboundLB is the configuration for the - node outbound load balancer. - properties: - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes specifies the timeout - for the TCP idle connection. - format: int32 - type: integer - sku: - description: SKU defines an Azure load balancer SKU. - type: string - type: - description: LBType defines an Azure load balancer - Type. - type: string - type: object - privateDNSZoneName: - description: PrivateDNSZoneName defines the zone name - for the Azure Private DNS. - type: string - subnets: - description: Subnets is the configuration for the control-plane - subnet and the node subnet. - items: - description: SubnetTemplateSpec specifies a template - for a subnet. - properties: - cidrBlocks: - description: CIDRBlocks defines the subnet's address - space, specified as one or more address prefixes - in CIDR notation. - items: - type: string - type: array - name: - description: Name defines a name for the subnet - resource. - type: string - natGateway: - description: NatGateway associated with this subnet. - properties: - name: - type: string - required: - - name - type: object - privateEndpoints: - description: PrivateEndpoints defines a list of - private endpoints that should be attached to this - subnet. - items: - description: PrivateEndpointSpec configures an - Azure Private Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies - the Application security group in which - the private endpoint IP configuration is - included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName specifies - the network interface name associated with - the private endpoint. - type: string - location: - description: Location specifies the region - to create the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of the - private endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections - specifies Private Link Service Connections - of the private endpoint. - items: - description: PrivateLinkServiceConnection - defines the specification for a private - link service connection associated with - a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the - ID(s) of the group(s) obtained from - the remote resource that this private - endpoint should connect to. - items: - type: string - type: array - name: - description: Name specifies the name - of the private link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID specifies - the resource ID of the private link - service. - type: string - requestMessage: - description: RequestMessage specifies - a message passed to the owner of the - remote resource with the private endpoint - connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - role: - description: Role defines the subnet role (eg. Node, - ControlPlane) - enum: - - node - - control-plane - - bastion - - all - type: string - securityGroup: - description: SecurityGroup defines the NSG (network - security group) that should be attached to this - subnet. - properties: - securityRules: - description: SecurityRules is a slice of Azure - security rules for security groups. - items: - description: SecurityRule defines an Azure - security rule for security groups. - properties: - action: - default: Allow - description: Action specifies whether - network traffic is allowed or denied. - Can either be "Allow" or "Deny". Defaults - to "Allow". - enum: - - Allow - - Deny - type: string - description: - description: A description for this rule. - Restricted to 140 chars. - type: string - destination: - description: Destination is the destination - address prefix. CIDR or destination - IP range. Asterix '*' can also be used - to match all source IPs. Default tags - such as 'VirtualNetwork', 'AzureLoadBalancer' - and 'Internet' can also be used. - type: string - destinationPorts: - description: DestinationPorts specifies - the destination port or range. Integer - or range between 0 and 65535. Asterix - '*' can also be used to match all ports. - type: string - direction: - description: Direction indicates whether - the rule applies to inbound, or outbound - traffic. "Inbound" or "Outbound". - enum: - - Inbound - - Outbound - type: string - name: - description: Name is a unique name within - the network security group. - type: string - priority: - description: Priority is a number between - 100 and 4096. Each rule should have - a unique value for priority. Rules are - processed in priority order, with lower - numbers processed before higher numbers. - Once traffic matches a rule, processing - stops. - format: int32 - type: integer - protocol: - description: Protocol specifies the protocol - type. "Tcp", "Udp", "Icmp", or "*". - enum: - - Tcp - - Udp - - Icmp - - '*' - type: string - source: - description: Source specifies the CIDR - or source IP range. Asterix '*' can - also be used to match all source IPs. - Default tags such as 'VirtualNetwork', - 'AzureLoadBalancer' and 'Internet' can - also be used. If this is an ingress - rule, specifies where network traffic - originates from. - type: string - sourcePorts: - description: SourcePorts specifies source - port or range. Integer or range between - 0 and 65535. Asterix '*' can also be - used to match all ports. - type: string - sources: - description: Sources specifies The CIDR - or source IP ranges. - items: - type: string - type: array - required: - - description - - direction - - name - - protocol - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - tags: - additionalProperties: - type: string - description: Tags defines a map of tags. - type: object - type: object - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual - Network service endpoints to enable for the subnets. - items: - description: ServiceEndpointSpec configures an - Azure Service Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - name - - role - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnet: - description: Vnet is the configuration for the Azure virtual - network. - properties: - cidrBlocks: - description: CIDRBlocks defines the virtual network's - address space, specified as one or more address - prefixes in CIDR notation. - items: - type: string - type: array - peerings: - description: Peerings defines a list of peerings of - the newly created virtual network with existing - virtual networks. - items: - description: VnetPeeringClassSpec specifies a virtual - network peering class. - properties: - forwardPeeringProperties: - description: |- - ForwardPeeringProperties specifies VnetPeeringProperties for peering from the cluster's virtual network to the - remote virtual network. - properties: - allowForwardedTraffic: - description: |- - AllowForwardedTraffic specifies whether the forwarded traffic from the VMs in the local virtual network will be - allowed/disallowed in remote virtual network. - type: boolean - allowGatewayTransit: - description: |- - AllowGatewayTransit specifies if gateway links can be used in remote virtual networking to link to this virtual - network. - type: boolean - allowVirtualNetworkAccess: - description: |- - AllowVirtualNetworkAccess specifies whether the VMs in the local virtual network space would be able to access - the VMs in remote virtual network space. - type: boolean - useRemoteGateways: - description: |- - UseRemoteGateways specifies if remote gateways can be used on this virtual network. - If the flag is set to true, and allowGatewayTransit on remote peering is also set to true, the virtual network - will use the gateways of the remote virtual network for transit. Only one peering can have this flag set to true. - This flag cannot be set if virtual network already has a gateway. - type: boolean - type: object - remoteVnetName: - description: RemoteVnetName defines name of - the remote virtual network. - type: string - resourceGroup: - description: ResourceGroup is the resource group - name of the remote virtual network. - type: string - reversePeeringProperties: - description: |- - ReversePeeringProperties specifies VnetPeeringProperties for peering from the remote virtual network to the - cluster's virtual network. - properties: - allowForwardedTraffic: - description: |- - AllowForwardedTraffic specifies whether the forwarded traffic from the VMs in the local virtual network will be - allowed/disallowed in remote virtual network. - type: boolean - allowGatewayTransit: - description: |- - AllowGatewayTransit specifies if gateway links can be used in remote virtual networking to link to this virtual - network. - type: boolean - allowVirtualNetworkAccess: - description: |- - AllowVirtualNetworkAccess specifies whether the VMs in the local virtual network space would be able to access - the VMs in remote virtual network space. - type: boolean - useRemoteGateways: - description: |- - UseRemoteGateways specifies if remote gateways can be used on this virtual network. - If the flag is set to true, and allowGatewayTransit on remote peering is also set to true, the virtual network - will use the gateways of the remote virtual network for transit. Only one peering can have this flag set to true. - This flag cannot be set if virtual network already has a gateway. - type: boolean - type: object - required: - - remoteVnetName - type: object - type: array - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - type: object - type: object - subscriptionID: - type: string - required: - - location - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index afa297103..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,871 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: azuremachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureMachine - listKind: AzureMachineList - plural: azuremachines - singular: azuremachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AzureMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].severity - name: Severity - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].message - name: Message - priority: 1 - type: string - - description: Azure VM provisioning state - jsonPath: .status.vmState - name: State - type: string - - description: Machine object to which this AzureMachine belongs - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - priority: 1 - type: string - - description: Azure VM ID - jsonPath: .spec.providerID - name: VM ID - priority: 1 - type: string - - description: Azure VM Size - jsonPath: .spec.vmSize - name: VM Size - priority: 1 - type: string - - description: Time duration since creation of this AzureMachine - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureMachine is the Schema for the azuremachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureMachineSpec defines the desired state of AzureMachine. - properties: - acceleratedNetworking: - description: 'Deprecated: AcceleratedNetworking should be set in the - networkInterfaces field.' - type: boolean - additionalCapabilities: - description: AdditionalCapabilities specifies additional capabilities - enabled or disabled on the virtual machine. - properties: - ultraSSDEnabled: - description: |- - UltraSSDEnabled enables or disables Azure UltraSSD capability for the virtual machine. - Defaults to true if Ultra SSD data disks are specified, - otherwise it doesn't set the capability on the VM. - type: boolean - type: object - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - Azure provider. If both the AzureCluster and the AzureMachine specify the same tag name with different values, the - AzureMachine's value takes precedence. - type: object - allocatePublicIP: - description: AllocatePublicIP allows the ability to create dynamic - public ips for machines where this value is true. - type: boolean - capacityReservationGroupID: - description: |- - CapacityReservationGroupID specifies the capacity reservation group resource id that should be - used for allocating the virtual machine. - type: string - dataDisks: - description: DataDisk specifies the parameters that are used to add - one or more data disks to the machine - items: - description: DataDisk specifies the parameters that are used to - add one or more data disks to the machine. - properties: - cachingType: - description: CachingType specifies the caching requirements. - enum: - - None - - ReadOnly - - ReadWrite - type: string - diskSizeGB: - description: DiskSizeGB is the size in GB to assign to the data - disk. - format: int32 - type: integer - lun: - description: |- - Lun Specifies the logical unit number of the data disk. This value is used to identify data disks within the VM and therefore must be unique for each data disk attached to a VM. - The value must be between 0 and 63. - format: int32 - type: integer - managedDisk: - description: ManagedDisk specifies the Managed Disk parameters - for the data disk. - properties: - diskEncryptionSet: - description: DiskEncryptionSet specifies the customer-managed - disk encryption set resource id for the managed disk. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityProfile: - description: SecurityProfile specifies the security profile - for the managed disk. - properties: - diskEncryptionSet: - description: |- - DiskEncryptionSet specifies the customer-managed disk encryption set resource id for the - managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and - VMGuest blob. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityEncryptionType: - description: |- - SecurityEncryptionType specifies the encryption type of the managed disk. - It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState - blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. - When set to VMGuestStateOnly, VirtualizedTrustedPlatformModule should be set to Enabled. - When set to DiskWithVMGuestState, EncryptionAtHost should be disabled, SecureBoot and - VirtualizedTrustedPlatformModule should be set to Enabled. - It can be set only for Confidential VMs. - enum: - - VMGuestStateOnly - - DiskWithVMGuestState - type: string - type: object - storageAccountType: - type: string - type: object - nameSuffix: - description: |- - NameSuffix is the suffix to be appended to the machine name to generate the disk name. - Each disk name will be in format _. - type: string - required: - - diskSizeGB - - nameSuffix - type: object - type: array - diagnostics: - description: |- - Diagnostics specifies the diagnostics settings for a virtual machine. - If not specified then Boot diagnostics (Managed) will be enabled. - properties: - boot: - description: |- - Boot configures the boot diagnostics settings for the virtual machine. - This allows to configure capturing serial output from the virtual machine on boot. - This is useful for debugging software based launch issues. - If not specified then Boot diagnostics (Managed) will be enabled. - properties: - storageAccountType: - description: |- - StorageAccountType determines if the storage account for storing the diagnostics data - should be disabled (Disabled), provisioned by Azure (Managed) or by the user (UserManaged). - enum: - - Managed - - UserManaged - - Disabled - type: string - userManaged: - description: UserManaged provides a reference to the user-managed - storage account. - properties: - storageAccountURI: - description: |- - StorageAccountURI is the URI of the user-managed storage account. - The URI typically will be `https://.blob.core.windows.net/` - but may differ if you are using Azure DNS zone endpoints. - You can find the correct endpoint by looking for the Blob Primary Endpoint in the - endpoints tab in the Azure console or with the CLI by issuing - `az storage account list --query='[].{name: name, "resource group": resourceGroup, "blob endpoint": primaryEndpoints.blob}'`. - maxLength: 1024 - pattern: ^https:// - type: string - required: - - storageAccountURI - type: object - required: - - storageAccountType - type: object - type: object - dnsServers: - description: DNSServers adds a list of DNS Server IP addresses to - the VM NICs. - items: - type: string - type: array - enableIPForwarding: - description: |- - EnableIPForwarding enables IP Forwarding in Azure which is required for some CNI's to send traffic from a pods on one machine - to another. This is required for IpV6 with Calico in combination with User Defined Routes (set by the Azure Cloud Controller - manager). Default is false for disabled. - type: boolean - failureDomain: - description: |- - FailureDomain is the failure domain unique identifier this Machine should be attached to, - as defined in Cluster API. This relates to an Azure Availability Zone - type: string - identity: - default: None - description: |- - Identity is the type of identity used for the virtual machine. - The type 'SystemAssigned' is an implicitly created identity. - The generated identity will be assigned a Subscription contributor role. - The type 'UserAssigned' is a standalone Azure resource provided by the user - and assigned to the VM - enum: - - None - - SystemAssigned - - UserAssigned - type: string - image: - description: |- - Image is used to provide details of an image to use during VM creation. - If image details are omitted the image will default the Azure Marketplace "capi" offer, - which is based on Ubuntu. - properties: - computeGallery: - description: ComputeGallery specifies an image to use from the - Azure Compute Gallery - properties: - gallery: - description: Gallery specifies the name of the compute image - gallery that contains the image - minLength: 1 - type: string - name: - description: Name is the name of the image - minLength: 1 - type: string - plan: - description: Plan contains plan information. - properties: - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization - that created the image - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - type: string - required: - - offer - - publisher - - sku - type: object - resourceGroup: - description: ResourceGroup specifies the resource group containing - the private compute gallery. - type: string - subscriptionID: - description: SubscriptionID is the identifier of the subscription - that contains the private compute gallery. - type: string - version: - description: |- - Version specifies the version of the marketplace image. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - gallery - - name - - version - type: object - id: - description: ID specifies an image to use by ID - type: string - marketplace: - description: Marketplace specifies an image to use from the Azure - Marketplace - properties: - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization that - created the image - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - type: string - thirdPartyImage: - default: false - description: |- - ThirdPartyImage indicates the image is published by a third party publisher and a Plan - will be generated for it. - type: boolean - version: - description: |- - Version specifies the version of an image sku. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - offer - - publisher - - sku - - version - type: object - sharedGallery: - description: |- - SharedGallery specifies an image to use from an Azure Shared Image Gallery - Deprecated: use ComputeGallery instead. - properties: - gallery: - description: Gallery specifies the name of the shared image - gallery that contains the image - minLength: 1 - type: string - name: - description: Name is the name of the image - minLength: 1 - type: string - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - publisher: - description: |- - Publisher is the name of the organization that created the image. - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - resourceGroup: - description: ResourceGroup specifies the resource group containing - the shared image gallery - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - subscriptionID: - description: SubscriptionID is the identifier of the subscription - that contains the shared image gallery - minLength: 1 - type: string - version: - description: |- - Version specifies the version of the marketplace image. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - gallery - - name - - resourceGroup - - subscriptionID - - version - type: object - type: object - networkInterfaces: - description: |- - NetworkInterfaces specifies a list of network interface configurations. - If left unspecified, the VM will get a single network interface with a - single IPConfig in the subnet specified in the cluster's node subnet field. - The primary interface will be the first networkInterface specified (index 0) in the list. - items: - description: NetworkInterface defines a network interface. - properties: - acceleratedNetworking: - description: |- - AcceleratedNetworking enables or disables Azure accelerated networking. If omitted, it will be set based on - whether the requested VMSize supports accelerated networking. - If AcceleratedNetworking is set to true with a VMSize that does not support it, Azure will return an error. - type: boolean - privateIPConfigs: - description: |- - PrivateIPConfigs specifies the number of private IP addresses to attach to the interface. - Defaults to 1 if not specified. - type: integer - subnetName: - description: SubnetName specifies the subnet in which the new - network interface will be placed. - type: string - type: object - type: array - osDisk: - description: OSDisk specifies the parameters for the operating system - disk of the machine - properties: - cachingType: - description: CachingType specifies the caching requirements. - enum: - - None - - ReadOnly - - ReadWrite - type: string - diffDiskSettings: - description: DiffDiskSettings describe ephemeral disk settings - for the os disk. - properties: - option: - description: |- - Option enables ephemeral OS when set to "Local" - See https://learn.microsoft.com/azure/virtual-machines/ephemeral-os-disks for full details - enum: - - Local - type: string - required: - - option - type: object - diskSizeGB: - description: |- - DiskSizeGB is the size in GB to assign to the OS disk. - Will have a default of 30GB if not provided - format: int32 - type: integer - managedDisk: - description: ManagedDisk specifies the Managed Disk parameters - for the OS disk. - properties: - diskEncryptionSet: - description: DiskEncryptionSet specifies the customer-managed - disk encryption set resource id for the managed disk. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityProfile: - description: SecurityProfile specifies the security profile - for the managed disk. - properties: - diskEncryptionSet: - description: |- - DiskEncryptionSet specifies the customer-managed disk encryption set resource id for the - managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and - VMGuest blob. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityEncryptionType: - description: |- - SecurityEncryptionType specifies the encryption type of the managed disk. - It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState - blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. - When set to VMGuestStateOnly, VirtualizedTrustedPlatformModule should be set to Enabled. - When set to DiskWithVMGuestState, EncryptionAtHost should be disabled, SecureBoot and - VirtualizedTrustedPlatformModule should be set to Enabled. - It can be set only for Confidential VMs. - enum: - - VMGuestStateOnly - - DiskWithVMGuestState - type: string - type: object - storageAccountType: - type: string - type: object - osType: - type: string - required: - - osType - type: object - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - roleAssignmentName: - description: 'Deprecated: RoleAssignmentName should be set in the - systemAssignedIdentityRole field.' - type: string - securityProfile: - description: SecurityProfile specifies the Security profile settings - for a virtual machine. - properties: - encryptionAtHost: - description: |- - This field indicates whether Host Encryption should be enabled - or disabled for a virtual machine or virtual machine scale set. - This should be disabled when SecurityEncryptionType is set to DiskWithVMGuestState. - Default is disabled. - type: boolean - securityType: - description: |- - SecurityType specifies the SecurityType of the virtual machine. It has to be set to any specified value to - enable UefiSettings. The default behavior is: UefiSettings will not be enabled unless this property is set. - enum: - - ConfidentialVM - - TrustedLaunch - type: string - uefiSettings: - description: UefiSettings specifies the security settings like - secure boot and vTPM used while creating the virtual machine. - properties: - secureBootEnabled: - description: |- - SecureBootEnabled specifies whether secure boot should be enabled on the virtual machine. - Secure Boot verifies the digital signature of all boot components and halts the boot process if signature verification fails. - If omitted, the platform chooses a default, which is subject to change over time, currently that default is false. - type: boolean - vTpmEnabled: - description: |- - VTpmEnabled specifies whether vTPM should be enabled on the virtual machine. - When true it enables the virtualized trusted platform module measurements to create a known good boot integrity policy baseline. - The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. - This is required to be set to Enabled if SecurityEncryptionType is defined. - If omitted, the platform chooses a default, which is subject to change over time, currently that default is false. - type: boolean - type: object - type: object - spotVMOptions: - description: SpotVMOptions allows the ability to specify the Machine - should use a Spot VM - properties: - evictionPolicy: - description: EvictionPolicy defines the behavior of the virtual - machine when it is evicted. It can be either Delete or Deallocate. - enum: - - Deallocate - - Delete - type: string - maxPrice: - anyOf: - - type: integer - - type: string - description: MaxPrice defines the maximum price the user is willing - to pay for Spot VM instances - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - sshPublicKey: - description: |- - SSHPublicKey is the SSH public key string, base64-encoded to add to a Virtual Machine. Linux only. - Refer to documentation on how to set up SSH access on Windows instances. - type: string - subnetName: - description: 'Deprecated: SubnetName should be set in the networkInterfaces - field.' - type: string - systemAssignedIdentityRole: - description: SystemAssignedIdentityRole defines the role and scope - to assign to the system-assigned identity. - properties: - definitionID: - description: |- - DefinitionID is the ID of the role definition to create for a system assigned identity. It can be an Azure built-in role or a custom role. - Refer to built-in roles: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles - type: string - name: - description: |- - Name is the name of the role assignment to create for a system assigned identity. It can be any valid UUID. - If not specified, a random UUID will be generated. - type: string - scope: - description: |- - Scope is the scope that the role assignment or definition applies to. The scope can be any REST resource instance. - If not specified, the scope will be the subscription. - type: string - type: object - userAssignedIdentities: - description: |- - UserAssignedIdentities is a list of standalone Azure identities provided by the user - The lifecycle of a user-assigned identity is managed separately from the lifecycle of - the AzureMachine. - See https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-cli - items: - description: |- - UserAssignedIdentity defines the user-assigned identities provided - by the user to be assigned to Azure resources. - properties: - providerID: - description: |- - ProviderID is the identification ID of the user-assigned Identity, the format of an identity is: - 'azure:///subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}' - type: string - required: - - providerID - type: object - type: array - vmExtensions: - description: VMExtensions specifies a list of extensions to be added - to the virtual machine. - items: - description: VMExtension specifies the parameters for a custom VM - extension. - properties: - name: - description: Name is the name of the extension. - type: string - protectedSettings: - additionalProperties: - type: string - description: ProtectedSettings is a JSON formatted protected - settings for the extension. - type: object - publisher: - description: Publisher is the name of the extension handler - publisher. - type: string - settings: - additionalProperties: - type: string - description: Settings is a JSON formatted public settings for - the extension. - type: object - version: - description: Version specifies the version of the script handler. - type: string - required: - - name - - publisher - - version - type: object - type: array - vmSize: - type: string - required: - - osDisk - - vmSize - type: object - status: - description: AzureMachineStatus defines the observed state of AzureMachine. - properties: - addresses: - description: Addresses contains the Azure instance associated addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the AzureMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - ErrorMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - ErrorReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - longRunningOperationStates: - description: |- - LongRunningOperationStates saves the states for Azure long-running operations so they can be continued on the - next reconciliation loop. - items: - description: Future contains the data needed for an Azure long-running - operation to continue across reconcile loops. - properties: - data: - description: Data is the base64 url encoded json Azure AutoRest - Future. - type: string - name: - description: |- - Name is the name of the Azure resource. - Together with the service name, this forms the unique identifier for the future. - type: string - resourceGroup: - description: ResourceGroup is the Azure resource group for the - resource. - type: string - serviceName: - description: |- - ServiceName is the name of the Azure service. - Together with the name of the resource, this forms the unique identifier for the future. - type: string - type: - description: Type describes the type of future, such as update, - create, delete, etc. - type: string - required: - - data - - name - - serviceName - - type - type: object - type: array - ready: - description: Ready is true when the provider resource is ready. - type: boolean - vmState: - description: VMState is the provisioning state of the Azure virtual - machine. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 3cc8bf189..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,742 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: azuremachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureMachineTemplate - listKind: AzureMachineTemplateList - plural: azuremachinetemplates - singular: azuremachinetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureMachineTemplate is the Schema for the azuremachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureMachineTemplateSpec defines the desired state of AzureMachineTemplate. - properties: - template: - description: AzureMachineTemplateResource describes the data needed - to create an AzureMachine from a template. - properties: - metadata: - description: |- - ObjectMeta is metadata that all persisted resources must have, which includes all objects - users must create. This is a copy of customizable fields from metav1.ObjectMeta. - - - ObjectMeta is embedded in `Machine.Spec`, `MachineDeployment.Template` and `MachineSet.Template`, - which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases - and read-only fields which end up in the generated CRD validation, having it as a subset simplifies - the API and some issues that can impact user experience. - - - During the [upgrade to controller-tools@v2](https://github.com/kubernetes-sigs/cluster-api/pull/1054) - for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, - specifically `spec.metadata.creationTimestamp in body must be of type string: "null"`. - The investigation showed that `controller-tools@v2` behaves differently than its previous version - when handling types from [metav1](k8s.io/apimachinery/pkg/apis/meta/v1) package. - - - In more details, we found that embedded (non-top level) types that embedded `metav1.ObjectMeta` - had validation properties, including for `creationTimestamp` (metav1.Time). - The `metav1.Time` type specifies a custom json marshaller that, when IsZero() is true, returns `null` - which breaks validation because the field isn't marked as nullable. - - - In future versions, controller-tools@v2 might allow overriding the type and validation for embedded - types. When that happens, this hack should be revisited. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - acceleratedNetworking: - description: 'Deprecated: AcceleratedNetworking should be - set in the networkInterfaces field.' - type: boolean - additionalCapabilities: - description: AdditionalCapabilities specifies additional capabilities - enabled or disabled on the virtual machine. - properties: - ultraSSDEnabled: - description: |- - UltraSSDEnabled enables or disables Azure UltraSSD capability for the virtual machine. - Defaults to true if Ultra SSD data disks are specified, - otherwise it doesn't set the capability on the VM. - type: boolean - type: object - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to an instance, in addition to the ones added by default by the - Azure provider. If both the AzureCluster and the AzureMachine specify the same tag name with different values, the - AzureMachine's value takes precedence. - type: object - allocatePublicIP: - description: AllocatePublicIP allows the ability to create - dynamic public ips for machines where this value is true. - type: boolean - capacityReservationGroupID: - description: |- - CapacityReservationGroupID specifies the capacity reservation group resource id that should be - used for allocating the virtual machine. - type: string - dataDisks: - description: DataDisk specifies the parameters that are used - to add one or more data disks to the machine - items: - description: DataDisk specifies the parameters that are - used to add one or more data disks to the machine. - properties: - cachingType: - description: CachingType specifies the caching requirements. - enum: - - None - - ReadOnly - - ReadWrite - type: string - diskSizeGB: - description: DiskSizeGB is the size in GB to assign - to the data disk. - format: int32 - type: integer - lun: - description: |- - Lun Specifies the logical unit number of the data disk. This value is used to identify data disks within the VM and therefore must be unique for each data disk attached to a VM. - The value must be between 0 and 63. - format: int32 - type: integer - managedDisk: - description: ManagedDisk specifies the Managed Disk - parameters for the data disk. - properties: - diskEncryptionSet: - description: DiskEncryptionSet specifies the customer-managed - disk encryption set resource id for the managed - disk. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityProfile: - description: SecurityProfile specifies the security - profile for the managed disk. - properties: - diskEncryptionSet: - description: |- - DiskEncryptionSet specifies the customer-managed disk encryption set resource id for the - managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and - VMGuest blob. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityEncryptionType: - description: |- - SecurityEncryptionType specifies the encryption type of the managed disk. - It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState - blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. - When set to VMGuestStateOnly, VirtualizedTrustedPlatformModule should be set to Enabled. - When set to DiskWithVMGuestState, EncryptionAtHost should be disabled, SecureBoot and - VirtualizedTrustedPlatformModule should be set to Enabled. - It can be set only for Confidential VMs. - enum: - - VMGuestStateOnly - - DiskWithVMGuestState - type: string - type: object - storageAccountType: - type: string - type: object - nameSuffix: - description: |- - NameSuffix is the suffix to be appended to the machine name to generate the disk name. - Each disk name will be in format _. - type: string - required: - - diskSizeGB - - nameSuffix - type: object - type: array - diagnostics: - description: |- - Diagnostics specifies the diagnostics settings for a virtual machine. - If not specified then Boot diagnostics (Managed) will be enabled. - properties: - boot: - description: |- - Boot configures the boot diagnostics settings for the virtual machine. - This allows to configure capturing serial output from the virtual machine on boot. - This is useful for debugging software based launch issues. - If not specified then Boot diagnostics (Managed) will be enabled. - properties: - storageAccountType: - description: |- - StorageAccountType determines if the storage account for storing the diagnostics data - should be disabled (Disabled), provisioned by Azure (Managed) or by the user (UserManaged). - enum: - - Managed - - UserManaged - - Disabled - type: string - userManaged: - description: UserManaged provides a reference to the - user-managed storage account. - properties: - storageAccountURI: - description: |- - StorageAccountURI is the URI of the user-managed storage account. - The URI typically will be `https://.blob.core.windows.net/` - but may differ if you are using Azure DNS zone endpoints. - You can find the correct endpoint by looking for the Blob Primary Endpoint in the - endpoints tab in the Azure console or with the CLI by issuing - `az storage account list --query='[].{name: name, "resource group": resourceGroup, "blob endpoint": primaryEndpoints.blob}'`. - maxLength: 1024 - pattern: ^https:// - type: string - required: - - storageAccountURI - type: object - required: - - storageAccountType - type: object - type: object - dnsServers: - description: DNSServers adds a list of DNS Server IP addresses - to the VM NICs. - items: - type: string - type: array - enableIPForwarding: - description: |- - EnableIPForwarding enables IP Forwarding in Azure which is required for some CNI's to send traffic from a pods on one machine - to another. This is required for IpV6 with Calico in combination with User Defined Routes (set by the Azure Cloud Controller - manager). Default is false for disabled. - type: boolean - failureDomain: - description: |- - FailureDomain is the failure domain unique identifier this Machine should be attached to, - as defined in Cluster API. This relates to an Azure Availability Zone - type: string - identity: - default: None - description: |- - Identity is the type of identity used for the virtual machine. - The type 'SystemAssigned' is an implicitly created identity. - The generated identity will be assigned a Subscription contributor role. - The type 'UserAssigned' is a standalone Azure resource provided by the user - and assigned to the VM - enum: - - None - - SystemAssigned - - UserAssigned - type: string - image: - description: |- - Image is used to provide details of an image to use during VM creation. - If image details are omitted the image will default the Azure Marketplace "capi" offer, - which is based on Ubuntu. - properties: - computeGallery: - description: ComputeGallery specifies an image to use - from the Azure Compute Gallery - properties: - gallery: - description: Gallery specifies the name of the compute - image gallery that contains the image - minLength: 1 - type: string - name: - description: Name is the name of the image - minLength: 1 - type: string - plan: - description: Plan contains plan information. - properties: - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization - that created the image - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - type: string - required: - - offer - - publisher - - sku - type: object - resourceGroup: - description: ResourceGroup specifies the resource - group containing the private compute gallery. - type: string - subscriptionID: - description: SubscriptionID is the identifier of the - subscription that contains the private compute gallery. - type: string - version: - description: |- - Version specifies the version of the marketplace image. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - gallery - - name - - version - type: object - id: - description: ID specifies an image to use by ID - type: string - marketplace: - description: Marketplace specifies an image to use from - the Azure Marketplace - properties: - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization - that created the image - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - type: string - thirdPartyImage: - default: false - description: |- - ThirdPartyImage indicates the image is published by a third party publisher and a Plan - will be generated for it. - type: boolean - version: - description: |- - Version specifies the version of an image sku. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - offer - - publisher - - sku - - version - type: object - sharedGallery: - description: |- - SharedGallery specifies an image to use from an Azure Shared Image Gallery - Deprecated: use ComputeGallery instead. - properties: - gallery: - description: Gallery specifies the name of the shared - image gallery that contains the image - minLength: 1 - type: string - name: - description: Name is the name of the image - minLength: 1 - type: string - offer: - description: |- - Offer specifies the name of a group of related images created by the publisher. - For example, UbuntuServer, WindowsServer - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - publisher: - description: |- - Publisher is the name of the organization that created the image. - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - resourceGroup: - description: ResourceGroup specifies the resource - group containing the shared image gallery - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - This value will be used to add a `Plan` in the API request when creating the VM/VMSS resource. - This is needed when the source image from which this SIG image was built requires the `Plan` to be used. - type: string - subscriptionID: - description: SubscriptionID is the identifier of the - subscription that contains the shared image gallery - minLength: 1 - type: string - version: - description: |- - Version specifies the version of the marketplace image. The allowed formats - are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. - Specify 'latest' to use the latest version of an image available at deploy time. - Even if you use 'latest', the VM image will not automatically update after deploy - time even if a new version becomes available. - minLength: 1 - type: string - required: - - gallery - - name - - resourceGroup - - subscriptionID - - version - type: object - type: object - networkInterfaces: - description: |- - NetworkInterfaces specifies a list of network interface configurations. - If left unspecified, the VM will get a single network interface with a - single IPConfig in the subnet specified in the cluster's node subnet field. - The primary interface will be the first networkInterface specified (index 0) in the list. - items: - description: NetworkInterface defines a network interface. - properties: - acceleratedNetworking: - description: |- - AcceleratedNetworking enables or disables Azure accelerated networking. If omitted, it will be set based on - whether the requested VMSize supports accelerated networking. - If AcceleratedNetworking is set to true with a VMSize that does not support it, Azure will return an error. - type: boolean - privateIPConfigs: - description: |- - PrivateIPConfigs specifies the number of private IP addresses to attach to the interface. - Defaults to 1 if not specified. - type: integer - subnetName: - description: SubnetName specifies the subnet in which - the new network interface will be placed. - type: string - type: object - type: array - osDisk: - description: OSDisk specifies the parameters for the operating - system disk of the machine - properties: - cachingType: - description: CachingType specifies the caching requirements. - enum: - - None - - ReadOnly - - ReadWrite - type: string - diffDiskSettings: - description: DiffDiskSettings describe ephemeral disk - settings for the os disk. - properties: - option: - description: |- - Option enables ephemeral OS when set to "Local" - See https://learn.microsoft.com/azure/virtual-machines/ephemeral-os-disks for full details - enum: - - Local - type: string - required: - - option - type: object - diskSizeGB: - description: |- - DiskSizeGB is the size in GB to assign to the OS disk. - Will have a default of 30GB if not provided - format: int32 - type: integer - managedDisk: - description: ManagedDisk specifies the Managed Disk parameters - for the OS disk. - properties: - diskEncryptionSet: - description: DiskEncryptionSet specifies the customer-managed - disk encryption set resource id for the managed - disk. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityProfile: - description: SecurityProfile specifies the security - profile for the managed disk. - properties: - diskEncryptionSet: - description: |- - DiskEncryptionSet specifies the customer-managed disk encryption set resource id for the - managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and - VMGuest blob. - properties: - id: - description: ID defines resourceID for diskEncryptionSet - resource. It must be in the same subscription - type: string - type: object - securityEncryptionType: - description: |- - SecurityEncryptionType specifies the encryption type of the managed disk. - It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState - blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. - When set to VMGuestStateOnly, VirtualizedTrustedPlatformModule should be set to Enabled. - When set to DiskWithVMGuestState, EncryptionAtHost should be disabled, SecureBoot and - VirtualizedTrustedPlatformModule should be set to Enabled. - It can be set only for Confidential VMs. - enum: - - VMGuestStateOnly - - DiskWithVMGuestState - type: string - type: object - storageAccountType: - type: string - type: object - osType: - type: string - required: - - osType - type: object - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - roleAssignmentName: - description: 'Deprecated: RoleAssignmentName should be set - in the systemAssignedIdentityRole field.' - type: string - securityProfile: - description: SecurityProfile specifies the Security profile - settings for a virtual machine. - properties: - encryptionAtHost: - description: |- - This field indicates whether Host Encryption should be enabled - or disabled for a virtual machine or virtual machine scale set. - This should be disabled when SecurityEncryptionType is set to DiskWithVMGuestState. - Default is disabled. - type: boolean - securityType: - description: |- - SecurityType specifies the SecurityType of the virtual machine. It has to be set to any specified value to - enable UefiSettings. The default behavior is: UefiSettings will not be enabled unless this property is set. - enum: - - ConfidentialVM - - TrustedLaunch - type: string - uefiSettings: - description: UefiSettings specifies the security settings - like secure boot and vTPM used while creating the virtual - machine. - properties: - secureBootEnabled: - description: |- - SecureBootEnabled specifies whether secure boot should be enabled on the virtual machine. - Secure Boot verifies the digital signature of all boot components and halts the boot process if signature verification fails. - If omitted, the platform chooses a default, which is subject to change over time, currently that default is false. - type: boolean - vTpmEnabled: - description: |- - VTpmEnabled specifies whether vTPM should be enabled on the virtual machine. - When true it enables the virtualized trusted platform module measurements to create a known good boot integrity policy baseline. - The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. - This is required to be set to Enabled if SecurityEncryptionType is defined. - If omitted, the platform chooses a default, which is subject to change over time, currently that default is false. - type: boolean - type: object - type: object - spotVMOptions: - description: SpotVMOptions allows the ability to specify the - Machine should use a Spot VM - properties: - evictionPolicy: - description: EvictionPolicy defines the behavior of the - virtual machine when it is evicted. It can be either - Delete or Deallocate. - enum: - - Deallocate - - Delete - type: string - maxPrice: - anyOf: - - type: integer - - type: string - description: MaxPrice defines the maximum price the user - is willing to pay for Spot VM instances - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - sshPublicKey: - description: |- - SSHPublicKey is the SSH public key string, base64-encoded to add to a Virtual Machine. Linux only. - Refer to documentation on how to set up SSH access on Windows instances. - type: string - subnetName: - description: 'Deprecated: SubnetName should be set in the - networkInterfaces field.' - type: string - systemAssignedIdentityRole: - description: SystemAssignedIdentityRole defines the role and - scope to assign to the system-assigned identity. - properties: - definitionID: - description: |- - DefinitionID is the ID of the role definition to create for a system assigned identity. It can be an Azure built-in role or a custom role. - Refer to built-in roles: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles - type: string - name: - description: |- - Name is the name of the role assignment to create for a system assigned identity. It can be any valid UUID. - If not specified, a random UUID will be generated. - type: string - scope: - description: |- - Scope is the scope that the role assignment or definition applies to. The scope can be any REST resource instance. - If not specified, the scope will be the subscription. - type: string - type: object - userAssignedIdentities: - description: |- - UserAssignedIdentities is a list of standalone Azure identities provided by the user - The lifecycle of a user-assigned identity is managed separately from the lifecycle of - the AzureMachine. - See https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-cli - items: - description: |- - UserAssignedIdentity defines the user-assigned identities provided - by the user to be assigned to Azure resources. - properties: - providerID: - description: |- - ProviderID is the identification ID of the user-assigned Identity, the format of an identity is: - 'azure:///subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}' - type: string - required: - - providerID - type: object - type: array - vmExtensions: - description: VMExtensions specifies a list of extensions to - be added to the virtual machine. - items: - description: VMExtension specifies the parameters for a - custom VM extension. - properties: - name: - description: Name is the name of the extension. - type: string - protectedSettings: - additionalProperties: - type: string - description: ProtectedSettings is a JSON formatted protected - settings for the extension. - type: object - publisher: - description: Publisher is the name of the extension - handler publisher. - type: string - settings: - additionalProperties: - type: string - description: Settings is a JSON formatted public settings - for the extension. - type: object - version: - description: Version specifies the version of the script - handler. - type: string - required: - - name - - publisher - - version - type: object - type: array - vmSize: - type: string - required: - - osDisk - - vmSize - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 0be51ac60..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,95 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedCluster - listKind: AzureManagedClusterList - plural: azuremanagedclusters - shortNames: - - amc - singular: azuremanagedcluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AzureManagedCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - jsonPath: .status.ready - name: Ready - type: string - - description: Time duration since creation of this AzureManagedCluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedCluster is the Schema for the azuremanagedclusters - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedClusterSpec defines the desired state of AzureManagedCluster. - properties: - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. - Immutable, populated by the AKS API at create. - Because this field is programmatically set by CAPZ after resource creation, we define it as +optional - in the API schema to permit resource admission. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - type: object - status: - description: AzureManagedClusterStatus defines the observed state of AzureManagedCluster. - properties: - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 84cc9adf8..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedClusterTemplate - listKind: AzureManagedClusterTemplateList - plural: azuremanagedclustertemplates - shortNames: - - amct - singular: azuremanagedclustertemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedClusterTemplate is the Schema for the AzureManagedClusterTemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedClusterTemplateSpec defines the desired state - of AzureManagedClusterTemplate. - properties: - template: - description: AzureManagedClusterTemplateResource describes the data - needed to create an AzureManagedCluster from a template. - properties: - spec: - description: AzureManagedClusterTemplateResourceSpec specifies - an Azure managed cluster template resource. - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanes.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanes.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index d25a51526..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanes.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1016 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedcontrolplanes.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedControlPlane - listKind: AzureManagedControlPlaneList - plural: azuremanagedcontrolplanes - shortNames: - - amcp - singular: azuremanagedcontrolplane - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AzureManagedControlPlane belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].severity - name: Severity - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].message - name: Message - priority: 1 - type: string - - description: Time duration since creation of this AzureManagedControlPlane - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedControlPlane is the Schema for the azuremanagedcontrolplanes - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedControlPlaneSpec defines the desired state of - AzureManagedControlPlane. - properties: - aadProfile: - description: AadProfile is Azure Active Directory configuration to - integrate with AKS for aad authentication. - properties: - adminGroupObjectIDs: - description: AdminGroupObjectIDs - AAD group object IDs that will - have admin role of the cluster. - items: - type: string - type: array - managed: - description: Managed - Whether to enable managed AAD. - type: boolean - required: - - adminGroupObjectIDs - - managed - type: object - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the Azure provider, in addition to the - ones added by default. - type: object - addonProfiles: - description: AddonProfiles are the profiles of managed cluster add-on. - items: - description: AddonProfile represents a managed cluster add-on. - properties: - config: - additionalProperties: - type: string - description: Config - Key-value pairs for configuring the add-on. - type: object - enabled: - description: Enabled - Whether the add-on is enabled or not. - type: boolean - name: - description: Name - The name of the managed cluster add-on. - type: string - required: - - enabled - - name - type: object - type: array - apiServerAccessProfile: - description: |- - APIServerAccessProfile is the access profile for AKS API server. - Immutable except for `authorizedIPRanges`. - properties: - authorizedIPRanges: - description: AuthorizedIPRanges - Authorized IP Ranges to kubernetes - API server. - items: - type: string - type: array - enablePrivateCluster: - description: EnablePrivateCluster indicates whether to create - the cluster as a private cluster or not. - type: boolean - enablePrivateClusterPublicFQDN: - description: EnablePrivateClusterPublicFQDN indicates whether - to create additional public FQDN for private cluster or not. - type: boolean - privateDNSZone: - description: PrivateDNSZone enables private dns zone mode for - private cluster. - type: string - type: object - asoManagedClusterPatches: - description: |- - ASOManagedClusterPatches defines JSON merge patches to be applied to the generated ASO ManagedCluster resource. - WARNING: This is meant to be used sparingly to enable features for development and testing that are not - otherwise represented in the CAPZ API. Misconfiguration that conflicts with CAPZ's normal mode of - operation is possible. - items: - type: string - type: array - autoUpgradeProfile: - description: AutoUpgradeProfile defines the auto upgrade configuration. - properties: - upgradeChannel: - description: UpgradeChannel determines the type of upgrade channel - for automatically upgrading the cluster. - enum: - - node-image - - none - - patch - - rapid - - stable - type: string - type: object - autoscalerProfile: - description: AutoscalerProfile is the parameters to be applied to - the cluster-autoscaler when enabled - properties: - balanceSimilarNodeGroups: - description: BalanceSimilarNodeGroups - Valid values are 'true' - and 'false'. The default is false. - enum: - - "true" - - "false" - type: string - expander: - description: Expander - If not specified, the default is 'random'. - See [expanders](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-expanders) - for more information. - enum: - - least-waste - - most-pods - - priority - - random - type: string - maxEmptyBulkDelete: - description: MaxEmptyBulkDelete - The default is 10. - type: string - maxGracefulTerminationSec: - description: MaxGracefulTerminationSec - The default is 600. - pattern: ^(\d+)$ - type: string - maxNodeProvisionTime: - description: MaxNodeProvisionTime - The default is '15m'. Values - must be an integer followed by an 'm'. No unit of time other - than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - maxTotalUnreadyPercentage: - description: MaxTotalUnreadyPercentage - The default is 45. The - maximum is 100 and the minimum is 0. - maxLength: 3 - minLength: 1 - pattern: ^(\d+)$ - type: string - newPodScaleUpDelay: - description: NewPodScaleUpDelay - For scenarios like burst/batch - scale where you don't want CA to act before the kubernetes scheduler - could schedule all the pods, you can tell CA to ignore unscheduled - pods before they're a certain age. The default is '0s'. Values - must be an integer followed by a unit ('s' for seconds, 'm' - for minutes, 'h' for hours, etc). - type: string - okTotalUnreadyCount: - description: OkTotalUnreadyCount - This must be an integer. The - default is 3. - pattern: ^(\d+)$ - type: string - scaleDownDelayAfterAdd: - description: ScaleDownDelayAfterAdd - The default is '10m'. Values - must be an integer followed by an 'm'. No unit of time other - than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownDelayAfterDelete: - description: ScaleDownDelayAfterDelete - The default is the scan-interval. - Values must be an integer followed by an 's'. No unit of time - other than seconds (s) is supported. - pattern: ^(\d+)s$ - type: string - scaleDownDelayAfterFailure: - description: ScaleDownDelayAfterFailure - The default is '3m'. - Values must be an integer followed by an 'm'. No unit of time - other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUnneededTime: - description: ScaleDownUnneededTime - The default is '10m'. Values - must be an integer followed by an 'm'. No unit of time other - than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUnreadyTime: - description: ScaleDownUnreadyTime - The default is '20m'. Values - must be an integer followed by an 'm'. No unit of time other - than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUtilizationThreshold: - description: ScaleDownUtilizationThreshold - The default is '0.5'. - type: string - scanInterval: - description: ScanInterval - How often cluster is reevaluated for - scale up or down. The default is '10s'. - pattern: ^(\d+)s$ - type: string - skipNodesWithLocalStorage: - description: SkipNodesWithLocalStorage - The default is false. - enum: - - "true" - - "false" - type: string - skipNodesWithSystemPods: - description: SkipNodesWithSystemPods - The default is true. - enum: - - "true" - - "false" - type: string - type: object - azureEnvironment: - description: |- - AzureEnvironment is the name of the AzureCloud to be used. - The default value that would be used by most users is "AzurePublicCloud", other values are: - - ChinaCloud: "AzureChinaCloud" - - PublicCloud: "AzurePublicCloud" - - USGovernmentCloud: "AzureUSGovernmentCloud" - - - Note that values other than the default must also be accompanied by corresponding changes to the - aso-controller-settings Secret to configure ASO to refer to the non-Public cloud. ASO currently does - not support referring to multiple different clouds in a single installation. The following fields must - be defined in the Secret: - - AZURE_AUTHORITY_HOST - - AZURE_RESOURCE_MANAGER_ENDPOINT - - AZURE_RESOURCE_MANAGER_AUDIENCE - - - See the [ASO docs] for more details. - - - [ASO docs]: https://azure.github.io/azure-service-operator/guide/aso-controller-settings-options/ - type: string - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. - Immutable, populated by the AKS API at create. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - disableLocalAccounts: - description: DisableLocalAccounts disables getting static credentials - for this cluster when set. Expected to only be used for AAD clusters. - type: boolean - dnsPrefix: - description: |- - DNSPrefix allows the user to customize dns prefix. - Immutable. - type: string - dnsServiceIP: - description: |- - DNSServiceIP is an IP address assigned to the Kubernetes DNS service. - It must be within the Kubernetes service address range specified in serviceCidr. - Immutable. - type: string - enablePreviewFeatures: - description: EnablePreviewFeatures enables preview features for the - cluster. - type: boolean - extensions: - description: Extensions is a list of AKS extensions to be installed - on the cluster. - items: - description: |- - AKSExtension represents the configuration for an AKS cluster extension. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/aks/cluster-extensions - properties: - aksAssignedIdentityType: - description: AKSAssignedIdentityType is the type of the AKS - assigned identity. - enum: - - SystemAssigned - - UserAssigned - type: string - autoUpgradeMinorVersion: - default: true - description: AutoUpgradeMinorVersion is a flag to note if this - extension participates in auto upgrade of minor version, or - not. - type: boolean - configurationSettings: - additionalProperties: - type: string - description: ConfigurationSettings are the name-value pairs - for configuring this extension. - type: object - extensionType: - description: |- - ExtensionType is the type of the Extension of which this resource is an instance. - It must be one of the Extension Types registered with Microsoft.KubernetesConfiguration by the Extension publisher. - type: string - identity: - description: Identity is the identity type of the Extension - resource in an AKS cluster. - enum: - - SystemAssigned - type: string - name: - description: Name is the name of the extension. - type: string - plan: - description: Plan is the plan of the extension. - properties: - name: - description: Name is the user-defined name of the 3rd Party - Artifact that is being procured. - type: string - product: - description: Product is the name of the 3rd Party artifact - that is being procured. - type: string - promotionCode: - description: PromotionCode is a publisher-provided promotion - code as provisioned in Data Market for the said product/artifact. - type: string - publisher: - description: Publisher is the name of the publisher of the - 3rd Party Artifact that is being bought. - type: string - version: - description: Version is the version of the plan. - type: string - type: object - releaseTrain: - description: |- - ReleaseTrain is the release train this extension participates in for auto-upgrade (e.g. Stable, Preview, etc.) - This is only used if autoUpgradeMinorVersion is ‘true’. - type: string - scope: - description: Scope is the scope at which this extension is enabled. - properties: - releaseNamespace: - description: |- - ReleaseNamespace is the namespace where the extension Release must be placed, for a Cluster-scoped extension. - Required for Cluster-scoped extensions. - type: string - scopeType: - description: ScopeType is the scope of the extension. It - can be either Cluster or Namespace, but not both. - enum: - - Cluster - - Namespace - type: string - targetNamespace: - description: |- - TargetNamespace is the namespace where the extension will be created for a Namespace-scoped extension. - Required for Namespace-scoped extensions. - type: string - required: - - scopeType - type: object - version: - description: Version is the version of the extension. - type: string - required: - - extensionType - - name - type: object - type: array - fleetsMember: - description: |- - FleetsMember is the spec for the fleet this cluster is a member of. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/templates/microsoft.containerservice/2023-03-15-preview/fleets/members - properties: - group: - description: Group is the group this member belongs to for multi-cluster - update management. - type: string - managerName: - description: ManagerName is the name of the fleet manager. - type: string - managerResourceGroup: - description: ManagerResourceGroup is the resource group of the - fleet manager. - type: string - name: - description: Name is the name of the member. - type: string - required: - - managerName - - managerResourceGroup - type: object - httpProxyConfig: - description: |- - HTTPProxyConfig is the HTTP proxy configuration for the cluster. - Immutable. - properties: - httpProxy: - description: HTTPProxy is the HTTP proxy server endpoint to use. - type: string - httpsProxy: - description: HTTPSProxy is the HTTPS proxy server endpoint to - use. - type: string - noProxy: - description: NoProxy indicates the endpoints that should not go - through proxy. - items: - type: string - type: array - trustedCa: - description: TrustedCA is the alternative CA cert to use for connecting - to proxy servers. - type: string - type: object - identity: - description: Identity configuration used by the AKS control plane. - properties: - type: - description: Type - The Identity type to use. - enum: - - SystemAssigned - - UserAssigned - type: string - userAssignedIdentityResourceID: - description: UserAssignedIdentityResourceID - Identity ARM resource - ID when using user-assigned identity. - type: string - type: object - identityRef: - description: IdentityRef is a reference to a AzureClusterIdentity - to be used when reconciling this cluster - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - kubeletUserAssignedIdentity: - description: |- - KubeletUserAssignedIdentity is the user-assigned identity for kubelet. - For authentication with Azure Container Registry. - type: string - loadBalancerProfile: - description: LoadBalancerProfile is the profile of the cluster load - balancer. - properties: - allocatedOutboundPorts: - description: AllocatedOutboundPorts - Desired number of allocated - SNAT ports per VM. Allowed values must be in the range of 0 - to 64000 (inclusive). The default value is 0 which results in - Azure dynamically allocating ports. - type: integer - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes - Desired outbound flow idle - timeout in minutes. Allowed values must be in the range of 4 - to 120 (inclusive). The default value is 30 minutes. - type: integer - managedOutboundIPs: - description: ManagedOutboundIPs - Desired managed outbound IPs - for the cluster load balancer. - type: integer - outboundIPPrefixes: - description: OutboundIPPrefixes - Desired outbound IP Prefix resources - for the cluster load balancer. - items: - type: string - type: array - outboundIPs: - description: OutboundIPs - Desired outbound IP resources for the - cluster load balancer. - items: - type: string - type: array - type: object - loadBalancerSKU: - default: Standard - description: |- - LoadBalancerSKU is the SKU of the loadBalancer to be provisioned. - Immutable. - enum: - - Basic - - Standard - type: string - location: - description: 'Location is a string matching one of the canonical Azure - region names. Examples: "westus2", "eastus".' - type: string - machineTemplate: - description: |- - MachineTemplate contains information about how machines - should be shaped when creating or updating a control plane. - For the AzureManagedControlPlaneTemplate, this field is used - only to fulfill the CAPI contract. - type: object - networkDataplane: - description: NetworkDataplane is the dataplane used for building the - Kubernetes network. - enum: - - azure - - cilium - type: string - networkPlugin: - description: NetworkPlugin used for building Kubernetes network. - enum: - - azure - - kubenet - - none - type: string - networkPluginMode: - description: |- - NetworkPluginMode is the mode the network plugin should use. - Allowed value is "overlay". - enum: - - overlay - type: string - networkPolicy: - description: NetworkPolicy used for building Kubernetes network. - enum: - - azure - - calico - - cilium - type: string - nodeResourceGroupName: - description: |- - NodeResourceGroupName is the name of the resource group - containing cluster IaaS resources. Will be populated to default - in webhook. - Immutable. - type: string - oidcIssuerProfile: - description: OIDCIssuerProfile is the OIDC issuer profile of the Managed - Cluster. - properties: - enabled: - description: Enabled is whether the OIDC issuer is enabled. - type: boolean - type: object - outboundType: - description: Outbound configuration used by Nodes. - enum: - - loadBalancer - - managedNATGateway - - userAssignedNATGateway - - userDefinedRouting - type: string - resourceGroupName: - description: |- - ResourceGroupName is the name of the Azure resource group for this AKS Cluster. - Immutable. - type: string - securityProfile: - description: SecurityProfile defines the security profile for cluster. - properties: - azureKeyVaultKms: - description: AzureKeyVaultKms defines Azure Key Vault Management - Services Profile for the security profile. - properties: - enabled: - description: Enabled enables the Azure Key Vault key management - service. The default is false. - type: boolean - keyID: - description: |- - KeyID defines the Identifier of Azure Key Vault key. - When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier. - type: string - keyVaultNetworkAccess: - default: Public - description: |- - KeyVaultNetworkAccess defines the network access of key vault. - The possible values are Public and Private. - Public means the key vault allows public access from all networks. - Private means the key vault disables public access and enables private link. The default value is Public. - type: string - keyVaultResourceID: - description: KeyVaultResourceID is the Resource ID of key - vault. When keyVaultNetworkAccess is Private, this field - is required and must be a valid resource ID. - type: string - required: - - enabled - - keyID - type: object - defender: - description: Defender settings for the security profile. - properties: - logAnalyticsWorkspaceResourceID: - description: |- - LogAnalyticsWorkspaceResourceID is the ID of the Log Analytics workspace that has to be associated with Microsoft Defender. - When Microsoft Defender is enabled, this field is required and must be a valid workspace resource ID. - type: string - securityMonitoring: - description: SecurityMonitoring profile defines the Microsoft - Defender threat detection for Cloud settings for the security - profile. - properties: - enabled: - description: Enabled enables Defender threat detection - type: boolean - required: - - enabled - type: object - required: - - logAnalyticsWorkspaceResourceID - - securityMonitoring - type: object - imageCleaner: - description: ImageCleaner settings for the security profile. - properties: - enabled: - description: Enabled enables the Image Cleaner on AKS cluster. - type: boolean - intervalHours: - description: IntervalHours defines Image Cleaner scanning - interval in hours. Default value is 24 hours. - maximum: 2160 - minimum: 24 - type: integer - required: - - enabled - type: object - workloadIdentity: - description: Workloadidentity enables Kubernetes applications - to access Azure cloud resources securely with Azure AD. Ensure - to enable OIDC issuer while enabling Workload Identity - properties: - enabled: - description: Enabled enables the workload identity. - type: boolean - required: - - enabled - type: object - type: object - sku: - description: SKU is the SKU of the AKS to be provisioned. - properties: - tier: - description: Tier - Tier of an AKS cluster. - enum: - - Free - - Paid - - Standard - type: string - required: - - tier - type: object - sshPublicKey: - description: |- - SSHPublicKey is a string literal containing an ssh public key base64 encoded. - Use empty string to autogenerate new key. Use null value to not set key. - Immutable. - type: string - subscriptionID: - description: SubscriptionID is the GUID of the Azure subscription - that owns this cluster. - type: string - version: - description: Version defines the desired Kubernetes version. - minLength: 2 - type: string - virtualNetwork: - description: VirtualNetwork describes the virtual network for the - AKS cluster. It will be created if it does not already exist. - properties: - cidrBlock: - type: string - name: - description: Name is the name of the virtual network. - type: string - resourceGroup: - description: ResourceGroup is the name of the Azure resource group - for the VNet and Subnet. - type: string - subnet: - description: ManagedControlPlaneSubnet describes a subnet for - an AKS cluster. - properties: - cidrBlock: - type: string - name: - type: string - privateEndpoints: - description: PrivateEndpoints is a slice of Virtual Network - private endpoints to create for the subnets. - items: - description: PrivateEndpointSpec configures an Azure Private - Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies the - Application security group in which the private endpoint - IP configuration is included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName specifies the - network interface name associated with the private - endpoint. - type: string - location: - description: Location specifies the region to create - the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of the private - endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections specifies - Private Link Service Connections of the private endpoint. - items: - description: PrivateLinkServiceConnection defines - the specification for a private link service connection - associated with a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the ID(s) of the - group(s) obtained from the remote resource that - this private endpoint should connect to. - items: - type: string - type: array - name: - description: Name specifies the name of the private - link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID specifies the - resource ID of the private link service. - type: string - requestMessage: - description: RequestMessage specifies a message - passed to the owner of the remote resource with - the private endpoint connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual Network - service endpoints to enable for the subnets. - items: - description: ServiceEndpointSpec configures an Azure Service - Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - cidrBlock - - name - type: object - required: - - cidrBlock - - name - type: object - required: - - identityRef - - location - - resourceGroupName - - version - type: object - status: - description: AzureManagedControlPlaneStatus defines the observed state - of AzureManagedControlPlane. - properties: - autoUpgradeVersion: - description: AutoUpgradeVersion is the Kubernetes version populated - after auto-upgrade based on the upgrade channel. - minLength: 2 - type: string - conditions: - description: Conditions defines current service state of the AzureManagedControlPlane. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - initialized: - description: |- - Initialized is true when the control plane is available for initial contact. - This may occur before the control plane is fully ready. - In the AzureManagedControlPlane implementation, these are identical. - type: boolean - longRunningOperationStates: - description: |- - LongRunningOperationStates saves the states for Azure long-running operations so they can be continued on the - next reconciliation loop. - items: - description: Future contains the data needed for an Azure long-running - operation to continue across reconcile loops. - properties: - data: - description: Data is the base64 url encoded json Azure AutoRest - Future. - type: string - name: - description: |- - Name is the name of the Azure resource. - Together with the service name, this forms the unique identifier for the future. - type: string - resourceGroup: - description: ResourceGroup is the Azure resource group for the - resource. - type: string - serviceName: - description: |- - ServiceName is the name of the Azure service. - Together with the name of the resource, this forms the unique identifier for the future. - type: string - type: - description: Type describes the type of future, such as update, - create, delete, etc. - type: string - required: - - data - - name - - serviceName - - type - type: object - type: array - oidcIssuerProfile: - description: OIDCIssuerProfile is the OIDC issuer profile of the Managed - Cluster. - properties: - issuerURL: - description: IssuerURL is the OIDC issuer url of the Managed Cluster. - type: string - type: object - ready: - description: Ready is true when the provider resource is ready. - type: boolean - version: - description: Version defines the Kubernetes version for the control - plane instance. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 70e4afb84..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedcontrolplanetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,885 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedcontrolplanetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedControlPlaneTemplate - listKind: AzureManagedControlPlaneTemplateList - plural: azuremanagedcontrolplanetemplates - shortNames: - - amcpt - singular: azuremanagedcontrolplanetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedControlPlaneTemplate is the Schema for the AzureManagedControlPlaneTemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedControlPlaneTemplateSpec defines the desired - state of AzureManagedControlPlaneTemplate. - properties: - template: - description: AzureManagedControlPlaneTemplateResource describes the - data needed to create an AzureManagedCluster from a template. - properties: - spec: - description: AzureManagedControlPlaneTemplateResourceSpec specifies - an Azure managed control plane template resource. - properties: - aadProfile: - description: AadProfile is Azure Active Directory configuration - to integrate with AKS for aad authentication. - properties: - adminGroupObjectIDs: - description: AdminGroupObjectIDs - AAD group object IDs - that will have admin role of the cluster. - items: - type: string - type: array - managed: - description: Managed - Whether to enable managed AAD. - type: boolean - required: - - adminGroupObjectIDs - - managed - type: object - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the Azure provider, in addition to the - ones added by default. - type: object - addonProfiles: - description: AddonProfiles are the profiles of managed cluster - add-on. - items: - description: AddonProfile represents a managed cluster add-on. - properties: - config: - additionalProperties: - type: string - description: Config - Key-value pairs for configuring - the add-on. - type: object - enabled: - description: Enabled - Whether the add-on is enabled - or not. - type: boolean - name: - description: Name - The name of the managed cluster - add-on. - type: string - required: - - enabled - - name - type: object - type: array - apiServerAccessProfile: - description: |- - APIServerAccessProfile is the access profile for AKS API server. - Immutable except for `authorizedIPRanges`. - properties: - authorizedIPRanges: - description: AuthorizedIPRanges - Authorized IP Ranges - to kubernetes API server. - items: - type: string - type: array - enablePrivateCluster: - description: EnablePrivateCluster indicates whether to - create the cluster as a private cluster or not. - type: boolean - enablePrivateClusterPublicFQDN: - description: EnablePrivateClusterPublicFQDN indicates - whether to create additional public FQDN for private - cluster or not. - type: boolean - privateDNSZone: - description: PrivateDNSZone enables private dns zone mode - for private cluster. - type: string - type: object - asoManagedClusterPatches: - description: |- - ASOManagedClusterPatches defines JSON merge patches to be applied to the generated ASO ManagedCluster resource. - WARNING: This is meant to be used sparingly to enable features for development and testing that are not - otherwise represented in the CAPZ API. Misconfiguration that conflicts with CAPZ's normal mode of - operation is possible. - items: - type: string - type: array - autoUpgradeProfile: - description: AutoUpgradeProfile defines the auto upgrade configuration. - properties: - upgradeChannel: - description: UpgradeChannel determines the type of upgrade - channel for automatically upgrading the cluster. - enum: - - node-image - - none - - patch - - rapid - - stable - type: string - type: object - autoscalerProfile: - description: AutoscalerProfile is the parameters to be applied - to the cluster-autoscaler when enabled - properties: - balanceSimilarNodeGroups: - description: BalanceSimilarNodeGroups - Valid values are - 'true' and 'false'. The default is false. - enum: - - "true" - - "false" - type: string - expander: - description: Expander - If not specified, the default - is 'random'. See [expanders](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-expanders) - for more information. - enum: - - least-waste - - most-pods - - priority - - random - type: string - maxEmptyBulkDelete: - description: MaxEmptyBulkDelete - The default is 10. - type: string - maxGracefulTerminationSec: - description: MaxGracefulTerminationSec - The default is - 600. - pattern: ^(\d+)$ - type: string - maxNodeProvisionTime: - description: MaxNodeProvisionTime - The default is '15m'. - Values must be an integer followed by an 'm'. No unit - of time other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - maxTotalUnreadyPercentage: - description: MaxTotalUnreadyPercentage - The default is - 45. The maximum is 100 and the minimum is 0. - maxLength: 3 - minLength: 1 - pattern: ^(\d+)$ - type: string - newPodScaleUpDelay: - description: NewPodScaleUpDelay - For scenarios like burst/batch - scale where you don't want CA to act before the kubernetes - scheduler could schedule all the pods, you can tell - CA to ignore unscheduled pods before they're a certain - age. The default is '0s'. Values must be an integer - followed by a unit ('s' for seconds, 'm' for minutes, - 'h' for hours, etc). - type: string - okTotalUnreadyCount: - description: OkTotalUnreadyCount - This must be an integer. - The default is 3. - pattern: ^(\d+)$ - type: string - scaleDownDelayAfterAdd: - description: ScaleDownDelayAfterAdd - The default is '10m'. - Values must be an integer followed by an 'm'. No unit - of time other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownDelayAfterDelete: - description: ScaleDownDelayAfterDelete - The default is - the scan-interval. Values must be an integer followed - by an 's'. No unit of time other than seconds (s) is - supported. - pattern: ^(\d+)s$ - type: string - scaleDownDelayAfterFailure: - description: ScaleDownDelayAfterFailure - The default - is '3m'. Values must be an integer followed by an 'm'. - No unit of time other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUnneededTime: - description: ScaleDownUnneededTime - The default is '10m'. - Values must be an integer followed by an 'm'. No unit - of time other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUnreadyTime: - description: ScaleDownUnreadyTime - The default is '20m'. - Values must be an integer followed by an 'm'. No unit - of time other than minutes (m) is supported. - pattern: ^(\d+)m$ - type: string - scaleDownUtilizationThreshold: - description: ScaleDownUtilizationThreshold - The default - is '0.5'. - type: string - scanInterval: - description: ScanInterval - How often cluster is reevaluated - for scale up or down. The default is '10s'. - pattern: ^(\d+)s$ - type: string - skipNodesWithLocalStorage: - description: SkipNodesWithLocalStorage - The default is - false. - enum: - - "true" - - "false" - type: string - skipNodesWithSystemPods: - description: SkipNodesWithSystemPods - The default is - true. - enum: - - "true" - - "false" - type: string - type: object - azureEnvironment: - description: |- - AzureEnvironment is the name of the AzureCloud to be used. - The default value that would be used by most users is "AzurePublicCloud", other values are: - - ChinaCloud: "AzureChinaCloud" - - PublicCloud: "AzurePublicCloud" - - USGovernmentCloud: "AzureUSGovernmentCloud" - - - Note that values other than the default must also be accompanied by corresponding changes to the - aso-controller-settings Secret to configure ASO to refer to the non-Public cloud. ASO currently does - not support referring to multiple different clouds in a single installation. The following fields must - be defined in the Secret: - - AZURE_AUTHORITY_HOST - - AZURE_RESOURCE_MANAGER_ENDPOINT - - AZURE_RESOURCE_MANAGER_AUDIENCE - - - See the [ASO docs] for more details. - - - [ASO docs]: https://azure.github.io/azure-service-operator/guide/aso-controller-settings-options/ - type: string - disableLocalAccounts: - description: DisableLocalAccounts disables getting static - credentials for this cluster when set. Expected to only - be used for AAD clusters. - type: boolean - dnsServiceIP: - description: |- - DNSServiceIP is an IP address assigned to the Kubernetes DNS service. - It must be within the Kubernetes service address range specified in serviceCidr. - Immutable. - type: string - enablePreviewFeatures: - description: EnablePreviewFeatures enables preview features - for the cluster. - type: boolean - extensions: - description: Extensions is a list of AKS extensions to be - installed on the cluster. - items: - description: |- - AKSExtension represents the configuration for an AKS cluster extension. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/aks/cluster-extensions - properties: - aksAssignedIdentityType: - description: AKSAssignedIdentityType is the type of - the AKS assigned identity. - enum: - - SystemAssigned - - UserAssigned - type: string - autoUpgradeMinorVersion: - default: true - description: AutoUpgradeMinorVersion is a flag to note - if this extension participates in auto upgrade of - minor version, or not. - type: boolean - configurationSettings: - additionalProperties: - type: string - description: ConfigurationSettings are the name-value - pairs for configuring this extension. - type: object - extensionType: - description: |- - ExtensionType is the type of the Extension of which this resource is an instance. - It must be one of the Extension Types registered with Microsoft.KubernetesConfiguration by the Extension publisher. - type: string - identity: - description: Identity is the identity type of the Extension - resource in an AKS cluster. - enum: - - SystemAssigned - type: string - name: - description: Name is the name of the extension. - type: string - plan: - description: Plan is the plan of the extension. - properties: - name: - description: Name is the user-defined name of the - 3rd Party Artifact that is being procured. - type: string - product: - description: Product is the name of the 3rd Party - artifact that is being procured. - type: string - promotionCode: - description: PromotionCode is a publisher-provided - promotion code as provisioned in Data Market for - the said product/artifact. - type: string - publisher: - description: Publisher is the name of the publisher - of the 3rd Party Artifact that is being bought. - type: string - version: - description: Version is the version of the plan. - type: string - type: object - releaseTrain: - description: |- - ReleaseTrain is the release train this extension participates in for auto-upgrade (e.g. Stable, Preview, etc.) - This is only used if autoUpgradeMinorVersion is ‘true’. - type: string - scope: - description: Scope is the scope at which this extension - is enabled. - properties: - releaseNamespace: - description: |- - ReleaseNamespace is the namespace where the extension Release must be placed, for a Cluster-scoped extension. - Required for Cluster-scoped extensions. - type: string - scopeType: - description: ScopeType is the scope of the extension. - It can be either Cluster or Namespace, but not - both. - enum: - - Cluster - - Namespace - type: string - targetNamespace: - description: |- - TargetNamespace is the namespace where the extension will be created for a Namespace-scoped extension. - Required for Namespace-scoped extensions. - type: string - required: - - scopeType - type: object - version: - description: Version is the version of the extension. - type: string - required: - - extensionType - - name - type: object - type: array - fleetsMember: - description: |- - FleetsMember is the spec for the fleet this cluster is a member of. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/templates/microsoft.containerservice/2023-03-15-preview/fleets/members - properties: - group: - description: Group is the group this member belongs to - for multi-cluster update management. - type: string - managerName: - description: ManagerName is the name of the fleet manager. - type: string - managerResourceGroup: - description: ManagerResourceGroup is the resource group - of the fleet manager. - type: string - required: - - managerName - - managerResourceGroup - type: object - httpProxyConfig: - description: |- - HTTPProxyConfig is the HTTP proxy configuration for the cluster. - Immutable. - properties: - httpProxy: - description: HTTPProxy is the HTTP proxy server endpoint - to use. - type: string - httpsProxy: - description: HTTPSProxy is the HTTPS proxy server endpoint - to use. - type: string - noProxy: - description: NoProxy indicates the endpoints that should - not go through proxy. - items: - type: string - type: array - trustedCa: - description: TrustedCA is the alternative CA cert to use - for connecting to proxy servers. - type: string - type: object - identity: - description: Identity configuration used by the AKS control - plane. - properties: - type: - description: Type - The Identity type to use. - enum: - - SystemAssigned - - UserAssigned - type: string - userAssignedIdentityResourceID: - description: UserAssignedIdentityResourceID - Identity - ARM resource ID when using user-assigned identity. - type: string - type: object - identityRef: - description: IdentityRef is a reference to a AzureClusterIdentity - to be used when reconciling this cluster - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - kubeletUserAssignedIdentity: - description: |- - KubeletUserAssignedIdentity is the user-assigned identity for kubelet. - For authentication with Azure Container Registry. - type: string - loadBalancerProfile: - description: LoadBalancerProfile is the profile of the cluster - load balancer. - properties: - allocatedOutboundPorts: - description: AllocatedOutboundPorts - Desired number of - allocated SNAT ports per VM. Allowed values must be - in the range of 0 to 64000 (inclusive). The default - value is 0 which results in Azure dynamically allocating - ports. - type: integer - idleTimeoutInMinutes: - description: IdleTimeoutInMinutes - Desired outbound flow - idle timeout in minutes. Allowed values must be in the - range of 4 to 120 (inclusive). The default value is - 30 minutes. - type: integer - managedOutboundIPs: - description: ManagedOutboundIPs - Desired managed outbound - IPs for the cluster load balancer. - type: integer - outboundIPPrefixes: - description: OutboundIPPrefixes - Desired outbound IP - Prefix resources for the cluster load balancer. - items: - type: string - type: array - outboundIPs: - description: OutboundIPs - Desired outbound IP resources - for the cluster load balancer. - items: - type: string - type: array - type: object - loadBalancerSKU: - default: Standard - description: |- - LoadBalancerSKU is the SKU of the loadBalancer to be provisioned. - Immutable. - enum: - - Basic - - Standard - type: string - location: - description: 'Location is a string matching one of the canonical - Azure region names. Examples: "westus2", "eastus".' - type: string - machineTemplate: - description: |- - MachineTemplate contains information about how machines - should be shaped when creating or updating a control plane. - For the AzureManagedControlPlaneTemplate, this field is used - only to fulfill the CAPI contract. - type: object - networkDataplane: - description: NetworkDataplane is the dataplane used for building - the Kubernetes network. - enum: - - azure - - cilium - type: string - networkPlugin: - description: NetworkPlugin used for building Kubernetes network. - enum: - - azure - - kubenet - - none - type: string - networkPluginMode: - description: |- - NetworkPluginMode is the mode the network plugin should use. - Allowed value is "overlay". - enum: - - overlay - type: string - networkPolicy: - description: NetworkPolicy used for building Kubernetes network. - enum: - - azure - - calico - - cilium - type: string - oidcIssuerProfile: - description: OIDCIssuerProfile is the OIDC issuer profile - of the Managed Cluster. - properties: - enabled: - description: Enabled is whether the OIDC issuer is enabled. - type: boolean - type: object - outboundType: - description: Outbound configuration used by Nodes. - enum: - - loadBalancer - - managedNATGateway - - userAssignedNATGateway - - userDefinedRouting - type: string - resourceGroupName: - description: |- - ResourceGroupName is the name of the Azure resource group for this AKS Cluster. - Immutable. - type: string - securityProfile: - description: SecurityProfile defines the security profile - for cluster. - properties: - azureKeyVaultKms: - description: AzureKeyVaultKms defines Azure Key Vault - Management Services Profile for the security profile. - properties: - enabled: - description: Enabled enables the Azure Key Vault key - management service. The default is false. - type: boolean - keyID: - description: |- - KeyID defines the Identifier of Azure Key Vault key. - When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier. - type: string - keyVaultNetworkAccess: - default: Public - description: |- - KeyVaultNetworkAccess defines the network access of key vault. - The possible values are Public and Private. - Public means the key vault allows public access from all networks. - Private means the key vault disables public access and enables private link. The default value is Public. - type: string - keyVaultResourceID: - description: KeyVaultResourceID is the Resource ID - of key vault. When keyVaultNetworkAccess is Private, - this field is required and must be a valid resource - ID. - type: string - required: - - enabled - - keyID - type: object - defender: - description: Defender settings for the security profile. - properties: - logAnalyticsWorkspaceResourceID: - description: |- - LogAnalyticsWorkspaceResourceID is the ID of the Log Analytics workspace that has to be associated with Microsoft Defender. - When Microsoft Defender is enabled, this field is required and must be a valid workspace resource ID. - type: string - securityMonitoring: - description: SecurityMonitoring profile defines the - Microsoft Defender threat detection for Cloud settings - for the security profile. - properties: - enabled: - description: Enabled enables Defender threat detection - type: boolean - required: - - enabled - type: object - required: - - logAnalyticsWorkspaceResourceID - - securityMonitoring - type: object - imageCleaner: - description: ImageCleaner settings for the security profile. - properties: - enabled: - description: Enabled enables the Image Cleaner on - AKS cluster. - type: boolean - intervalHours: - description: IntervalHours defines Image Cleaner scanning - interval in hours. Default value is 24 hours. - maximum: 2160 - minimum: 24 - type: integer - required: - - enabled - type: object - workloadIdentity: - description: Workloadidentity enables Kubernetes applications - to access Azure cloud resources securely with Azure - AD. Ensure to enable OIDC issuer while enabling Workload - Identity - properties: - enabled: - description: Enabled enables the workload identity. - type: boolean - required: - - enabled - type: object - type: object - sku: - description: SKU is the SKU of the AKS to be provisioned. - properties: - tier: - description: Tier - Tier of an AKS cluster. - enum: - - Free - - Paid - - Standard - type: string - required: - - tier - type: object - subscriptionID: - description: SubscriptionID is the GUID of the Azure subscription - that owns this cluster. - type: string - version: - description: Version defines the desired Kubernetes version. - minLength: 2 - type: string - virtualNetwork: - description: VirtualNetwork describes the virtual network - for the AKS cluster. It will be created if it does not already - exist. - properties: - cidrBlock: - type: string - name: - description: Name is the name of the virtual network. - type: string - resourceGroup: - description: ResourceGroup is the name of the Azure resource - group for the VNet and Subnet. - type: string - subnet: - description: ManagedControlPlaneSubnet describes a subnet - for an AKS cluster. - properties: - cidrBlock: - type: string - name: - type: string - privateEndpoints: - description: PrivateEndpoints is a slice of Virtual - Network private endpoints to create for the subnets. - items: - description: PrivateEndpointSpec configures an Azure - Private Endpoint. - properties: - applicationSecurityGroups: - description: ApplicationSecurityGroups specifies - the Application security group in which the - private endpoint IP configuration is included. - items: - type: string - type: array - customNetworkInterfaceName: - description: CustomNetworkInterfaceName specifies - the network interface name associated with - the private endpoint. - type: string - location: - description: Location specifies the region to - create the private endpoint. - type: string - manualApproval: - description: |- - ManualApproval specifies if the connection approval needs to be done manually or not. - Set it true when the network admin does not have access to approve connections to the remote resource. - Defaults to false. - type: boolean - name: - description: Name specifies the name of the - private endpoint. - type: string - privateIPAddresses: - description: |- - PrivateIPAddresses specifies the IP addresses for the network interface associated with the private endpoint. - They have to be part of the subnet where the private endpoint is linked. - items: - type: string - type: array - privateLinkServiceConnections: - description: PrivateLinkServiceConnections specifies - Private Link Service Connections of the private - endpoint. - items: - description: PrivateLinkServiceConnection - defines the specification for a private - link service connection associated with - a private endpoint. - properties: - groupIDs: - description: GroupIDs specifies the ID(s) - of the group(s) obtained from the remote - resource that this private endpoint - should connect to. - items: - type: string - type: array - name: - description: Name specifies the name of - the private link service. - type: string - privateLinkServiceID: - description: PrivateLinkServiceID specifies - the resource ID of the private link - service. - type: string - requestMessage: - description: RequestMessage specifies - a message passed to the owner of the - remote resource with the private endpoint - connection request. - maxLength: 140 - type: string - type: object - type: array - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceEndpoints: - description: ServiceEndpoints is a slice of Virtual - Network service endpoints to enable for the subnets. - items: - description: ServiceEndpointSpec configures an Azure - Service Endpoint. - properties: - locations: - items: - type: string - type: array - service: - type: string - required: - - locations - - service - type: object - type: array - x-kubernetes-list-map-keys: - - service - x-kubernetes-list-type: map - required: - - cidrBlock - - name - type: object - required: - - cidrBlock - - name - type: object - required: - - identityRef - - location - - resourceGroupName - - version - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepools.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepools.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 5e2a2d9e0..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepools.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,752 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedmachinepools.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedMachinePool - listKind: AzureManagedMachinePoolList - plural: azuremanagedmachinepools - shortNames: - - ammp - singular: azuremanagedmachinepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AzureManagedMachinePool belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].severity - name: Severity - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=='Ready')].message - name: Message - priority: 1 - type: string - - description: Time duration since creation of this AzureManagedMachinePool - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .spec.mode - name: Mode - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedMachinePool is the Schema for the azuremanagedmachinepools - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedMachinePoolSpec defines the desired state of - AzureManagedMachinePool. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the - Azure provider, in addition to the ones added by default. - type: object - asoManagedClustersAgentPoolPatches: - description: |- - ASOManagedClustersAgentPoolPatches defines JSON merge patches to be applied to the generated ASO ManagedClustersAgentPool resource. - WARNING: This is meant to be used sparingly to enable features for development and testing that are not - otherwise represented in the CAPZ API. Misconfiguration that conflicts with CAPZ's normal mode of - operation is possible. - items: - type: string - type: array - availabilityZones: - description: |- - AvailabilityZones - Availability zones for nodes. Must use VirtualMachineScaleSets AgentPoolType. - Immutable. - items: - type: string - type: array - enableEncryptionAtHost: - description: |- - EnableEncryptionAtHost indicates whether host encryption is enabled on the node pool. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/aks/enable-host-encryption - type: boolean - enableFIPS: - description: |- - EnableFIPS indicates whether FIPS is enabled on the node pool. - Immutable. - type: boolean - enableNodePublicIP: - description: |- - EnableNodePublicIP controls whether or not nodes in the pool each have a public IP address. - Immutable. - type: boolean - enableUltraSSD: - description: |- - EnableUltraSSD enables the storage type UltraSSD_LRS for the agent pool. - Immutable. - type: boolean - kubeletConfig: - description: |- - KubeletConfig specifies the kubelet configurations for nodes. - Immutable. - properties: - allowedUnsafeSysctls: - description: |- - AllowedUnsafeSysctls - Allowlist of unsafe sysctls or unsafe sysctl patterns (ending in `*`). - Valid values match `kernel.shm*`, `kernel.msg*`, `kernel.sem`, `fs.mqueue.*`, or `net.*`. - items: - type: string - type: array - containerLogMaxFiles: - description: ContainerLogMaxFiles - The maximum number of container - log files that can be present for a container. The number must - be ≥ 2. - minimum: 2 - type: integer - containerLogMaxSizeMB: - description: ContainerLogMaxSizeMB - The maximum size in MB of - a container log file before it is rotated. - type: integer - cpuCfsQuota: - description: CPUCfsQuota - Enable CPU CFS quota enforcement for - containers that specify CPU limits. - type: boolean - cpuCfsQuotaPeriod: - description: |- - CPUCfsQuotaPeriod - Sets CPU CFS quota period value. - Must end in "ms", e.g. "100ms" - type: string - cpuManagerPolicy: - description: CPUManagerPolicy - CPU Manager policy to use. - enum: - - none - - static - type: string - failSwapOn: - description: FailSwapOn - If set to true it will make the Kubelet - fail to start if swap is enabled on the node. - type: boolean - imageGcHighThreshold: - description: |- - ImageGcHighThreshold - The percent of disk usage after which image garbage collection is always run. - Valid values are 0-100 (inclusive). - maximum: 100 - minimum: 0 - type: integer - imageGcLowThreshold: - description: |- - ImageGcLowThreshold - The percent of disk usage before which image garbage collection is never run. - Valid values are 0-100 (inclusive) and must be less than `imageGcHighThreshold`. - maximum: 100 - minimum: 0 - type: integer - podMaxPids: - description: |- - PodMaxPids - The maximum number of processes per pod. - Must not exceed kernel PID limit. -1 disables the limit. - minimum: -1 - type: integer - topologyManagerPolicy: - description: TopologyManagerPolicy - Topology Manager policy to - use. - enum: - - none - - best-effort - - restricted - - single-numa-node - type: string - type: object - kubeletDiskType: - description: |- - KubeletDiskType specifies the kubelet disk type. Default to OS. Possible values include: 'OS', 'Temporary'. - Requires Microsoft.ContainerService/KubeletDisk preview feature to be set. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/rest/api/aks/agent-pools/create-or-update?tabs=HTTP#kubeletdisktype - enum: - - OS - - Temporary - type: string - linuxOSConfig: - description: |- - LinuxOSConfig specifies the custom Linux OS settings and configurations. - Immutable. - properties: - swapFileSizeMB: - description: |- - SwapFileSizeMB specifies size in MB of a swap file will be created on the agent nodes from this node pool. - Max value of SwapFileSizeMB should be the size of temporary disk(/dev/sdb). - Must be at least 1. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview#temporary-disk - minimum: 1 - type: integer - sysctls: - description: Sysctl specifies the settings for Linux agent nodes. - properties: - fsAioMaxNr: - description: |- - FsAioMaxNr specifies the maximum number of system-wide asynchronous io requests. - Valid values are 65536-6553500 (inclusive). - Maps to fs.aio-max-nr. - maximum: 6553500 - minimum: 65536 - type: integer - fsFileMax: - description: |- - FsFileMax specifies the max number of file-handles that the Linux kernel will allocate, by increasing increases the maximum number of open files permitted. - Valid values are 8192-12000500 (inclusive). - Maps to fs.file-max. - maximum: 12000500 - minimum: 8192 - type: integer - fsInotifyMaxUserWatches: - description: |- - FsInotifyMaxUserWatches specifies the number of file watches allowed by the system. Each watch is roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes on a 64-bit kernel. - Valid values are 781250-2097152 (inclusive). - Maps to fs.inotify.max_user_watches. - maximum: 2097152 - minimum: 781250 - type: integer - fsNrOpen: - description: |- - FsNrOpen specifies the maximum number of file-handles a process can allocate. - Valid values are 8192-20000500 (inclusive). - Maps to fs.nr_open. - maximum: 20000500 - minimum: 8192 - type: integer - kernelThreadsMax: - description: |- - KernelThreadsMax specifies the maximum number of all threads that can be created. - Valid values are 20-513785 (inclusive). - Maps to kernel.threads-max. - maximum: 513785 - minimum: 20 - type: integer - netCoreNetdevMaxBacklog: - description: |- - NetCoreNetdevMaxBacklog specifies maximum number of packets, queued on the INPUT side, when the interface receives packets faster than kernel can process them. - Valid values are 1000-3240000 (inclusive). - Maps to net.core.netdev_max_backlog. - maximum: 3240000 - minimum: 1000 - type: integer - netCoreOptmemMax: - description: |- - NetCoreOptmemMax specifies the maximum ancillary buffer size (option memory buffer) allowed per socket. - Socket option memory is used in a few cases to store extra structures relating to usage of the socket. - Valid values are 20480-4194304 (inclusive). - Maps to net.core.optmem_max. - maximum: 4194304 - minimum: 20480 - type: integer - netCoreRmemDefault: - description: |- - NetCoreRmemDefault specifies the default receive socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.rmem_default. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreRmemMax: - description: |- - NetCoreRmemMax specifies the maximum receive socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.rmem_max. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreSomaxconn: - description: |- - NetCoreSomaxconn specifies maximum number of connection requests that can be queued for any given listening socket. - An upper limit for the value of the backlog parameter passed to the listen(2)(https://man7.org/linux/man-pages/man2/listen.2.html) function. - If the backlog argument is greater than the somaxconn, then it's silently truncated to this limit. - Valid values are 4096-3240000 (inclusive). - Maps to net.core.somaxconn. - maximum: 3240000 - minimum: 4096 - type: integer - netCoreWmemDefault: - description: |- - NetCoreWmemDefault specifies the default send socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.wmem_default. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreWmemMax: - description: |- - NetCoreWmemMax specifies the maximum send socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.wmem_max. - maximum: 134217728 - minimum: 212992 - type: integer - netIpv4IPLocalPortRange: - description: |- - NetIpv4IPLocalPortRange is used by TCP and UDP traffic to choose the local port on the agent node. - PortRange should be specified in the format "first last". - First, being an integer, must be between [1024 - 60999]. - Last, being an integer, must be between [32768 - 65000]. - Maps to net.ipv4.ip_local_port_range. - type: string - netIpv4NeighDefaultGcThresh1: - description: |- - NetIpv4NeighDefaultGcThresh1 specifies the minimum number of entries that may be in the ARP cache. - Garbage collection won't be triggered if the number of entries is below this setting. - Valid values are 128-80000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh1. - maximum: 80000 - minimum: 128 - type: integer - netIpv4NeighDefaultGcThresh2: - description: |- - NetIpv4NeighDefaultGcThresh2 specifies soft maximum number of entries that may be in the ARP cache. - ARP garbage collection will be triggered about 5 seconds after reaching this soft maximum. - Valid values are 512-90000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh2. - maximum: 90000 - minimum: 512 - type: integer - netIpv4NeighDefaultGcThresh3: - description: |- - NetIpv4NeighDefaultGcThresh3 specified hard maximum number of entries in the ARP cache. - Valid values are 1024-100000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh3. - maximum: 100000 - minimum: 1024 - type: integer - netIpv4TCPFinTimeout: - description: |- - NetIpv4TCPFinTimeout specifies the length of time an orphaned connection will remain in the FIN_WAIT_2 state before it's aborted at the local end. - Valid values are 5-120 (inclusive). - Maps to net.ipv4.tcp_fin_timeout. - maximum: 120 - minimum: 5 - type: integer - netIpv4TCPKeepaliveProbes: - description: |- - NetIpv4TCPKeepaliveProbes specifies the number of keepalive probes TCP sends out, until it decides the connection is broken. - Valid values are 1-15 (inclusive). - Maps to net.ipv4.tcp_keepalive_probes. - maximum: 15 - minimum: 1 - type: integer - netIpv4TCPKeepaliveTime: - description: |- - NetIpv4TCPKeepaliveTime specifies the rate at which TCP sends out a keepalive message when keepalive is enabled. - Valid values are 30-432000 (inclusive). - Maps to net.ipv4.tcp_keepalive_time. - maximum: 432000 - minimum: 30 - type: integer - netIpv4TCPMaxSynBacklog: - description: |- - NetIpv4TCPMaxSynBacklog specifies the maximum number of queued connection requests that have still not received an acknowledgment from the connecting client. - If this number is exceeded, the kernel will begin dropping requests. - Valid values are 128-3240000 (inclusive). - Maps to net.ipv4.tcp_max_syn_backlog. - maximum: 3240000 - minimum: 128 - type: integer - netIpv4TCPMaxTwBuckets: - description: |- - NetIpv4TCPMaxTwBuckets specifies maximal number of timewait sockets held by system simultaneously. - If this number is exceeded, time-wait socket is immediately destroyed and warning is printed. - Valid values are 8000-1440000 (inclusive). - Maps to net.ipv4.tcp_max_tw_buckets. - maximum: 1440000 - minimum: 8000 - type: integer - netIpv4TCPTwReuse: - description: |- - NetIpv4TCPTwReuse is used to allow to reuse TIME-WAIT sockets for new connections when it's safe from protocol viewpoint. - Maps to net.ipv4.tcp_tw_reuse. - type: boolean - netIpv4TCPkeepaliveIntvl: - description: |- - NetIpv4TCPkeepaliveIntvl specifies the frequency of the probes sent out. - Multiplied by tcpKeepaliveprobes, it makes up the time to kill a connection that isn't responding, after probes started. - Valid values are 1-75 (inclusive). - Maps to net.ipv4.tcp_keepalive_intvl. - maximum: 75 - minimum: 1 - type: integer - netNetfilterNfConntrackBuckets: - description: |- - NetNetfilterNfConntrackBuckets specifies the size of hash table used by nf_conntrack module to record the established connection record of the TCP protocol. - Valid values are 65536-147456 (inclusive). - Maps to net.netfilter.nf_conntrack_buckets. - maximum: 147456 - minimum: 65536 - type: integer - netNetfilterNfConntrackMax: - description: |- - NetNetfilterNfConntrackMax specifies the maximum number of connections supported by the nf_conntrack module or the size of connection tracking table. - Valid values are 131072-1048576 (inclusive). - Maps to net.netfilter.nf_conntrack_max. - maximum: 1048576 - minimum: 131072 - type: integer - vmMaxMapCount: - description: |- - VMMaxMapCount specifies the maximum number of memory map areas a process may have. - Maps to vm.max_map_count. - Valid values are 65530-262144 (inclusive). - maximum: 262144 - minimum: 65530 - type: integer - vmSwappiness: - description: |- - VMSwappiness specifies aggressiveness of the kernel in swapping memory pages. - Higher values will increase aggressiveness, lower values decrease the amount of swap. - Valid values are 0-100 (inclusive). - Maps to vm.swappiness. - maximum: 100 - minimum: 0 - type: integer - vmVfsCachePressure: - description: |- - VMVfsCachePressure specifies the percentage value that controls tendency of the kernel to reclaim the memory, which is used for caching of directory and inode objects. - Valid values are 1-500 (inclusive). - Maps to vm.vfs_cache_pressure. - maximum: 500 - minimum: 1 - type: integer - type: object - transparentHugePageDefrag: - description: |- - TransparentHugePageDefrag specifies whether the kernel should make aggressive use of memory compaction to make more hugepages available. - See also [Linux doc]. - - - [Linux doc]: https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html#admin-guide-transhuge for more details. - enum: - - always - - defer - - defer+madvise - - madvise - - never - type: string - transparentHugePageEnabled: - description: |- - TransparentHugePageEnabled specifies various modes of Transparent Hugepages. - See also [Linux doc]. - - - [Linux doc]: https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html#admin-guide-transhuge for more details. - enum: - - always - - madvise - - never - type: string - type: object - maxPods: - description: |- - MaxPods specifies the kubelet `--max-pods` configuration for the node pool. - Immutable. - See also [AKS doc], [K8s doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/configure-azure-cni#configure-maximum---new-clusters - [K8s doc]: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ - type: integer - mode: - description: 'Mode represents the mode of an agent pool. Possible - values include: System, User.' - enum: - - System - - User - type: string - name: - description: |- - Name is the name of the agent pool. If not specified, CAPZ uses the name of the CR as the agent pool name. - Immutable. - type: string - nodeLabels: - additionalProperties: - type: string - description: |- - Node labels represent the labels for all of the nodes present in node pool. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/use-labels - type: object - nodePublicIPPrefixID: - description: |- - NodePublicIPPrefixID specifies the public IP prefix resource ID which VM nodes should use IPs from. - Immutable. - type: string - osDiskSizeGB: - description: |- - OSDiskSizeGB is the disk size for every machine in this agent pool. - If you specify 0, it will apply the default osDisk size according to the vmSize specified. - Immutable. - type: integer - osDiskType: - default: Managed - description: |- - OsDiskType specifies the OS disk type for each node in the pool. Allowed values are 'Ephemeral' and 'Managed' (default). - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/cluster-configuration#ephemeral-os - enum: - - Ephemeral - - Managed - type: string - osType: - description: |- - OSType specifies the virtual machine operating system. Default to Linux. Possible values include: 'Linux', 'Windows'. - 'Windows' requires the AzureManagedControlPlane's `spec.networkPlugin` to be `azure`. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/rest/api/aks/agent-pools/create-or-update?tabs=HTTP#ostype - enum: - - Linux - - Windows - type: string - providerIDList: - description: ProviderIDList is the unique identifier as specified - by the cloud provider. - items: - type: string - type: array - scaleDownMode: - default: Delete - description: 'ScaleDownMode affects the cluster autoscaler behavior. - Default to Delete. Possible values include: ''Deallocate'', ''Delete''' - enum: - - Deallocate - - Delete - type: string - scaleSetPriority: - description: |- - ScaleSetPriority specifies the ScaleSetPriority value. Default to Regular. Possible values include: 'Regular', 'Spot' - Immutable. - enum: - - Regular - - Spot - type: string - scaling: - description: Scaling specifies the autoscaling parameters for the - node pool. - properties: - maxSize: - description: MaxSize is the maximum number of nodes for auto-scaling. - type: integer - minSize: - description: MinSize is the minimum number of nodes for auto-scaling. - type: integer - type: object - sku: - description: |- - SKU is the size of the VMs in the node pool. - Immutable. - type: string - spotMaxPrice: - anyOf: - - type: integer - - type: string - description: |- - SpotMaxPrice defines max price to pay for spot instance. Possible values are any decimal value greater than zero or -1. - If you set the max price to be -1, the VM won't be evicted based on price. The price for the VM will be the current price - for spot or the price for a standard VM, which ever is less, as long as there's capacity and quota available. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - subnetName: - description: |- - SubnetName specifies the Subnet where the MachinePool will be placed - Immutable. - type: string - taints: - description: |- - Taints specifies the taints for nodes present in this agent pool. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/use-multiple-node-pools#setting-node-pool-taints - items: - description: Taint represents a Kubernetes taint. - properties: - effect: - description: Effect specifies the effect for the taint - enum: - - NoSchedule - - NoExecute - - PreferNoSchedule - type: string - key: - description: Key is the key of the taint - type: string - value: - description: Value is the value of the taint - type: string - required: - - effect - - key - - value - type: object - type: array - required: - - mode - - sku - type: object - status: - description: AzureManagedMachinePoolStatus defines the observed state - of AzureManagedMachinePool. - properties: - conditions: - description: Conditions defines current service state of the AzureManagedControlPlane. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - errorMessage: - description: |- - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - errorReason: - description: |- - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - longRunningOperationStates: - description: |- - LongRunningOperationStates saves the states for Azure long-running operations so they can be continued on the - next reconciliation loop. - items: - description: Future contains the data needed for an Azure long-running - operation to continue across reconcile loops. - properties: - data: - description: Data is the base64 url encoded json Azure AutoRest - Future. - type: string - name: - description: |- - Name is the name of the Azure resource. - Together with the service name, this forms the unique identifier for the future. - type: string - resourceGroup: - description: ResourceGroup is the Azure resource group for the - resource. - type: string - serviceName: - description: |- - ServiceName is the name of the Azure service. - Together with the name of the resource, this forms the unique identifier for the future. - type: string - type: - description: Type describes the type of future, such as update, - create, delete, etc. - type: string - required: - - data - - name - - serviceName - - type - type: object - type: array - ready: - description: Ready is true when the provider resource is ready. - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepooltemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepooltemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 31fed717d..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-azuremanagedmachinepooltemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,633 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: azuremanagedmachinepooltemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AzureManagedMachinePoolTemplate - listKind: AzureManagedMachinePoolTemplateList - plural: azuremanagedmachinepooltemplates - shortNames: - - ammpt - singular: azuremanagedmachinepooltemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: AzureManagedMachinePoolTemplate is the Schema for the AzureManagedMachinePoolTemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: AzureManagedMachinePoolTemplateSpec defines the desired state - of AzureManagedMachinePoolTemplate. - properties: - template: - description: AzureManagedMachinePoolTemplateResource describes the - data needed to create an AzureManagedCluster from a template. - properties: - spec: - description: AzureManagedMachinePoolTemplateResourceSpec specifies - an Azure managed control plane template resource. - properties: - additionalTags: - additionalProperties: - type: string - description: |- - AdditionalTags is an optional set of tags to add to Azure resources managed by the - Azure provider, in addition to the ones added by default. - type: object - asoManagedClustersAgentPoolPatches: - description: |- - ASOManagedClustersAgentPoolPatches defines JSON merge patches to be applied to the generated ASO ManagedClustersAgentPool resource. - WARNING: This is meant to be used sparingly to enable features for development and testing that are not - otherwise represented in the CAPZ API. Misconfiguration that conflicts with CAPZ's normal mode of - operation is possible. - items: - type: string - type: array - availabilityZones: - description: |- - AvailabilityZones - Availability zones for nodes. Must use VirtualMachineScaleSets AgentPoolType. - Immutable. - items: - type: string - type: array - enableEncryptionAtHost: - description: |- - EnableEncryptionAtHost indicates whether host encryption is enabled on the node pool. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/en-us/azure/aks/enable-host-encryption - type: boolean - enableFIPS: - description: |- - EnableFIPS indicates whether FIPS is enabled on the node pool. - Immutable. - type: boolean - enableNodePublicIP: - description: |- - EnableNodePublicIP controls whether or not nodes in the pool each have a public IP address. - Immutable. - type: boolean - enableUltraSSD: - description: |- - EnableUltraSSD enables the storage type UltraSSD_LRS for the agent pool. - Immutable. - type: boolean - kubeletConfig: - description: |- - KubeletConfig specifies the kubelet configurations for nodes. - Immutable. - properties: - allowedUnsafeSysctls: - description: |- - AllowedUnsafeSysctls - Allowlist of unsafe sysctls or unsafe sysctl patterns (ending in `*`). - Valid values match `kernel.shm*`, `kernel.msg*`, `kernel.sem`, `fs.mqueue.*`, or `net.*`. - items: - type: string - type: array - containerLogMaxFiles: - description: ContainerLogMaxFiles - The maximum number - of container log files that can be present for a container. - The number must be ≥ 2. - minimum: 2 - type: integer - containerLogMaxSizeMB: - description: ContainerLogMaxSizeMB - The maximum size - in MB of a container log file before it is rotated. - type: integer - cpuCfsQuota: - description: CPUCfsQuota - Enable CPU CFS quota enforcement - for containers that specify CPU limits. - type: boolean - cpuCfsQuotaPeriod: - description: |- - CPUCfsQuotaPeriod - Sets CPU CFS quota period value. - Must end in "ms", e.g. "100ms" - type: string - cpuManagerPolicy: - description: CPUManagerPolicy - CPU Manager policy to - use. - enum: - - none - - static - type: string - failSwapOn: - description: FailSwapOn - If set to true it will make - the Kubelet fail to start if swap is enabled on the - node. - type: boolean - imageGcHighThreshold: - description: |- - ImageGcHighThreshold - The percent of disk usage after which image garbage collection is always run. - Valid values are 0-100 (inclusive). - maximum: 100 - minimum: 0 - type: integer - imageGcLowThreshold: - description: |- - ImageGcLowThreshold - The percent of disk usage before which image garbage collection is never run. - Valid values are 0-100 (inclusive) and must be less than `imageGcHighThreshold`. - maximum: 100 - minimum: 0 - type: integer - podMaxPids: - description: |- - PodMaxPids - The maximum number of processes per pod. - Must not exceed kernel PID limit. -1 disables the limit. - minimum: -1 - type: integer - topologyManagerPolicy: - description: TopologyManagerPolicy - Topology Manager - policy to use. - enum: - - none - - best-effort - - restricted - - single-numa-node - type: string - type: object - kubeletDiskType: - description: |- - KubeletDiskType specifies the kubelet disk type. Default to OS. Possible values include: 'OS', 'Temporary'. - Requires Microsoft.ContainerService/KubeletDisk preview feature to be set. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/rest/api/aks/agent-pools/create-or-update?tabs=HTTP#kubeletdisktype - enum: - - OS - - Temporary - type: string - linuxOSConfig: - description: |- - LinuxOSConfig specifies the custom Linux OS settings and configurations. - Immutable. - properties: - swapFileSizeMB: - description: |- - SwapFileSizeMB specifies size in MB of a swap file will be created on the agent nodes from this node pool. - Max value of SwapFileSizeMB should be the size of temporary disk(/dev/sdb). - Must be at least 1. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview#temporary-disk - minimum: 1 - type: integer - sysctls: - description: Sysctl specifies the settings for Linux agent - nodes. - properties: - fsAioMaxNr: - description: |- - FsAioMaxNr specifies the maximum number of system-wide asynchronous io requests. - Valid values are 65536-6553500 (inclusive). - Maps to fs.aio-max-nr. - maximum: 6553500 - minimum: 65536 - type: integer - fsFileMax: - description: |- - FsFileMax specifies the max number of file-handles that the Linux kernel will allocate, by increasing increases the maximum number of open files permitted. - Valid values are 8192-12000500 (inclusive). - Maps to fs.file-max. - maximum: 12000500 - minimum: 8192 - type: integer - fsInotifyMaxUserWatches: - description: |- - FsInotifyMaxUserWatches specifies the number of file watches allowed by the system. Each watch is roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes on a 64-bit kernel. - Valid values are 781250-2097152 (inclusive). - Maps to fs.inotify.max_user_watches. - maximum: 2097152 - minimum: 781250 - type: integer - fsNrOpen: - description: |- - FsNrOpen specifies the maximum number of file-handles a process can allocate. - Valid values are 8192-20000500 (inclusive). - Maps to fs.nr_open. - maximum: 20000500 - minimum: 8192 - type: integer - kernelThreadsMax: - description: |- - KernelThreadsMax specifies the maximum number of all threads that can be created. - Valid values are 20-513785 (inclusive). - Maps to kernel.threads-max. - maximum: 513785 - minimum: 20 - type: integer - netCoreNetdevMaxBacklog: - description: |- - NetCoreNetdevMaxBacklog specifies maximum number of packets, queued on the INPUT side, when the interface receives packets faster than kernel can process them. - Valid values are 1000-3240000 (inclusive). - Maps to net.core.netdev_max_backlog. - maximum: 3240000 - minimum: 1000 - type: integer - netCoreOptmemMax: - description: |- - NetCoreOptmemMax specifies the maximum ancillary buffer size (option memory buffer) allowed per socket. - Socket option memory is used in a few cases to store extra structures relating to usage of the socket. - Valid values are 20480-4194304 (inclusive). - Maps to net.core.optmem_max. - maximum: 4194304 - minimum: 20480 - type: integer - netCoreRmemDefault: - description: |- - NetCoreRmemDefault specifies the default receive socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.rmem_default. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreRmemMax: - description: |- - NetCoreRmemMax specifies the maximum receive socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.rmem_max. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreSomaxconn: - description: |- - NetCoreSomaxconn specifies maximum number of connection requests that can be queued for any given listening socket. - An upper limit for the value of the backlog parameter passed to the listen(2)(https://man7.org/linux/man-pages/man2/listen.2.html) function. - If the backlog argument is greater than the somaxconn, then it's silently truncated to this limit. - Valid values are 4096-3240000 (inclusive). - Maps to net.core.somaxconn. - maximum: 3240000 - minimum: 4096 - type: integer - netCoreWmemDefault: - description: |- - NetCoreWmemDefault specifies the default send socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.wmem_default. - maximum: 134217728 - minimum: 212992 - type: integer - netCoreWmemMax: - description: |- - NetCoreWmemMax specifies the maximum send socket buffer size in bytes. - Valid values are 212992-134217728 (inclusive). - Maps to net.core.wmem_max. - maximum: 134217728 - minimum: 212992 - type: integer - netIpv4IPLocalPortRange: - description: |- - NetIpv4IPLocalPortRange is used by TCP and UDP traffic to choose the local port on the agent node. - PortRange should be specified in the format "first last". - First, being an integer, must be between [1024 - 60999]. - Last, being an integer, must be between [32768 - 65000]. - Maps to net.ipv4.ip_local_port_range. - type: string - netIpv4NeighDefaultGcThresh1: - description: |- - NetIpv4NeighDefaultGcThresh1 specifies the minimum number of entries that may be in the ARP cache. - Garbage collection won't be triggered if the number of entries is below this setting. - Valid values are 128-80000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh1. - maximum: 80000 - minimum: 128 - type: integer - netIpv4NeighDefaultGcThresh2: - description: |- - NetIpv4NeighDefaultGcThresh2 specifies soft maximum number of entries that may be in the ARP cache. - ARP garbage collection will be triggered about 5 seconds after reaching this soft maximum. - Valid values are 512-90000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh2. - maximum: 90000 - minimum: 512 - type: integer - netIpv4NeighDefaultGcThresh3: - description: |- - NetIpv4NeighDefaultGcThresh3 specified hard maximum number of entries in the ARP cache. - Valid values are 1024-100000 (inclusive). - Maps to net.ipv4.neigh.default.gc_thresh3. - maximum: 100000 - minimum: 1024 - type: integer - netIpv4TCPFinTimeout: - description: |- - NetIpv4TCPFinTimeout specifies the length of time an orphaned connection will remain in the FIN_WAIT_2 state before it's aborted at the local end. - Valid values are 5-120 (inclusive). - Maps to net.ipv4.tcp_fin_timeout. - maximum: 120 - minimum: 5 - type: integer - netIpv4TCPKeepaliveProbes: - description: |- - NetIpv4TCPKeepaliveProbes specifies the number of keepalive probes TCP sends out, until it decides the connection is broken. - Valid values are 1-15 (inclusive). - Maps to net.ipv4.tcp_keepalive_probes. - maximum: 15 - minimum: 1 - type: integer - netIpv4TCPKeepaliveTime: - description: |- - NetIpv4TCPKeepaliveTime specifies the rate at which TCP sends out a keepalive message when keepalive is enabled. - Valid values are 30-432000 (inclusive). - Maps to net.ipv4.tcp_keepalive_time. - maximum: 432000 - minimum: 30 - type: integer - netIpv4TCPMaxSynBacklog: - description: |- - NetIpv4TCPMaxSynBacklog specifies the maximum number of queued connection requests that have still not received an acknowledgment from the connecting client. - If this number is exceeded, the kernel will begin dropping requests. - Valid values are 128-3240000 (inclusive). - Maps to net.ipv4.tcp_max_syn_backlog. - maximum: 3240000 - minimum: 128 - type: integer - netIpv4TCPMaxTwBuckets: - description: |- - NetIpv4TCPMaxTwBuckets specifies maximal number of timewait sockets held by system simultaneously. - If this number is exceeded, time-wait socket is immediately destroyed and warning is printed. - Valid values are 8000-1440000 (inclusive). - Maps to net.ipv4.tcp_max_tw_buckets. - maximum: 1440000 - minimum: 8000 - type: integer - netIpv4TCPTwReuse: - description: |- - NetIpv4TCPTwReuse is used to allow to reuse TIME-WAIT sockets for new connections when it's safe from protocol viewpoint. - Maps to net.ipv4.tcp_tw_reuse. - type: boolean - netIpv4TCPkeepaliveIntvl: - description: |- - NetIpv4TCPkeepaliveIntvl specifies the frequency of the probes sent out. - Multiplied by tcpKeepaliveprobes, it makes up the time to kill a connection that isn't responding, after probes started. - Valid values are 1-75 (inclusive). - Maps to net.ipv4.tcp_keepalive_intvl. - maximum: 75 - minimum: 1 - type: integer - netNetfilterNfConntrackBuckets: - description: |- - NetNetfilterNfConntrackBuckets specifies the size of hash table used by nf_conntrack module to record the established connection record of the TCP protocol. - Valid values are 65536-147456 (inclusive). - Maps to net.netfilter.nf_conntrack_buckets. - maximum: 147456 - minimum: 65536 - type: integer - netNetfilterNfConntrackMax: - description: |- - NetNetfilterNfConntrackMax specifies the maximum number of connections supported by the nf_conntrack module or the size of connection tracking table. - Valid values are 131072-1048576 (inclusive). - Maps to net.netfilter.nf_conntrack_max. - maximum: 1048576 - minimum: 131072 - type: integer - vmMaxMapCount: - description: |- - VMMaxMapCount specifies the maximum number of memory map areas a process may have. - Maps to vm.max_map_count. - Valid values are 65530-262144 (inclusive). - maximum: 262144 - minimum: 65530 - type: integer - vmSwappiness: - description: |- - VMSwappiness specifies aggressiveness of the kernel in swapping memory pages. - Higher values will increase aggressiveness, lower values decrease the amount of swap. - Valid values are 0-100 (inclusive). - Maps to vm.swappiness. - maximum: 100 - minimum: 0 - type: integer - vmVfsCachePressure: - description: |- - VMVfsCachePressure specifies the percentage value that controls tendency of the kernel to reclaim the memory, which is used for caching of directory and inode objects. - Valid values are 1-500 (inclusive). - Maps to vm.vfs_cache_pressure. - maximum: 500 - minimum: 1 - type: integer - type: object - transparentHugePageDefrag: - description: |- - TransparentHugePageDefrag specifies whether the kernel should make aggressive use of memory compaction to make more hugepages available. - See also [Linux doc]. - - - [Linux doc]: https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html#admin-guide-transhuge for more details. - enum: - - always - - defer - - defer+madvise - - madvise - - never - type: string - transparentHugePageEnabled: - description: |- - TransparentHugePageEnabled specifies various modes of Transparent Hugepages. - See also [Linux doc]. - - - [Linux doc]: https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html#admin-guide-transhuge for more details. - enum: - - always - - madvise - - never - type: string - type: object - maxPods: - description: |- - MaxPods specifies the kubelet `--max-pods` configuration for the node pool. - Immutable. - See also [AKS doc], [K8s doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/configure-azure-cni#configure-maximum---new-clusters - [K8s doc]: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ - type: integer - mode: - description: 'Mode represents the mode of an agent pool. Possible - values include: System, User.' - enum: - - System - - User - type: string - name: - description: |- - Name is the name of the agent pool. If not specified, CAPZ uses the name of the CR as the agent pool name. - Immutable. - type: string - nodeLabels: - additionalProperties: - type: string - description: |- - Node labels represent the labels for all of the nodes present in node pool. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/use-labels - type: object - nodePublicIPPrefixID: - description: |- - NodePublicIPPrefixID specifies the public IP prefix resource ID which VM nodes should use IPs from. - Immutable. - type: string - osDiskSizeGB: - description: |- - OSDiskSizeGB is the disk size for every machine in this agent pool. - If you specify 0, it will apply the default osDisk size according to the vmSize specified. - Immutable. - type: integer - osDiskType: - default: Managed - description: |- - OsDiskType specifies the OS disk type for each node in the pool. Allowed values are 'Ephemeral' and 'Managed' (default). - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/cluster-configuration#ephemeral-os - enum: - - Ephemeral - - Managed - type: string - osType: - description: |- - OSType specifies the virtual machine operating system. Default to Linux. Possible values include: 'Linux', 'Windows'. - 'Windows' requires the AzureManagedControlPlane's `spec.networkPlugin` to be `azure`. - Immutable. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/rest/api/aks/agent-pools/create-or-update?tabs=HTTP#ostype - enum: - - Linux - - Windows - type: string - scaleDownMode: - default: Delete - description: 'ScaleDownMode affects the cluster autoscaler - behavior. Default to Delete. Possible values include: ''Deallocate'', - ''Delete''' - enum: - - Deallocate - - Delete - type: string - scaleSetPriority: - description: |- - ScaleSetPriority specifies the ScaleSetPriority value. Default to Regular. Possible values include: 'Regular', 'Spot' - Immutable. - enum: - - Regular - - Spot - type: string - scaling: - description: Scaling specifies the autoscaling parameters - for the node pool. - properties: - maxSize: - description: MaxSize is the maximum number of nodes for - auto-scaling. - type: integer - minSize: - description: MinSize is the minimum number of nodes for - auto-scaling. - type: integer - type: object - sku: - description: |- - SKU is the size of the VMs in the node pool. - Immutable. - type: string - spotMaxPrice: - anyOf: - - type: integer - - type: string - description: |- - SpotMaxPrice defines max price to pay for spot instance. Possible values are any decimal value greater than zero or -1. - If you set the max price to be -1, the VM won't be evicted based on price. The price for the VM will be the current price - for spot or the price for a standard VM, which ever is less, as long as there's capacity and quota available. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - subnetName: - description: |- - SubnetName specifies the Subnet where the MachinePool will be placed - Immutable. - type: string - taints: - description: |- - Taints specifies the taints for nodes present in this agent pool. - See also [AKS doc]. - - - [AKS doc]: https://learn.microsoft.com/azure/aks/use-multiple-node-pools#setting-node-pool-taints - items: - description: Taint represents a Kubernetes taint. - properties: - effect: - description: Effect specifies the effect for the taint - enum: - - NoSchedule - - NoExecute - - PreferNoSchedule - type: string - key: - description: Key is the key of the taint - type: string - value: - description: Value is the value of the taint - type: string - required: - - effect - - key - - value - type: object - type: array - required: - - mode - - sku - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-certificaterevocationrequests.certificates.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-certificaterevocationrequests.certificates.hypershift.openshift.io.yaml deleted file mode 100644 index 066acc9a2..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-certificaterevocationrequests.certificates.hypershift.openshift.io.yaml +++ /dev/null @@ -1,177 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: certificaterevocationrequests.certificates.hypershift.openshift.io -spec: - group: certificates.hypershift.openshift.io - names: - kind: CertificateRevocationRequest - listKind: CertificateRevocationRequestList - plural: certificaterevocationrequests - shortNames: - - crr - - crrs - singular: certificaterevocationrequest - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - CertificateRevocationRequest defines the desired state of CertificateRevocationRequest. - A request denotes the user's desire to revoke a signer certificate of the class indicated in spec. - 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: CertificateRevocationRequestSpec defines the desired state - of CertificateRevocationRequest - properties: - signerClass: - description: |- - SignerClass identifies the class of signer to revoke. All the active signing CAs for the - signer class will be revoked. - enum: - - customer-break-glass - - sre-break-glass - type: string - x-kubernetes-validations: - - message: signerClass is immutable - rule: self == oldSelf - required: - - signerClass - type: object - status: - description: CertificateRevocationRequestStatus defines the observed state - of CertificateRevocationRequest - properties: - conditions: - description: Conditions contain details about the various aspects - of certificate revocation. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - previousSigner: - description: |- - PreviousSigner stores a reference to the previous signer certificate. We require - storing this data to ensure that we can validate that the old signer is no longer - valid before considering revocation complete. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - revocationTimestamp: - description: |- - RevocationTimestamp is the cut-off time for signing CAs to be revoked. All certificates that - are valid before this time will be revoked; all re-generated certificates will not be valid - at or before this time. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.certificates.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.certificates.hypershift.openshift.io.yaml deleted file mode 100644 index b2977a1ec..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.certificates.hypershift.openshift.io.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: certificatesigningrequestapprovals.certificates.hypershift.openshift.io -spec: - group: certificates.hypershift.openshift.io - names: - kind: CertificateSigningRequestApproval - listKind: CertificateSigningRequestApprovalList - plural: certificatesigningrequestapprovals - shortNames: - - csra - - csras - singular: certificatesigningrequestapproval - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: CertificateSigningRequestApproval defines the desired state of - CertificateSigningRequestApproval - 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: CertificateSigningRequestApprovalSpec defines the desired - state of CertificateSigningRequestApproval - type: object - status: - description: CertificateSigningRequestApprovalStatus defines the observed - state of CertificateSigningRequestApproval - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.hypershift.openshift.io.yaml deleted file mode 100644 index 8412090a1..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-certificatesigningrequestapprovals.hypershift.openshift.io.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: certificatesigningrequestapprovals.hypershift.openshift.io -spec: - group: hypershift.openshift.io - names: - kind: CertificateSigningRequestApproval - listKind: CertificateSigningRequestApprovalList - plural: certificatesigningrequestapprovals - shortNames: - - csra - - csras - singular: certificatesigningrequestapproval - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: CertificateSigningRequestApproval defines the desired state of - CertificateSigningRequestApproval - 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: CertificateSigningRequestApprovalSpec defines the desired - state of CertificateSigningRequestApproval - type: object - status: - description: CertificateSigningRequestApprovalStatus defines the observed - state of CertificateSigningRequestApproval - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterclasses.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-clusterclasses.cluster.x-k8s.io.yaml deleted file mode 100644 index 900d91415..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterclasses.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1635 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: clusterclasses.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: ClusterClass - listKind: ClusterClassList - plural: clusterclasses - shortNames: - - cc - singular: clusterclass - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of ClusterClass - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterClass is a template which can be used to create managed - topologies. - 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: ClusterClassSpec describes the desired state of the ClusterClass. - properties: - controlPlane: - description: |- - ControlPlane is a reference to a local struct that holds the details - for provisioning the Control Plane for the Cluster. - properties: - machineHealthCheck: - description: |- - MachineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass. - This field is supported if and only if the ControlPlane provider template - referenced above is Machine based and supports setting replicas. - properties: - maxUnhealthy: - anyOf: - - type: integer - - type: string - description: |- - Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by - "selector" are not healthy. - x-kubernetes-int-or-string: true - nodeStartupTimeout: - description: |- - Machines older than this duration without a node will be considered to have - failed and will be remediated. - If you wish to disable this feature, set the value explicitly to 0. - type: string - remediationTemplate: - description: |- - RemediationTemplate is a reference to a remediation template - provided by an infrastructure provider. - - - This field is completely optional, when filled, the MachineHealthCheck controller - creates a new object from the template referenced and hands off remediation of the machine to - a controller that lives outside of Cluster API. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - unhealthyConditions: - description: |- - UnhealthyConditions contains a list of the conditions that determine - whether a node is considered unhealthy. The conditions are combined in a - logical OR, i.e. if any of the conditions is met, the node is unhealthy. - items: - description: |- - UnhealthyCondition represents a Node condition type and value with a timeout - specified as a duration. When the named condition has been in the given - status for at least the timeout value, a node is considered unhealthy. - properties: - status: - minLength: 1 - type: string - timeout: - type: string - type: - minLength: 1 - type: string - required: - - status - - timeout - - type - type: object - type: array - unhealthyRange: - description: |- - Any further remediation is only allowed if the number of machines selected by "selector" as not healthy - is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy. - Eg. "[3-5]" - This means that remediation will be allowed only when: - (a) there are at least 3 unhealthy machines (and) - (b) there are at most 5 unhealthy machines - pattern: ^\[[0-9]+-[0-9]+\]$ - type: string - type: object - machineInfrastructure: - description: |- - MachineInfrastructure defines the metadata and infrastructure information - for control plane machines. - - - This field is supported if and only if the control plane provider template - referenced above is Machine based and supports setting replicas. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - metadata: - description: |- - Metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane - if the ControlPlaneTemplate referenced is machine based. If not, it is applied only to the - ControlPlane. - At runtime this metadata is merged with the corresponding metadata from the topology. - - - This field is supported if and only if the control plane provider template - referenced is Machine based. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - namingStrategy: - description: NamingStrategy allows changing the naming pattern - used when creating the control plane provider object. - properties: - template: - description: |- - Template defines the template to use for generating the name of the ControlPlane object. - If not defined, it will fallback to `{{ .cluster.name }}-{{ .random }}`. - If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will - get concatenated with a random suffix of length 5. - The templating mechanism provides the following arguments: - * `.cluster.name`: The name of the cluster object. - * `.random`: A random alphanumeric string, without vowels, of length 5. - type: string - type: object - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - NOTE: This value can be overridden while defining a Cluster.Topology. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - NOTE: This value can be overridden while defining a Cluster.Topology. - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - NOTE: This value can be overridden while defining a Cluster.Topology. - type: string - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - infrastructure: - description: |- - Infrastructure is a reference to a provider-specific template that holds - the details for provisioning infrastructure specific cluster - for the underlying provider. - The underlying provider is responsible for the implementation - of the template to an infrastructure cluster. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - patches: - description: |- - Patches defines the patches which are applied to customize - referenced templates of a ClusterClass. - Note: Patches will be applied in the order of the array. - items: - description: ClusterClassPatch defines a patch which is applied - to customize the referenced templates. - properties: - definitions: - description: |- - Definitions define inline patches. - Note: Patches will be applied in the order of the array. - Note: Exactly one of Definitions or External must be set. - items: - description: PatchDefinition defines a patch which is applied - to customize the referenced templates. - properties: - jsonPatches: - description: |- - JSONPatches defines the patches which should be applied on the templates - matching the selector. - Note: Patches will be applied in the order of the array. - items: - description: JSONPatch defines a JSON patch. - properties: - op: - description: |- - Op defines the operation of the patch. - Note: Only `add`, `replace` and `remove` are supported. - type: string - path: - description: |- - Path defines the path of the patch. - Note: Only the spec of a template can be patched, thus the path has to start with /spec/. - Note: For now the only allowed array modifications are `append` and `prepend`, i.e.: - * for op: `add`: only index 0 (prepend) and - (append) are allowed - * for op: `replace` or `remove`: no indexes are allowed - type: string - value: - description: |- - Value defines the value of the patch. - Note: Either Value or ValueFrom is required for add and replace - operations. Only one of them is allowed to be set at the same time. - Note: We have to use apiextensionsv1.JSON instead of our JSON type, - because controller-tools has a hard-coded schema for apiextensionsv1.JSON - which cannot be produced by another type (unset type field). - Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111 - x-kubernetes-preserve-unknown-fields: true - valueFrom: - description: |- - ValueFrom defines the value of the patch. - Note: Either Value or ValueFrom is required for add and replace - operations. Only one of them is allowed to be set at the same time. - properties: - template: - description: |- - Template is the Go template to be used to calculate the value. - A template can reference variables defined in .spec.variables and builtin variables. - Note: The template must evaluate to a valid YAML or JSON value. - type: string - variable: - description: |- - Variable is the variable to be used as value. - Variable can be one of the variables defined in .spec.variables or a builtin variable. - type: string - type: object - required: - - op - - path - type: object - type: array - selector: - description: Selector defines on which templates the patch - should be applied. - properties: - apiVersion: - description: APIVersion filters templates by apiVersion. - type: string - kind: - description: Kind filters templates by kind. - type: string - matchResources: - description: MatchResources selects templates based - on where they are referenced. - properties: - controlPlane: - description: |- - ControlPlane selects templates referenced in .spec.ControlPlane. - Note: this will match the controlPlane and also the controlPlane - machineInfrastructure (depending on the kind and apiVersion). - type: boolean - infrastructureCluster: - description: InfrastructureCluster selects templates - referenced in .spec.infrastructure. - type: boolean - machineDeploymentClass: - description: |- - MachineDeploymentClass selects templates referenced in specific MachineDeploymentClasses in - .spec.workers.machineDeployments. - properties: - names: - description: Names selects templates by class - names. - items: - type: string - type: array - type: object - machinePoolClass: - description: |- - MachinePoolClass selects templates referenced in specific MachinePoolClasses in - .spec.workers.machinePools. - properties: - names: - description: Names selects templates by class - names. - items: - type: string - type: array - type: object - type: object - required: - - apiVersion - - kind - - matchResources - type: object - required: - - jsonPatches - - selector - type: object - type: array - description: - description: Description is a human-readable description of - this patch. - type: string - enabledIf: - description: |- - EnabledIf is a Go template to be used to calculate if a patch should be enabled. - It can reference variables defined in .spec.variables and builtin variables. - The patch will be enabled if the template evaluates to `true`, otherwise it will - be disabled. - If EnabledIf is not set, the patch will be enabled per default. - type: string - external: - description: |- - External defines an external patch. - Note: Exactly one of Definitions or External must be set. - properties: - discoverVariablesExtension: - description: DiscoverVariablesExtension references an extension - which is called to discover variables. - type: string - generateExtension: - description: GenerateExtension references an extension which - is called to generate patches. - type: string - settings: - additionalProperties: - type: string - description: |- - Settings defines key value pairs to be passed to the extensions. - Values defined here take precedence over the values defined in the - corresponding ExtensionConfig. - type: object - validateExtension: - description: ValidateExtension references an extension which - is called to validate the topology. - type: string - type: object - name: - description: Name of the patch. - type: string - required: - - name - type: object - type: array - variables: - description: |- - Variables defines the variables which can be configured - in the Cluster topology and are then used in patches. - items: - description: |- - ClusterClassVariable defines a variable which can - be configured in the Cluster topology and used in patches. - properties: - metadata: - description: |- - Metadata is the metadata of a variable. - It can be used to add additional data for higher level tools to - a ClusterClassVariable. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map that can be used to store and - retrieve arbitrary metadata. - They are not queryable. - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) variables. - type: object - type: object - name: - description: Name of the variable. - type: string - required: - description: |- - Required specifies if the variable is required. - Note: this applies to the variable as a whole and thus the - top-level object defined in the schema. If nested fields are - required, this will be specified inside the schema. - type: boolean - schema: - description: Schema defines the schema of the variable. - properties: - openAPIV3Schema: - description: |- - OpenAPIV3Schema defines the schema of a variable via OpenAPI v3 - schema. The schema is a subset of the schema used in - Kubernetes CRDs. - properties: - additionalProperties: - description: |- - AdditionalProperties specifies the schema of values in a map (keys are always strings). - NOTE: Can only be set if type is object. - NOTE: AdditionalProperties is mutually exclusive with Properties. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - default: - description: |- - Default is the default value of the variable. - NOTE: Can be set for all types. - x-kubernetes-preserve-unknown-fields: true - description: - description: Description is a human-readable description - of this variable. - type: string - enum: - description: |- - Enum is the list of valid values of the variable. - NOTE: Can be set for all types. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - example: - description: Example is an example for this variable. - x-kubernetes-preserve-unknown-fields: true - exclusiveMaximum: - description: |- - ExclusiveMaximum specifies if the Maximum is exclusive. - NOTE: Can only be set if type is integer or number. - type: boolean - exclusiveMinimum: - description: |- - ExclusiveMinimum specifies if the Minimum is exclusive. - NOTE: Can only be set if type is integer or number. - type: boolean - format: - description: |- - Format is an OpenAPI v3 format string. Unknown formats are ignored. - For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using) - https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go - NOTE: Can only be set if type is string. - type: string - items: - description: |- - Items specifies fields of an array. - NOTE: Can only be set if type is array. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - maxItems: - description: |- - MaxItems is the max length of an array variable. - NOTE: Can only be set if type is array. - format: int64 - type: integer - maxLength: - description: |- - MaxLength is the max length of a string variable. - NOTE: Can only be set if type is string. - format: int64 - type: integer - maximum: - description: |- - Maximum is the maximum of an integer or number variable. - If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum. - If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum. - NOTE: Can only be set if type is integer or number. - format: int64 - type: integer - minItems: - description: |- - MinItems is the min length of an array variable. - NOTE: Can only be set if type is array. - format: int64 - type: integer - minLength: - description: |- - MinLength is the min length of a string variable. - NOTE: Can only be set if type is string. - format: int64 - type: integer - minimum: - description: |- - Minimum is the minimum of an integer or number variable. - If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum. - If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum. - NOTE: Can only be set if type is integer or number. - format: int64 - type: integer - pattern: - description: |- - Pattern is the regex which a string variable must match. - NOTE: Can only be set if type is string. - type: string - properties: - description: |- - Properties specifies fields of an object. - NOTE: Can only be set if type is object. - NOTE: Properties is mutually exclusive with AdditionalProperties. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - required: - description: |- - Required specifies which fields of an object are required. - NOTE: Can only be set if type is object. - items: - type: string - type: array - type: - description: |- - Type is the type of the variable. - Valid values are: object, array, string, integer, number or boolean. - type: string - uniqueItems: - description: |- - UniqueItems specifies if items in an array must be unique. - NOTE: Can only be set if type is array. - type: boolean - x-kubernetes-preserve-unknown-fields: - description: |- - XPreserveUnknownFields allows setting fields in a variable object - which are not defined in the variable schema. This affects fields recursively, - except if nested properties or additionalProperties are specified in the schema. - type: boolean - required: - - type - type: object - required: - - openAPIV3Schema - type: object - required: - - name - - required - - schema - type: object - type: array - workers: - description: |- - Workers describes the worker nodes for the cluster. - It is a collection of node types which can be used to create - the worker nodes of the cluster. - properties: - machineDeployments: - description: |- - MachineDeployments is a list of machine deployment classes that can be used to create - a set of worker nodes. - items: - description: |- - MachineDeploymentClass serves as a template to define a set of worker nodes of the cluster - provisioned using the `ClusterClass`. - properties: - class: - description: |- - Class denotes a type of worker node present in the cluster, - this name MUST be unique within a ClusterClass and can be referenced - in the Cluster to create a managed MachineDeployment. - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machines will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - type: string - machineHealthCheck: - description: MachineHealthCheck defines a MachineHealthCheck - for this MachineDeploymentClass. - properties: - maxUnhealthy: - anyOf: - - type: integer - - type: string - description: |- - Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by - "selector" are not healthy. - x-kubernetes-int-or-string: true - nodeStartupTimeout: - description: |- - Machines older than this duration without a node will be considered to have - failed and will be remediated. - If you wish to disable this feature, set the value explicitly to 0. - type: string - remediationTemplate: - description: |- - RemediationTemplate is a reference to a remediation template - provided by an infrastructure provider. - - - This field is completely optional, when filled, the MachineHealthCheck controller - creates a new object from the template referenced and hands off remediation of the machine to - a controller that lives outside of Cluster API. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - unhealthyConditions: - description: |- - UnhealthyConditions contains a list of the conditions that determine - whether a node is considered unhealthy. The conditions are combined in a - logical OR, i.e. if any of the conditions is met, the node is unhealthy. - items: - description: |- - UnhealthyCondition represents a Node condition type and value with a timeout - specified as a duration. When the named condition has been in the given - status for at least the timeout value, a node is considered unhealthy. - properties: - status: - minLength: 1 - type: string - timeout: - type: string - type: - minLength: 1 - type: string - required: - - status - - timeout - - type - type: object - type: array - unhealthyRange: - description: |- - Any further remediation is only allowed if the number of machines selected by "selector" as not healthy - is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy. - Eg. "[3-5]" - This means that remediation will be allowed only when: - (a) there are at least 3 unhealthy machines (and) - (b) there are at most 5 unhealthy machines - pattern: ^\[[0-9]+-[0-9]+\]$ - type: string - type: object - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine should - be ready. - Defaults to 0 (machine will be considered available as soon as it - is ready) - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - format: int32 - type: integer - namingStrategy: - description: NamingStrategy allows changing the naming pattern - used when creating the MachineDeployment. - properties: - template: - description: |- - Template defines the template to use for generating the name of the MachineDeployment object. - If not defined, it will fallback to `{{ .cluster.name }}-{{ .machineDeployment.topologyName }}-{{ .random }}`. - If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will - get concatenated with a random suffix of length 5. - The templating mechanism provides the following arguments: - * `.cluster.name`: The name of the cluster object. - * `.random`: A random alphanumeric string, without vowels, of length 5. - * `.machineDeployment.topologyName`: The name of the MachineDeployment topology (Cluster.spec.topology.workers.machineDeployments[].name). - type: string - type: object - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - type: string - strategy: - description: |- - The deployment strategy to use to replace existing machines with - new ones. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachineDeploymentClass. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if - MachineDeploymentStrategyType = RollingUpdate. - properties: - deletePolicy: - description: |- - DeletePolicy defines the policy used by the MachineDeployment to identify nodes to delete when downscaling. - Valid values are "Random, "Newest", "Oldest" - When no value is supplied, the default DeletePolicy of MachineSet is used - enum: - - Random - - Newest - - Oldest - type: string - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be scheduled above the - desired number of machines. - Value can be an absolute number (ex: 5) or a percentage of - desired machines (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 1. - Example: when this is set to 30%, the new MachineSet can be scaled - up immediately when the rolling update starts, such that the total - number of old and new machines do not exceed 130% of desired - machines. Once old machines have been killed, new MachineSet can - be scaled up further, ensuring that total number of machines running - at any time during the update is at most 130% of desired machines. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired - machines (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 0. - Example: when this is set to 30%, the old MachineSet can be scaled - down to 70% of desired machines immediately when the rolling update - starts. Once new machines are ready, old MachineSet can be scaled - down further, followed by scaling up the new MachineSet, ensuring - that the total number of machines available at all times - during the update is at least 70% of desired machines. - x-kubernetes-int-or-string: true - type: object - type: - description: |- - Type of deployment. Allowed values are RollingUpdate and OnDelete. - The default is RollingUpdate. - enum: - - RollingUpdate - - OnDelete - type: string - type: object - template: - description: |- - Template is a local struct containing a collection of templates for creation of - MachineDeployment objects representing a set of worker nodes. - properties: - bootstrap: - description: |- - Bootstrap contains the bootstrap template reference to be used - for the creation of worker Machines. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - infrastructure: - description: |- - Infrastructure contains the infrastructure template reference to be used - for the creation of worker Machines. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - metadata: - description: |- - Metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. - At runtime this metadata is merged with the corresponding metadata from the topology. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - required: - - bootstrap - - infrastructure - type: object - required: - - class - - template - type: object - type: array - machinePools: - description: |- - MachinePools is a list of machine pool classes that can be used to create - a set of worker nodes. - items: - description: |- - MachinePoolClass serves as a template to define a pool of worker nodes of the cluster - provisioned using `ClusterClass`. - properties: - class: - description: |- - Class denotes a type of machine pool present in the cluster, - this name MUST be unique within a ClusterClass and can be referenced - in the Cluster to create a managed MachinePool. - type: string - failureDomains: - description: |- - FailureDomains is the list of failure domains the MachinePool should be attached to. - Must match a key in the FailureDomains map stored on the cluster object. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass. - items: - type: string - type: array - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine pool should - be ready. - Defaults to 0 (machine will be considered available as soon as it - is ready) - NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass. - format: int32 - type: integer - namingStrategy: - description: NamingStrategy allows changing the naming pattern - used when creating the MachinePool. - properties: - template: - description: |- - Template defines the template to use for generating the name of the MachinePool object. - If not defined, it will fallback to `{{ .cluster.name }}-{{ .machinePool.topologyName }}-{{ .random }}`. - If the templated string exceeds 63 characters, it will be trimmed to 58 characters and will - get concatenated with a random suffix of length 5. - The templating mechanism provides the following arguments: - * `.cluster.name`: The name of the cluster object. - * `.random`: A random alphanumeric string, without vowels, of length 5. - * `.machinePool.topologyName`: The name of the MachinePool topology (Cluster.spec.topology.workers.machinePools[].name). - type: string - type: object - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine Pool is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass. - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - NOTE: This value can be overridden while defining a Cluster.Topology using this MachinePoolClass. - type: string - template: - description: |- - Template is a local struct containing a collection of templates for creation of - MachinePools objects representing a pool of worker nodes. - properties: - bootstrap: - description: |- - Bootstrap contains the bootstrap template reference to be used - for the creation of the Machines in the MachinePool. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - infrastructure: - description: |- - Infrastructure contains the infrastructure template reference to be used - for the creation of the MachinePool. - properties: - ref: - description: |- - Ref is a required reference to a custom resource - offered by a provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - required: - - ref - type: object - metadata: - description: |- - Metadata is the metadata applied to the MachinePool. - At runtime this metadata is merged with the corresponding metadata from the topology. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - required: - - bootstrap - - infrastructure - type: object - required: - - class - - template - type: object - type: array - type: object - type: object - status: - description: ClusterClassStatus defines the observed state of the ClusterClass. - properties: - conditions: - description: Conditions defines current observed state of the ClusterClass. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - variables: - description: Variables is a list of ClusterClassStatusVariable that - are defined for the ClusterClass. - items: - description: ClusterClassStatusVariable defines a variable which - appears in the status of a ClusterClass. - properties: - definitions: - description: Definitions is a list of definitions for a variable. - items: - description: ClusterClassStatusVariableDefinition defines - a variable which appears in the status of a ClusterClass. - properties: - from: - description: |- - From specifies the origin of the variable definition. - This will be `inline` for variables defined in the ClusterClass or the name of a patch defined in the ClusterClass - for variables discovered from a DiscoverVariables runtime extensions. - type: string - metadata: - description: |- - Metadata is the metadata of a variable. - It can be used to add additional data for higher level tools to - a ClusterClassVariable. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map that can be used to store and - retrieve arbitrary metadata. - They are not queryable. - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) variables. - type: object - type: object - required: - description: |- - Required specifies if the variable is required. - Note: this applies to the variable as a whole and thus the - top-level object defined in the schema. If nested fields are - required, this will be specified inside the schema. - type: boolean - schema: - description: Schema defines the schema of the variable. - properties: - openAPIV3Schema: - description: |- - OpenAPIV3Schema defines the schema of a variable via OpenAPI v3 - schema. The schema is a subset of the schema used in - Kubernetes CRDs. - properties: - additionalProperties: - description: |- - AdditionalProperties specifies the schema of values in a map (keys are always strings). - NOTE: Can only be set if type is object. - NOTE: AdditionalProperties is mutually exclusive with Properties. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - default: - description: |- - Default is the default value of the variable. - NOTE: Can be set for all types. - x-kubernetes-preserve-unknown-fields: true - description: - description: Description is a human-readable description - of this variable. - type: string - enum: - description: |- - Enum is the list of valid values of the variable. - NOTE: Can be set for all types. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - example: - description: Example is an example for this variable. - x-kubernetes-preserve-unknown-fields: true - exclusiveMaximum: - description: |- - ExclusiveMaximum specifies if the Maximum is exclusive. - NOTE: Can only be set if type is integer or number. - type: boolean - exclusiveMinimum: - description: |- - ExclusiveMinimum specifies if the Minimum is exclusive. - NOTE: Can only be set if type is integer or number. - type: boolean - format: - description: |- - Format is an OpenAPI v3 format string. Unknown formats are ignored. - For a list of supported formats please see: (of the k8s.io/apiextensions-apiserver version we're currently using) - https://github.com/kubernetes/apiextensions-apiserver/blob/master/pkg/apiserver/validation/formats.go - NOTE: Can only be set if type is string. - type: string - items: - description: |- - Items specifies fields of an array. - NOTE: Can only be set if type is array. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - maxItems: - description: |- - MaxItems is the max length of an array variable. - NOTE: Can only be set if type is array. - format: int64 - type: integer - maxLength: - description: |- - MaxLength is the max length of a string variable. - NOTE: Can only be set if type is string. - format: int64 - type: integer - maximum: - description: |- - Maximum is the maximum of an integer or number variable. - If ExclusiveMaximum is false, the variable is valid if it is lower than, or equal to, the value of Maximum. - If ExclusiveMaximum is true, the variable is valid if it is strictly lower than the value of Maximum. - NOTE: Can only be set if type is integer or number. - format: int64 - type: integer - minItems: - description: |- - MinItems is the min length of an array variable. - NOTE: Can only be set if type is array. - format: int64 - type: integer - minLength: - description: |- - MinLength is the min length of a string variable. - NOTE: Can only be set if type is string. - format: int64 - type: integer - minimum: - description: |- - Minimum is the minimum of an integer or number variable. - If ExclusiveMinimum is false, the variable is valid if it is greater than, or equal to, the value of Minimum. - If ExclusiveMinimum is true, the variable is valid if it is strictly greater than the value of Minimum. - NOTE: Can only be set if type is integer or number. - format: int64 - type: integer - pattern: - description: |- - Pattern is the regex which a string variable must match. - NOTE: Can only be set if type is string. - type: string - properties: - description: |- - Properties specifies fields of an object. - NOTE: Can only be set if type is object. - NOTE: Properties is mutually exclusive with AdditionalProperties. - NOTE: This field uses PreserveUnknownFields and Schemaless, - because recursive validation is not possible. - x-kubernetes-preserve-unknown-fields: true - required: - description: |- - Required specifies which fields of an object are required. - NOTE: Can only be set if type is object. - items: - type: string - type: array - type: - description: |- - Type is the type of the variable. - Valid values are: object, array, string, integer, number or boolean. - type: string - uniqueItems: - description: |- - UniqueItems specifies if items in an array must be unique. - NOTE: Can only be set if type is array. - type: boolean - x-kubernetes-preserve-unknown-fields: - description: |- - XPreserveUnknownFields allows setting fields in a variable object - which are not defined in the variable schema. This affects fields recursively, - except if nested properties or additionalProperties are specified in the schema. - type: boolean - required: - - type - type: object - required: - - openAPIV3Schema - type: object - required: - - from - - required - - schema - type: object - type: array - definitionsConflict: - description: DefinitionsConflict specifies whether or not there - are conflicting definitions for a single variable name. - type: boolean - name: - description: Name is the name of the variable. - type: string - required: - - definitions - - name - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesetbindings.addons.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesetbindings.addons.cluster.x-k8s.io.yaml deleted file mode 100644 index a87670506..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesetbindings.addons.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,121 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: clusterresourcesetbindings.addons.cluster.x-k8s.io -spec: - group: addons.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: ClusterResourceSetBinding - listKind: ClusterResourceSetBindingList - plural: clusterresourcesetbindings - singular: clusterresourcesetbinding - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of ClusterResourceSetBinding - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterResourceSetBinding lists all matching ClusterResourceSets - with the cluster it belongs to. - 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: ClusterResourceSetBindingSpec defines the desired state of - ClusterResourceSetBinding. - properties: - bindings: - description: Bindings is a list of ClusterResourceSets and their resources. - items: - description: ResourceSetBinding keeps info on all of the resources - in a ClusterResourceSet. - properties: - clusterResourceSetName: - description: ClusterResourceSetName is the name of the ClusterResourceSet - that is applied to the owner cluster of the binding. - type: string - resources: - description: Resources is a list of resources that the ClusterResourceSet - has. - items: - description: ResourceBinding shows the status of a resource - that belongs to a ClusterResourceSet matched by the owner - cluster of the ClusterResourceSetBinding object. - properties: - applied: - description: Applied is to track if a resource is applied - to the cluster or not. - type: boolean - hash: - description: |- - Hash is the hash of a resource's data. This can be used to decide if a resource is changed. - For "ApplyOnce" ClusterResourceSet.spec.strategy, this is no-op as that strategy does not act on change. - type: string - kind: - description: 'Kind of the resource. Supported kinds are: - Secrets and ConfigMaps.' - enum: - - Secret - - ConfigMap - type: string - lastAppliedTime: - description: LastAppliedTime identifies when this resource - was last applied to the cluster. - format: date-time - type: string - name: - description: Name of the resource that is in the same - namespace with ClusterResourceSet object. - minLength: 1 - type: string - required: - - applied - - kind - - name - type: object - type: array - required: - - clusterResourceSetName - type: object - type: array - clusterName: - description: |- - ClusterName is the name of the Cluster this binding applies to. - Note: this field mandatory in v1beta2. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesets.addons.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesets.addons.cluster.x-k8s.io.yaml deleted file mode 100644 index 6be48a1a5..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-clusterresourcesets.addons.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,197 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: clusterresourcesets.addons.cluster.x-k8s.io -spec: - group: addons.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: ClusterResourceSet - listKind: ClusterResourceSetList - plural: clusterresourcesets - singular: clusterresourceset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of ClusterResourceSet - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: ClusterResourceSet is the Schema for the clusterresourcesets - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterResourceSetSpec defines the desired state of ClusterResourceSet. - properties: - clusterSelector: - description: |- - Label selector for Clusters. The Clusters that are - selected by this will be the ones affected by this ClusterResourceSet. - It must match the Cluster labels. This field is immutable. - Label selector cannot be empty. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - resources: - description: Resources is a list of Secrets/ConfigMaps where each - contains 1 or more resources to be applied to remote clusters. - items: - description: ResourceRef specifies a resource. - properties: - kind: - description: 'Kind of the resource. Supported kinds are: Secrets - and ConfigMaps.' - enum: - - Secret - - ConfigMap - type: string - name: - description: Name of the resource that is in the same namespace - with ClusterResourceSet object. - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - strategy: - description: Strategy is the strategy to be used during applying resources. - Defaults to ApplyOnce. This field is immutable. - enum: - - ApplyOnce - - Reconcile - type: string - required: - - clusterSelector - type: object - status: - description: ClusterResourceSetStatus defines the observed state of ClusterResourceSet. - properties: - conditions: - description: Conditions defines current state of the ClusterResourceSet. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration reflects the generation of the most - recently observed ClusterResourceSet. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-clusters.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-clusters.cluster.x-k8s.io.yaml deleted file mode 100644 index 20168a0f3..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-clusters.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1000 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: clusters.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: Cluster - listKind: ClusterList - plural: clusters - shortNames: - - cl - singular: cluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: ClusterClass of this Cluster, empty if the Cluster is not using - a ClusterClass - jsonPath: .spec.topology.class - name: ClusterClass - type: string - - description: Cluster status such as Pending/Provisioning/Provisioned/Deleting/Failed - jsonPath: .status.phase - name: Phase - type: string - - description: Time duration since creation of Cluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Kubernetes version associated with this Cluster - jsonPath: .spec.topology.version - name: Version - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: Cluster is the Schema for the clusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ClusterSpec defines the desired state of Cluster. - properties: - clusterNetwork: - description: Cluster network configuration. - properties: - apiServerPort: - description: |- - APIServerPort specifies the port the API Server should bind to. - Defaults to 6443. - format: int32 - type: integer - pods: - description: The network ranges from which Pod networks are allocated. - properties: - cidrBlocks: - items: - type: string - type: array - required: - - cidrBlocks - type: object - serviceDomain: - description: Domain name for services. - type: string - services: - description: The network ranges from which service VIPs are allocated. - properties: - cidrBlocks: - items: - type: string - type: array - required: - - cidrBlocks - type: object - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneRef: - description: |- - ControlPlaneRef is an optional reference to a provider-specific resource that holds - the details for provisioning the Control Plane for a Cluster. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - infrastructureRef: - description: |- - InfrastructureRef is a reference to a provider-specific resource that holds the details - for provisioning infrastructure for a cluster in said provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - paused: - description: Paused can be used to prevent controllers from processing - the Cluster and all its associated objects. - type: boolean - topology: - description: |- - This encapsulates the topology for the cluster. - NOTE: It is required to enable the ClusterTopology - feature gate flag to activate managed topologies support; - this feature is highly experimental, and parts of it might still be not implemented. - properties: - class: - description: The name of the ClusterClass object to create the - topology. - type: string - controlPlane: - description: ControlPlane describes the cluster control plane. - properties: - machineHealthCheck: - description: |- - MachineHealthCheck allows to enable, disable and override - the MachineHealthCheck configuration in the ClusterClass for this control plane. - properties: - enable: - description: |- - Enable controls if a MachineHealthCheck should be created for the target machines. - - - If false: No MachineHealthCheck will be created. - - - If not set(default): A MachineHealthCheck will be created if it is defined here or - in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created. - - - If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will - block if `enable` is true and no MachineHealthCheck definition is available. - type: boolean - maxUnhealthy: - anyOf: - - type: integer - - type: string - description: |- - Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by - "selector" are not healthy. - x-kubernetes-int-or-string: true - nodeStartupTimeout: - description: |- - Machines older than this duration without a node will be considered to have - failed and will be remediated. - If you wish to disable this feature, set the value explicitly to 0. - type: string - remediationTemplate: - description: |- - RemediationTemplate is a reference to a remediation template - provided by an infrastructure provider. - - - This field is completely optional, when filled, the MachineHealthCheck controller - creates a new object from the template referenced and hands off remediation of the machine to - a controller that lives outside of Cluster API. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - unhealthyConditions: - description: |- - UnhealthyConditions contains a list of the conditions that determine - whether a node is considered unhealthy. The conditions are combined in a - logical OR, i.e. if any of the conditions is met, the node is unhealthy. - items: - description: |- - UnhealthyCondition represents a Node condition type and value with a timeout - specified as a duration. When the named condition has been in the given - status for at least the timeout value, a node is considered unhealthy. - properties: - status: - minLength: 1 - type: string - timeout: - type: string - type: - minLength: 1 - type: string - required: - - status - - timeout - - type - type: object - type: array - unhealthyRange: - description: |- - Any further remediation is only allowed if the number of machines selected by "selector" as not healthy - is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy. - Eg. "[3-5]" - This means that remediation will be allowed only when: - (a) there are at least 3 unhealthy machines (and) - (b) there are at most 5 unhealthy machines - pattern: ^\[[0-9]+-[0-9]+\]$ - type: string - type: object - metadata: - description: |- - Metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane - if the ControlPlaneTemplate referenced by the ClusterClass is machine based. If not, it - is applied only to the ControlPlane. - At runtime this metadata is merged with the corresponding metadata from the ClusterClass. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - replicas: - description: |- - Replicas is the number of control plane nodes. - If the value is nil, the ControlPlane object is created without the number of Replicas - and it's assumed that the control plane controller does not implement support for this field. - When specified against a control plane provider that lacks support for this field, this value will be ignored. - format: int32 - type: integer - type: object - rolloutAfter: - description: |- - RolloutAfter performs a rollout of the entire cluster one component at a time, - control plane first and then machine deployments. - - - Deprecated: This field has no function and is going to be removed in the next apiVersion. - format: date-time - type: string - variables: - description: |- - Variables can be used to customize the Cluster through - patches. They must comply to the corresponding - VariableClasses defined in the ClusterClass. - items: - description: |- - ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a - Variable definition in the ClusterClass `status` variables. - properties: - definitionFrom: - description: |- - DefinitionFrom specifies where the definition of this Variable is from. DefinitionFrom is `inline` when the - definition is from the ClusterClass `.spec.variables` or the name of a patch defined in the ClusterClass - `.spec.patches` where the patch is external and provides external variables. - This field is mandatory if the variable has `DefinitionsConflict: true` in ClusterClass `status.variables[]` - type: string - name: - description: Name of the variable. - type: string - value: - description: |- - Value of the variable. - Note: the value will be validated against the schema of the corresponding ClusterClassVariable - from the ClusterClass. - Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a - hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools, - i.e. it is not possible to have no type field. - Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111 - x-kubernetes-preserve-unknown-fields: true - required: - - name - - value - type: object - type: array - version: - description: The Kubernetes version of the cluster. - type: string - workers: - description: |- - Workers encapsulates the different constructs that form the worker nodes - for the cluster. - properties: - machineDeployments: - description: MachineDeployments is a list of machine deployments - in the cluster. - items: - description: |- - MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology. - This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller. - properties: - class: - description: |- - Class is the name of the MachineDeploymentClass used to create the set of worker nodes. - This should match one of the deployment classes defined in the ClusterClass object - mentioned in the `Cluster.Spec.Class` field. - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machines will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - type: string - machineHealthCheck: - description: |- - MachineHealthCheck allows to enable, disable and override - the MachineHealthCheck configuration in the ClusterClass for this MachineDeployment. - properties: - enable: - description: |- - Enable controls if a MachineHealthCheck should be created for the target machines. - - - If false: No MachineHealthCheck will be created. - - - If not set(default): A MachineHealthCheck will be created if it is defined here or - in the associated ClusterClass. If no MachineHealthCheck is defined then none will be created. - - - If true: A MachineHealthCheck is guaranteed to be created. Cluster validation will - block if `enable` is true and no MachineHealthCheck definition is available. - type: boolean - maxUnhealthy: - anyOf: - - type: integer - - type: string - description: |- - Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by - "selector" are not healthy. - x-kubernetes-int-or-string: true - nodeStartupTimeout: - description: |- - Machines older than this duration without a node will be considered to have - failed and will be remediated. - If you wish to disable this feature, set the value explicitly to 0. - type: string - remediationTemplate: - description: |- - RemediationTemplate is a reference to a remediation template - provided by an infrastructure provider. - - - This field is completely optional, when filled, the MachineHealthCheck controller - creates a new object from the template referenced and hands off remediation of the machine to - a controller that lives outside of Cluster API. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - unhealthyConditions: - description: |- - UnhealthyConditions contains a list of the conditions that determine - whether a node is considered unhealthy. The conditions are combined in a - logical OR, i.e. if any of the conditions is met, the node is unhealthy. - items: - description: |- - UnhealthyCondition represents a Node condition type and value with a timeout - specified as a duration. When the named condition has been in the given - status for at least the timeout value, a node is considered unhealthy. - properties: - status: - minLength: 1 - type: string - timeout: - type: string - type: - minLength: 1 - type: string - required: - - status - - timeout - - type - type: object - type: array - unhealthyRange: - description: |- - Any further remediation is only allowed if the number of machines selected by "selector" as not healthy - is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy. - Eg. "[3-5]" - This means that remediation will be allowed only when: - (a) there are at least 3 unhealthy machines (and) - (b) there are at most 5 unhealthy machines - pattern: ^\[[0-9]+-[0-9]+\]$ - type: string - type: object - metadata: - description: |- - Metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. - At runtime this metadata is merged with the corresponding metadata from the ClusterClass. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine should - be ready. - Defaults to 0 (machine will be considered available as soon as it - is ready) - format: int32 - type: integer - name: - description: |- - Name is the unique identifier for this MachineDeploymentTopology. - The value is used with other unique identifiers to create a MachineDeployment's Name - (e.g. cluster's name, etc). In case the name is greater than the allowed maximum length, - the values are hashed together. - type: string - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - replicas: - description: |- - Replicas is the number of worker nodes belonging to this set. - If the value is nil, the MachineDeployment is created without the number of Replicas (defaulting to 1) - and it's assumed that an external entity (like cluster autoscaler) is responsible for the management - of this value. - format: int32 - type: integer - strategy: - description: |- - The deployment strategy to use to replace existing machines with - new ones. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if - MachineDeploymentStrategyType = RollingUpdate. - properties: - deletePolicy: - description: |- - DeletePolicy defines the policy used by the MachineDeployment to identify nodes to delete when downscaling. - Valid values are "Random, "Newest", "Oldest" - When no value is supplied, the default DeletePolicy of MachineSet is used - enum: - - Random - - Newest - - Oldest - type: string - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be scheduled above the - desired number of machines. - Value can be an absolute number (ex: 5) or a percentage of - desired machines (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 1. - Example: when this is set to 30%, the new MachineSet can be scaled - up immediately when the rolling update starts, such that the total - number of old and new machines do not exceed 130% of desired - machines. Once old machines have been killed, new MachineSet can - be scaled up further, ensuring that total number of machines running - at any time during the update is at most 130% of desired machines. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired - machines (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 0. - Example: when this is set to 30%, the old MachineSet can be scaled - down to 70% of desired machines immediately when the rolling update - starts. Once new machines are ready, old MachineSet can be scaled - down further, followed by scaling up the new MachineSet, ensuring - that the total number of machines available at all times - during the update is at least 70% of desired machines. - x-kubernetes-int-or-string: true - type: object - type: - description: |- - Type of deployment. Allowed values are RollingUpdate and OnDelete. - The default is RollingUpdate. - enum: - - RollingUpdate - - OnDelete - type: string - type: object - variables: - description: Variables can be used to customize the - MachineDeployment through patches. - properties: - overrides: - description: Overrides can be used to override Cluster - level variables. - items: - description: |- - ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a - Variable definition in the ClusterClass `status` variables. - properties: - definitionFrom: - description: |- - DefinitionFrom specifies where the definition of this Variable is from. DefinitionFrom is `inline` when the - definition is from the ClusterClass `.spec.variables` or the name of a patch defined in the ClusterClass - `.spec.patches` where the patch is external and provides external variables. - This field is mandatory if the variable has `DefinitionsConflict: true` in ClusterClass `status.variables[]` - type: string - name: - description: Name of the variable. - type: string - value: - description: |- - Value of the variable. - Note: the value will be validated against the schema of the corresponding ClusterClassVariable - from the ClusterClass. - Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a - hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools, - i.e. it is not possible to have no type field. - Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111 - x-kubernetes-preserve-unknown-fields: true - required: - - name - - value - type: object - type: array - type: object - required: - - class - - name - type: object - type: array - machinePools: - description: MachinePools is a list of machine pools in the - cluster. - items: - description: |- - MachinePoolTopology specifies the different parameters for a pool of worker nodes in the topology. - This pool of nodes is managed by a MachinePool object whose lifecycle is managed by the Cluster controller. - properties: - class: - description: |- - Class is the name of the MachinePoolClass used to create the pool of worker nodes. - This should match one of the deployment classes defined in the ClusterClass object - mentioned in the `Cluster.Spec.Class` field. - type: string - failureDomains: - description: |- - FailureDomains is the list of failure domains the machine pool will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - items: - type: string - type: array - metadata: - description: |- - Metadata is the metadata applied to the MachinePool. - At runtime this metadata is merged with the corresponding metadata from the ClusterClass. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine pool should - be ready. - Defaults to 0 (machine will be considered available as soon as it - is ready) - format: int32 - type: integer - name: - description: |- - Name is the unique identifier for this MachinePoolTopology. - The value is used with other unique identifiers to create a MachinePool's Name - (e.g. cluster's name, etc). In case the name is greater than the allowed maximum length, - the values are hashed together. - type: string - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the MachinePool - hosts after the MachinePool is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - replicas: - description: |- - Replicas is the number of nodes belonging to this pool. - If the value is nil, the MachinePool is created without the number of Replicas (defaulting to 1) - and it's assumed that an external entity (like cluster autoscaler) is responsible for the management - of this value. - format: int32 - type: integer - variables: - description: Variables can be used to customize the - MachinePool through patches. - properties: - overrides: - description: Overrides can be used to override Cluster - level variables. - items: - description: |- - ClusterVariable can be used to customize the Cluster through patches. Each ClusterVariable is associated with a - Variable definition in the ClusterClass `status` variables. - properties: - definitionFrom: - description: |- - DefinitionFrom specifies where the definition of this Variable is from. DefinitionFrom is `inline` when the - definition is from the ClusterClass `.spec.variables` or the name of a patch defined in the ClusterClass - `.spec.patches` where the patch is external and provides external variables. - This field is mandatory if the variable has `DefinitionsConflict: true` in ClusterClass `status.variables[]` - type: string - name: - description: Name of the variable. - type: string - value: - description: |- - Value of the variable. - Note: the value will be validated against the schema of the corresponding ClusterClassVariable - from the ClusterClass. - Note: We have to use apiextensionsv1.JSON instead of a custom JSON type, because controller-tools has a - hard-coded schema for apiextensionsv1.JSON which cannot be produced by another type via controller-tools, - i.e. it is not possible to have no type field. - Ref: https://github.com/kubernetes-sigs/controller-tools/blob/d0e03a142d0ecdd5491593e941ee1d6b5d91dba6/pkg/crd/known_types.go#L106-L111 - x-kubernetes-preserve-unknown-fields: true - required: - - name - - value - type: object - type: array - type: object - required: - - class - - name - type: object - type: array - type: object - required: - - class - - version - type: object - type: object - status: - description: ClusterStatus defines the observed state of Cluster. - properties: - conditions: - description: Conditions defines current service state of the cluster. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - controlPlaneReady: - description: ControlPlaneReady defines if the control plane is ready. - type: boolean - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains is a slice of failure domain objects synced - from the infrastructure provider. - type: object - failureMessage: - description: |- - FailureMessage indicates that there is a fatal problem reconciling the - state, and will be set to a descriptive error message. - type: string - failureReason: - description: |- - FailureReason indicates that there is a fatal problem reconciling the - state, and will be set to a token value suitable for - programmatic interpretation. - type: string - infrastructureReady: - description: InfrastructureReady is the state of the infrastructure - provider. - type: boolean - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - phase: - description: |- - Phase represents the current phase of cluster actuation. - E.g. Pending, Running, Terminating, Failed etc. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-clustersizingconfigurations.scheduling.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-clustersizingconfigurations.scheduling.hypershift.openshift.io.yaml deleted file mode 100644 index 3c4df36a6..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-clustersizingconfigurations.scheduling.hypershift.openshift.io.yaml +++ /dev/null @@ -1,332 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: clustersizingconfigurations.scheduling.hypershift.openshift.io -spec: - group: scheduling.hypershift.openshift.io - names: - kind: ClusterSizingConfiguration - listKind: ClusterSizingConfigurationList - plural: clustersizingconfigurations - shortNames: - - csc - - cscs - singular: clustersizingconfiguration - scope: Cluster - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - ClusterSizingConfiguration defines the desired state of ClusterSizingConfiguration. - Configuration options here allow management cluster administrators to define sizing classes for hosted clusters and - how the system should adapt hosted cluster functionality based on size. - 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: ClusterSizingConfigurationSpec defines the desired state - of ClusterSizingConfiguration - properties: - concurrency: - description: |- - Concurrency defines the bounds of allowed behavior for clusters transitioning between sizes. - Transitions will require that request-serving pods be re-scheduled between nodes, so each - transition incurs a small user-facing cost as well as a cost to the management cluster. Use - the concurrency configuration options to manage how many transitions can be occurring. - These limits do not apply to new clusters entering the fleet. - If unset, a sensible default will be provided. - properties: - limit: - default: 5 - description: Limit is the maximum allowed number of cluster size - transitions during the sliding window. - format: int32 - minimum: 1 - type: integer - slidingWindow: - default: 10m - description: SlidingWindow is the window over which the concurrency - bound is enforced. - pattern: ^([0-9]+(\.[0-9]+)?(s|m|h))+$ - type: string - type: object - nonRequestServingNodesBufferPerZone: - anyOf: - - type: integer - - type: string - description: |- - NonRequestServingNodesBufferPerZone is the number of extra nodes to allocate for non request serving - workloads per zone. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - sizes: - description: |- - Sizes holds the different t-shirt size classes into which guest clusters will be sorted. - Each size class applies to guest clusters using node count criteria; it is required that - the entire interval between [0,+inf) be covered by the set of sizes provided here. - items: - description: SizeConfiguration holds options for clusters of a given - size. - properties: - criteria: - description: Criteria defines the node count range for clusters - to fall into this t-shirt size class. - properties: - from: - description: From is the inclusive lower limit to node count - for a cluster to be considered a particular size. - format: int32 - minimum: 0 - type: integer - to: - description: |- - To is the inclusive upper limit to node count for a cluster to be considered a particular size. - If unset, this size class will match clusters of all sizes greater than the lower limit. - format: int32 - minimum: 0 - type: integer - required: - - from - type: object - x-kubernetes-validations: - - message: lower limit must be less than or equal to the upper - limit - rule: '!has(self.to) || self.from <= self.to' - effects: - description: Effects define the effects on a cluster being considered - part of this t-shirt size class. - properties: - APICriticalPriorityClassName: - description: |- - APICriticalPriorityClassName is the priority class for pods in the API request serving path. - This includes Kube API Server, OpenShift APIServer, etc. - type: string - controlPlanePriorityClassName: - description: ControlPlanePriorityClassName is the priority - class to use for most control plane pods - type: string - etcdPriorityClassName: - description: EtcdPriorityClassName is the priority class - to use for etcd pods - type: string - kasGoMemLimit: - anyOf: - - type: integer - - type: string - description: KASGoMemLimit is the value to set for the $GOMEMLIMIT - of the Kube APIServer container - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - machineHealthCheckTimeout: - description: |- - MachineHealthCheckTimeout specifies an optional timeout for machinehealthchecks created - for HostedClusters with this specific size. - type: string - resourceRequests: - description: ResourceRequests allows specifying resource - requests for control plane pods. - items: - properties: - containerName: - description: ContainerName is the name of the container - to which the resource request applies. - type: string - cpu: - anyOf: - - type: integer - - type: string - description: CPU is the amount of CPU to request for - the container. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - deploymentName: - description: DeploymentName is the name of the deployment - to which the resource request applies. - type: string - memory: - anyOf: - - type: integer - - type: string - description: Memory is the amount of memory to request - for the container. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - required: - - containerName - - deploymentName - type: object - type: array - type: object - management: - description: Management configures the management aspects of - this size class on the management plane. - properties: - nonRequestServingNodesPerZone: - anyOf: - - type: integer - - type: string - description: |- - NonRequestServingNodesPerZone is the number of nodes to allocate for non request serving workloads - per HostedCluster. This will likely be a fraction of a node (ie. 0.2) to allow 5 HostedClusters in - a single node. The total number of nodes needed per HostedCluster is this number multiplied by 3 - (number of zones). - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - placeholders: - description: |- - Placeholders configures the number of dummy workloads that will be scheduled irrespective of - HostedClusters in order to keep a set of nodes ready to accept new cluster creation and scheduling. - minimum: 0 - type: integer - type: object - name: - description: Name is the t-shirt size name. - type: string - required: - - criteria - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - x-kubernetes-validations: - - message: exactly one size class must have a lower limit of zero - rule: self.exists_one(i, i.criteria.from == 0) - - message: exactly one size class must have no upper limit - rule: self.exists_one(i, !has(i.criteria.to)) - transitionDelay: - description: |- - TransitionDelay configures how quickly the system reacts to clusters transitioning between size classes. - It may be advantageous, for instance, to have a near-instant scale-down for clusters that begin to - use fewer resources, but allow for some lag on scale-up to ensure that the use is sustained before - incurring the larger cost for scale-up. - properties: - decrease: - default: 10m - description: |- - Decrease defines the minimum period of time to wait between a cluster's size decreasing and - the t-shirt size assigned to it being updated to reflect the new size. - pattern: ^([0-9]+(\.[0-9]+)?(s|m|h))+$ - type: string - increase: - default: 30s - description: |- - Increase defines the minimum period of time to wait between a cluster's size increasing and - the t-shirt size assigned to it being updated to reflect the new size. - pattern: ^([0-9]+(\.[0-9]+)?(s|m|h))+$ - type: string - type: object - type: object - status: - description: ClusterSizingConfigurationStatus defines the observed state - of ClusterSizingConfiguration - properties: - conditions: - description: Conditions contain details about the various aspects - of cluster sizing. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - x-kubernetes-validations: - - message: exactly one configuration may exist and must be named 'cluster' - rule: self.metadata.name == 'cluster' - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-hostedclusters.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-hostedclusters.hypershift.openshift.io.yaml deleted file mode 100644 index 858630f54..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-hostedclusters.hypershift.openshift.io.yaml +++ /dev/null @@ -1,10260 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: hostedclusters.hypershift.openshift.io -spec: - group: hypershift.openshift.io - names: - kind: HostedCluster - listKind: HostedClusterList - plural: hostedclusters - shortNames: - - hc - - hcs - singular: hostedcluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Version - jsonPath: .status.version.history[?(@.state=="Completed")].version - name: Version - type: string - - description: KubeConfig Secret - jsonPath: .status.kubeconfig.name - name: KubeConfig - type: string - - description: Progress - jsonPath: .status.version.history[?(@.state!="")].state - name: Progress - type: string - - description: Available - jsonPath: .status.conditions[?(@.type=="Available")].status - name: Available - type: string - - description: Progressing - jsonPath: .status.conditions[?(@.type=="Progressing")].status - name: Progressing - type: string - - description: Message - jsonPath: .status.conditions[?(@.type=="Available")].message - name: Message - type: string - deprecated: true - deprecationWarning: v1alpha1 is a deprecated version for HostedCluster - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - HostedCluster is the primary representation of a HyperShift cluster and encapsulates - the control plane and common data plane configuration. Creating a HostedCluster - results in a fully functional OpenShift control plane with no attached nodes. - To support workloads (e.g. pods), a HostedCluster may have one or more associated - NodePool resources. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the desired behavior of the HostedCluster. - properties: - additionalTrustBundle: - description: |- - AdditionalTrustBundle is a reference to a ConfigMap containing a - PEM-encoded X.509 certificate bundle that will be added to the hosted controlplane and nodes - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - auditWebhook: - description: |- - AuditWebhook contains metadata for configuring an audit webhook endpoint - for a cluster to process cluster audit events. It references a secret that - contains the webhook information for the audit webhook endpoint. It is a - secret because if the endpoint has mTLS the kubeconfig will contain client - keys. The kubeconfig needs to be stored in the secret with a secret key - name that corresponds to the constant AuditWebhookKubeconfigKey. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - autoscaling: - description: |- - Autoscaling specifies auto-scaling behavior that applies to all NodePools - associated with the control plane. - properties: - maxNodeProvisionTime: - description: |- - MaxNodeProvisionTime is the maximum time to wait for node provisioning - before considering the provisioning to be unsuccessful, expressed as a Go - duration string. The default is 15 minutes. - pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ - type: string - maxNodesTotal: - description: |- - MaxNodesTotal is the maximum allowable number of nodes across all NodePools - for a HostedCluster. The autoscaler will not grow the cluster beyond this - number. - format: int32 - minimum: 0 - type: integer - maxPodGracePeriod: - description: |- - MaxPodGracePeriod is the maximum seconds to wait for graceful pod - termination before scaling down a NodePool. The default is 600 seconds. - format: int32 - minimum: 0 - type: integer - podPriorityThreshold: - description: |- - PodPriorityThreshold enables users to schedule "best-effort" pods, which - shouldn't trigger autoscaler actions, but only run when there are spare - resources available. The default is -10. - - - See the following for more details: - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-cluster-autoscaler-work-with-pod-priority-and-preemption - format: int32 - type: integer - type: object - channel: - description: |- - channel is an identifier for explicitly requesting that a non-default - set of updates be applied to this cluster. The default channel will be - contain stable updates that are appropriate for production clusters. - type: string - clusterID: - description: |- - ClusterID uniquely identifies this cluster. This is expected to be - an RFC4122 UUID value (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in - hexadecimal values). - As with a Kubernetes metadata.uid, this ID uniquely identifies this - cluster in space and time. - This value identifies the cluster in metrics pushed to telemetry and - metrics produced by the control plane operators. If a value is not - specified, an ID is generated. After initial creation, the value is - immutable. - pattern: '[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}' - type: string - configuration: - description: |- - Configuration specifies configuration for individual OCP components in the - cluster, represented as embedded resources that correspond to the openshift - configuration API. - properties: - apiServer: - description: |- - APIServer holds configuration (like serving certificates, client CA and CORS domains) - shared by all API servers in the system, among them especially kube-apiserver - and openshift-apiserver. - properties: - additionalCORSAllowedOrigins: - description: |- - additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the - API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth - server from JavaScript applications. - The values are regular expressions that correspond to the Golang regular expression language. - items: - type: string - type: array - audit: - default: - profile: Default - description: |- - audit specifies the settings for audit configuration to be applied to all OpenShift-provided - API servers in the cluster. - properties: - customRules: - description: |- - customRules specify profiles per group. These profile take precedence over the - top-level profile field if they apply. They are evaluation from top to bottom and - the first one that matches, applies. - items: - description: |- - AuditCustomRule describes a custom rule for an audit profile that takes precedence over - the top-level profile. - properties: - group: - description: group is a name of group a request - user must be member of in order to this profile - to apply. - minLength: 1 - type: string - profile: - description: |- - profile specifies the name of the desired audit policy configuration to be deployed to - all OpenShift-provided API servers in the cluster. - - - The following profiles are provided: - - Default: the existing default policy. - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - required: - - group - - profile - type: object - type: array - x-kubernetes-list-map-keys: - - group - x-kubernetes-list-type: map - profile: - default: Default - description: |- - profile specifies the name of the desired top-level audit profile to be applied to all requests - sent to any of the OpenShift-provided API servers in the cluster (kube-apiserver, - openshift-apiserver and oauth-apiserver), with the exception of those requests that match - one or more of the customRules. - - - The following profiles are provided: - - Default: default policy which means MetaData level logging with the exception of events - (not logged at all), oauthaccesstokens and oauthauthorizetokens (both logged at RequestBody - level). - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - Warning: It is not recommended to disable audit logging by using the `None` profile unless you - are fully aware of the risks of not logging data that can be beneficial when troubleshooting issues. - If you disable audit logging and a support situation arises, you might need to enable audit logging - and reproduce the issue in order to troubleshoot properly. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - type: object - clientCA: - description: |- - clientCA references a ConfigMap containing a certificate bundle for the signers that will be recognized for - incoming client certificates in addition to the operator managed signers. If this is empty, then only operator managed signers are valid. - You usually only have to set this if you have your own PKI you wish to honor client certificates from. - The ConfigMap must exist in the openshift-config namespace and contain the following required fields: - - ConfigMap.Data["ca-bundle.crt"] - CA bundle. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - encryption: - description: encryption allows the configuration of encryption - of resources at the datastore layer. - properties: - type: - description: |- - type defines what encryption type should be used to encrypt resources at the datastore layer. - When this field is unset (i.e. when it is set to the empty string), identity is implied. - The behavior of unset can and will change over time. Even if encryption is enabled by default, - the meaning of unset may change to a different encryption type based on changes in best practices. - - - When encryption is enabled, all sensitive resources shipped with the platform are encrypted. - This list of sensitive resources can and will change over time. The current authoritative list is: - - - 1. secrets - 2. configmaps - 3. routes.route.openshift.io - 4. oauthaccesstokens.oauth.openshift.io - 5. oauthauthorizetokens.oauth.openshift.io - enum: - - "" - - identity - - aescbc - - aesgcm - type: string - type: object - servingCerts: - description: |- - servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates - will be used for serving secure traffic. - properties: - namedCertificates: - description: |- - namedCertificates references secrets containing the TLS cert info for serving secure traffic to specific hostnames. - If no named certificates are provided, or no named certificates match the server name as understood by a client, - the defaultServingCertificate will be used. - items: - description: APIServerNamedServingCert maps a server - DNS name, as understood by a client, to a certificate. - properties: - names: - description: |- - names is a optional list of explicit DNS names (leading wildcards allowed) that should use this certificate to - serve secure traffic. If no names are provided, the implicit names will be extracted from the certificates. - Exact names trump over wildcard names. Explicit names defined here trump over extracted implicit names. - items: - type: string - type: array - servingCertificate: - description: |- - servingCertificate references a kubernetes.io/tls type secret containing the TLS cert info for serving secure traffic. - The secret must exist in the openshift-config namespace and contain the following required fields: - - Secret.Data["tls.key"] - TLS private key. - - Secret.Data["tls.crt"] - TLS certificate. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - type: array - type: object - tlsSecurityProfile: - description: |- - tlsSecurityProfile specifies settings for TLS connections for externally exposed servers. - - - If unset, a default (which may change between releases) is chosen. Note that only Old, - Intermediate and Custom profiles are currently supported, and the maximum available - minTLSVersion is VersionTLS12. - properties: - custom: - description: |- - custom is a user-defined TLS security profile. Be extremely careful using a custom - profile as invalid configurations can be catastrophic. An example custom profile - looks like this: - - - ciphers: - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - minTLSVersion: VersionTLS11 - nullable: true - properties: - ciphers: - description: |- - ciphers is used to specify the cipher algorithms that are negotiated - during the TLS handshake. Operators may remove entries their operands - do not support. For example, to use DES-CBC3-SHA (yaml): - - - ciphers: - - DES-CBC3-SHA - items: - type: string - type: array - minTLSVersion: - description: |- - minTLSVersion is used to specify the minimal version of the TLS protocol - that is negotiated during the TLS handshake. For example, to use TLS - versions 1.1, 1.2 and 1.3 (yaml): - - - minTLSVersion: VersionTLS11 - - - NOTE: currently the highest minTLSVersion allowed is VersionTLS12 - enum: - - VersionTLS10 - - VersionTLS11 - - VersionTLS12 - - VersionTLS13 - type: string - type: object - intermediate: - description: |- - intermediate is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - minTLSVersion: VersionTLS12 - nullable: true - type: object - modern: - description: |- - modern is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - minTLSVersion: VersionTLS13 - nullable: true - type: object - old: - description: |- - old is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - - DHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-ECDSA-AES128-SHA256 - - - - ECDHE-RSA-AES128-SHA256 - - - - ECDHE-ECDSA-AES128-SHA - - - - ECDHE-RSA-AES128-SHA - - - - ECDHE-ECDSA-AES256-SHA384 - - - - ECDHE-RSA-AES256-SHA384 - - - - ECDHE-ECDSA-AES256-SHA - - - - ECDHE-RSA-AES256-SHA - - - - DHE-RSA-AES128-SHA256 - - - - DHE-RSA-AES256-SHA256 - - - - AES128-GCM-SHA256 - - - - AES256-GCM-SHA384 - - - - AES128-SHA256 - - - - AES256-SHA256 - - - - AES128-SHA - - - - AES256-SHA - - - - DES-CBC3-SHA - - - minTLSVersion: VersionTLS10 - nullable: true - type: object - type: - description: |- - type is one of Old, Intermediate, Modern or Custom. Custom provides - the ability to specify individual TLS security profile parameters. - Old, Intermediate and Modern are TLS security profiles based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations - - - The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers - are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be - reduced. - - - Note that the Modern profile is currently not supported because it is not - yet well adopted by common software libraries. - enum: - - Old - - Intermediate - - Modern - - Custom - type: string - type: object - type: object - authentication: - description: |- - Authentication specifies cluster-wide settings for authentication (like OAuth and - webhook token authenticators). - properties: - oauthMetadata: - description: |- - oauthMetadata contains the discovery endpoint data for OAuth 2.0 - Authorization Server Metadata for an external OAuth server. - This discovery document can be viewed from its served location: - oc get --raw '/.well-known/oauth-authorization-server' - For further details, see the IETF Draft: - https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 - If oauthMetadata.name is non-empty, this value has precedence - over any metadata reference stored in status. - The key "oauthMetadata" is used to locate the data. - If specified and the config map or expected key is not found, no metadata is served. - If the specified metadata is not valid, no metadata is served. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - oidcProviders: - description: |- - OIDCProviders are OIDC identity providers that can issue tokens - for this cluster - Can only be set if "Type" is set to "OIDC". - - - At most one provider can be configured. - items: - properties: - claimMappings: - description: |- - ClaimMappings describes rules on how to transform information from an - ID token into a cluster identity - properties: - groups: - description: |- - Groups is a name of the claim that should be used to construct - groups for the cluster identity. - The referenced claim must use array of strings values. - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - description: |- - Prefix is a string to prefix the value from the token in the result of the - claim mapping. - - - By default, no prefixing occurs. - - - Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains - an array of strings "a", "b" and "c", the mapping will result in an - array of string "myoidc:a", "myoidc:b" and "myoidc:c". - type: string - required: - - claim - type: object - username: - description: |- - Username is a name of the claim that should be used to construct - usernames for the cluster identity. - - - Default value: "sub" - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - properties: - prefixString: - minLength: 1 - type: string - required: - - prefixString - type: object - prefixPolicy: - description: |- - PrefixPolicy specifies how a prefix should apply. - - - By default, claims other than `email` will be prefixed with the issuer URL to - prevent naming clashes with other plugins. - - - Set to "NoPrefix" to disable prefixing. - - - Example: - (1) `prefix` is set to "myoidc:" and `claim` is set to "username". - If the JWT claim `username` contains value `userA`, the resulting - mapped value will be "myoidc:userA". - (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the - JWT `email` claim contains value "userA@myoidc.tld", the resulting - mapped value will be "myoidc:userA@myoidc.tld". - (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`, - the JWT claims include "username":"userA" and "email":"userA@myoidc.tld", - and `claim` is set to: - (a) "username": the mapped value will be "https://myoidc.tld#userA" - (b) "email": the mapped value will be "userA@myoidc.tld" - enum: - - "" - - NoPrefix - - Prefix - type: string - required: - - claim - type: object - x-kubernetes-validations: - - message: prefix must be set if prefixPolicy is - 'Prefix', but must remain unset otherwise - rule: 'has(self.prefixPolicy) && self.prefixPolicy - == ''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString) - > 0) : !has(self.prefix)' - type: object - claimValidationRules: - description: ClaimValidationRules are rules that are - applied to validate token claims to authenticate users. - items: - properties: - requiredClaim: - description: |- - RequiredClaim allows configuring a required claim name and its expected - value - properties: - claim: - description: |- - Claim is a name of a required claim. Only claims with string values are - supported. - minLength: 1 - type: string - requiredValue: - description: RequiredValue is the required - value for the claim. - minLength: 1 - type: string - required: - - claim - - requiredValue - type: object - type: - default: RequiredClaim - description: Type sets the type of the validation - rule - enum: - - RequiredClaim - type: string - type: object - type: array - x-kubernetes-list-type: atomic - issuer: - description: Issuer describes atributes of the OIDC - token issuer - properties: - audiences: - description: |- - Audiences is an array of audiences that the token was issued for. - Valid tokens must include at least one of these values in their - "aud" claim. - Must be set to exactly one value. - items: - minLength: 1 - type: string - maxItems: 10 - minItems: 1 - type: array - x-kubernetes-list-type: set - issuerCertificateAuthority: - description: |- - CertificateAuthority is a reference to a config map in the - configuration namespace. The .data of the configMap must contain - the "ca-bundle.crt" key. - If unset, system trust is used instead. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - issuerURL: - description: |- - URL is the serving URL of the token issuer. - Must use the https:// scheme. - pattern: ^https:\/\/[^\s] - type: string - required: - - audiences - - issuerURL - type: object - name: - description: Name of the OIDC provider - minLength: 1 - type: string - oidcClients: - description: |- - OIDCClients contains configuration for the platform's clients that - need to request tokens from the issuer - items: - properties: - clientID: - description: ClientID is the identifier of the - OIDC client from the OIDC provider - minLength: 1 - type: string - clientSecret: - description: |- - ClientSecret refers to a secret in the `openshift-config` namespace that - contains the client secret in the `clientSecret` key of the `.data` field - properties: - name: - description: name is the metadata.name of - the referenced secret - type: string - required: - - name - type: object - componentName: - description: |- - ComponentName is the name of the component that is supposed to consume this - client configuration - maxLength: 256 - minLength: 1 - type: string - componentNamespace: - description: |- - ComponentNamespace is the namespace of the component that is supposed to consume this - client configuration - maxLength: 63 - minLength: 1 - type: string - extraScopes: - description: ExtraScopes is an optional set of - scopes to request tokens with. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - clientID - - componentName - - componentNamespace - type: object - maxItems: 20 - type: array - x-kubernetes-list-map-keys: - - componentNamespace - - componentName - x-kubernetes-list-type: map - required: - - issuer - - name - type: object - maxItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceAccountIssuer: - description: |- - serviceAccountIssuer is the identifier of the bound service account token - issuer. - The default is https://kubernetes.default.svc - WARNING: Updating this field will not result in immediate invalidation of all bound tokens with the - previous issuer value. Instead, the tokens issued by previous service account issuer will continue to - be trusted for a time period chosen by the platform (currently set to 24h). - This time period is subject to change over time. - This allows internal components to transition to use new service account issuer without service distruption. - type: string - type: - description: |- - type identifies the cluster managed, user facing authentication mode in use. - Specifically, it manages the component that responds to login attempts. - The default is IntegratedOAuth. - type: string - webhookTokenAuthenticator: - description: |- - webhookTokenAuthenticator configures a remote token reviewer. - These remote authentication webhooks can be used to verify bearer tokens - via the tokenreviews.authentication.k8s.io REST API. This is required to - honor bearer tokens that are provisioned by an external authentication service. - - - Can only be set if "Type" is set to "None". - properties: - kubeConfig: - description: |- - kubeConfig references a secret that contains kube config file data which - describes how to access the remote webhook service. - The namespace for the referenced secret is openshift-config. - - - For further details, see: - - - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - - - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - kubeConfig - type: object - webhookTokenAuthenticators: - description: webhookTokenAuthenticators is DEPRECATED, setting - it has no effect. - items: - description: |- - deprecatedWebhookTokenAuthenticator holds the necessary configuration options for a remote token authenticator. - It's the same as WebhookTokenAuthenticator but it's missing the 'required' validation on KubeConfig field. - properties: - kubeConfig: - description: |- - kubeConfig contains kube config file data which describes how to access the remote webhook service. - For further details, see: - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - The namespace for this secret is determined by the point of use. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - configMapRefs: - description: |- - ConfigMapRefs holds references to any configmaps referenced by - configuration entries. Entries can reference the configmaps using local - object references. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - featureGate: - description: FeatureGate holds cluster-wide information about - feature gates. - properties: - customNoUpgrade: - description: |- - customNoUpgrade allows the enabling or disabling of any feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, and PREVENTS UPGRADES. - Because of its nature, this setting cannot be validated. If you have any typos or accidentally apply invalid combinations - your cluster may fail in an unrecoverable way. featureSet must equal "CustomNoUpgrade" must be set to use this field. - nullable: true - properties: - disabled: - description: disabled is a list of all feature gates that - you want to force off - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - enabled: - description: enabled is a list of all feature gates that - you want to force on - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - type: object - featureSet: - description: |- - featureSet changes the list of features in the cluster. The default is empty. Be very careful adjusting this setting. - Turning on or off features may cause irreversible changes in your cluster which cannot be undone. - type: string - x-kubernetes-validations: - - message: CustomNoUpgrade may not be changed - rule: 'oldSelf == ''CustomNoUpgrade'' ? self == ''CustomNoUpgrade'' - : true' - - message: TechPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''TechPreviewNoUpgrade'' ? self == ''TechPreviewNoUpgrade'' - : true' - - message: DevPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''DevPreviewNoUpgrade'' ? self == ''DevPreviewNoUpgrade'' - : true' - type: object - image: - description: |- - Image governs policies related to imagestream imports and runtime configuration - for external registries. It allows cluster admins to configure which registries - OpenShift is allowed to import images from, extra CA trust bundles for external - registries, and policies to block or allow registry hostnames. - When exposing OpenShift's image registry to the public, this also lets cluster - admins specify the external hostname. - properties: - additionalTrustedCA: - description: |- - additionalTrustedCA is a reference to a ConfigMap containing additional CAs that - should be trusted during imagestream import, pod image pull, build image pull, and - imageregistry pullthrough. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - allowedRegistriesForImport: - description: |- - allowedRegistriesForImport limits the container image registries that normal users may import - images from. Set this list to the registries that you trust to contain valid Docker - images and that you want applications to be able to import from. Users with - permission to create Images or ImageStreamMappings via the API are not affected by - this policy - typically only administrators or system integrations will have those - permissions. - items: - description: |- - RegistryLocation contains a location of the registry specified by the registry domain - name. The domain name might include wildcards, like '*' or '??'. - properties: - domainName: - description: |- - domainName specifies a domain name for the registry - In case the registry use non-standard (80 or 443) port, the port should be included - in the domain name as well. - type: string - insecure: - description: |- - insecure indicates whether the registry is secure (https) or insecure (http) - By default (if not specified) the registry is assumed as secure. - type: boolean - type: object - type: array - externalRegistryHostnames: - description: |- - externalRegistryHostnames provides the hostnames for the default external image - registry. The external hostname should be set only when the image registry - is exposed externally. The first value is used in 'publicDockerImageRepository' - field in ImageStreams. The value must be in "hostname[:port]" format. - items: - type: string - type: array - registrySources: - description: |- - registrySources contains configuration that determines how the container runtime - should treat individual registries when accessing images for builds+pods. (e.g. - whether or not to allow insecure access). It does not contain configuration for the - internal cluster registry. - properties: - allowedRegistries: - description: |- - allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - blockedRegistries: - description: |- - blockedRegistries cannot be used for image pull and push actions. All other registries are permitted. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - containerRuntimeSearchRegistries: - description: |- - containerRuntimeSearchRegistries are registries that will be searched when pulling images that do not have fully qualified - domains in their pull specs. Registries will be searched in the order provided in the list. - Note: this search list only works with the container runtime, i.e CRI-O. Will NOT work with builds or imagestream imports. - format: hostname - items: - type: string - minItems: 1 - type: array - x-kubernetes-list-type: set - insecureRegistries: - description: insecureRegistries are registries which do - not have a valid TLS certificates or only support HTTP - connections. - items: - type: string - type: array - type: object - type: object - ingress: - description: |- - Ingress holds cluster-wide information about ingress, including the default ingress domain - used for routes. - properties: - appsDomain: - description: |- - appsDomain is an optional domain to use instead of the one specified - in the domain field when a Route is created without specifying an explicit - host. If appsDomain is nonempty, this value is used to generate default - host values for Route. Unlike domain, appsDomain may be modified after - installation. - This assumes a new ingresscontroller has been setup with a wildcard - certificate. - type: string - componentRoutes: - description: |- - componentRoutes is an optional list of routes that are managed by OpenShift components - that a cluster-admin is able to configure the hostname and serving certificate for. - The namespace and name of each route in this list should match an existing entry in the - status.componentRoutes list. - - - To determine the set of configurable Routes, look at namespace and name of entries in the - .status.componentRoutes list, where participating operators write the status of - configurable routes. - items: - description: ComponentRouteSpec allows for configuration - of a route's hostname and serving certificate. - properties: - hostname: - description: hostname is the hostname that should be - used by the route. - pattern: ^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$|^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$ - type: string - name: - description: |- - name is the logical name of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 256 - minLength: 1 - type: string - namespace: - description: |- - namespace is the namespace of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - servingCertKeyPairSecret: - description: |- - servingCertKeyPairSecret is a reference to a secret of type `kubernetes.io/tls` in the openshift-config namespace. - The serving cert/key pair must match and will be used by the operator to fulfill the intent of serving with this name. - If the custom hostname uses the default routing suffix of the cluster, - the Secret specification for a serving certificate will not be needed. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - hostname - - name - - namespace - type: object - type: array - x-kubernetes-list-map-keys: - - namespace - - name - x-kubernetes-list-type: map - domain: - description: |- - domain is used to generate a default host name for a route when the - route's host name is empty. The generated host name will follow this - pattern: "..". - - - It is also used as the default wildcard domain suffix for ingress. The - default ingresscontroller domain will follow this pattern: "*.". - - - Once set, changing domain is not currently supported. - type: string - loadBalancer: - description: |- - loadBalancer contains the load balancer details in general which are not only specific to the underlying infrastructure - provider of the current cluster and are required for Ingress Controller to work on OpenShift. - properties: - platform: - description: |- - platform holds configuration specific to the underlying - infrastructure provider for the ingress load balancers. - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - properties: - aws: - description: aws contains settings specific to the - Amazon Web Services infrastructure provider. - properties: - type: - description: |- - type allows user to set a load balancer type. - When this field is set the default ingresscontroller will get created using the specified LBType. - If this field is not set then the default ingress controller of LBType Classic will be created. - Valid values are: - - - * "Classic": A Classic Load Balancer that makes routing decisions at either - the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See - the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb - - - * "NLB": A Network Load Balancer that makes routing decisions at the - transport layer (TCP/SSL). See the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb - enum: - - NLB - - Classic - type: string - required: - - type - type: object - type: - description: |- - type is the underlying infrastructure provider for the cluster. - Allowed values are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", - "OpenStack", "VSphere", "oVirt", "KubeVirt", "EquinixMetal", "PowerVS", - "AlibabaCloud", "Nutanix" and "None". Individual components may not support all platforms, - and must handle unrecognized platforms as None if they do not support that platform. - enum: - - "" - - AWS - - Azure - - BareMetal - - GCP - - Libvirt - - OpenStack - - None - - VSphere - - oVirt - - IBMCloud - - KubeVirt - - EquinixMetal - - PowerVS - - AlibabaCloud - - Nutanix - - External - type: string - type: object - type: object - requiredHSTSPolicies: - description: |- - requiredHSTSPolicies specifies HSTS policies that are required to be set on newly created or updated routes - matching the domainPattern/s and namespaceSelector/s that are specified in the policy. - Each requiredHSTSPolicy must have at least a domainPattern and a maxAge to validate a route HSTS Policy route - annotation, and affect route admission. - - - A candidate route is checked for HSTS Policies if it has the HSTS Policy route annotation: - "haproxy.router.openshift.io/hsts_header" - E.g. haproxy.router.openshift.io/hsts_header: max-age=31536000;preload;includeSubDomains - - - - For each candidate route, if it matches a requiredHSTSPolicy domainPattern and optional namespaceSelector, - then the maxAge, preloadPolicy, and includeSubdomainsPolicy must be valid to be admitted. Otherwise, the route - is rejected. - - The first match, by domainPattern and optional namespaceSelector, in the ordering of the RequiredHSTSPolicies - determines the route's admission status. - - If the candidate route doesn't match any requiredHSTSPolicy domainPattern and optional namespaceSelector, - then it may use any HSTS Policy annotation. - - - The HSTS policy configuration may be changed after routes have already been created. An update to a previously - admitted route may then fail if the updated route does not conform to the updated HSTS policy configuration. - However, changing the HSTS policy configuration will not cause a route that is already admitted to stop working. - - - Note that if there are no RequiredHSTSPolicies, any HSTS Policy annotation on the route is valid. - items: - properties: - domainPatterns: - description: |- - domainPatterns is a list of domains for which the desired HSTS annotations are required. - If domainPatterns is specified and a route is created with a spec.host matching one of the domains, - the route must specify the HSTS Policy components described in the matching RequiredHSTSPolicy. - - - The use of wildcards is allowed like this: *.foo.com matches everything under foo.com. - foo.com only matches foo.com, so to cover foo.com and everything under it, you must specify *both*. - items: - type: string - minItems: 1 - type: array - includeSubDomainsPolicy: - description: |- - includeSubDomainsPolicy means the HSTS Policy should apply to any subdomains of the host's - domain name. Thus, for the host bar.foo.com, if includeSubDomainsPolicy was set to RequireIncludeSubDomains: - - the host app.bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host foo.com would NOT inherit the HSTS Policy of bar.foo.com - - the host def.foo.com would NOT inherit the HSTS Policy of bar.foo.com - enum: - - RequireIncludeSubDomains - - RequireNoIncludeSubDomains - - NoOpinion - type: string - maxAge: - description: |- - maxAge is the delta time range in seconds during which hosts are regarded as HSTS hosts. - If set to 0, it negates the effect, and hosts are removed as HSTS hosts. - If set to 0 and includeSubdomains is specified, all subdomains of the host are also removed as HSTS hosts. - maxAge is a time-to-live value, and if this policy is not refreshed on a client, the HSTS - policy will eventually expire on that client. - properties: - largestMaxAge: - description: |- - The largest allowed value (in seconds) of the RequiredHSTSPolicy max-age - This value can be left unspecified, in which case no upper limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - smallestMaxAge: - description: |- - The smallest allowed value (in seconds) of the RequiredHSTSPolicy max-age - Setting max-age=0 allows the deletion of an existing HSTS header from a host. This is a necessary - tool for administrators to quickly correct mistakes. - This value can be left unspecified, in which case no lower limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - type: object - namespaceSelector: - description: |- - namespaceSelector specifies a label selector such that the policy applies only to those routes that - are in namespaces with labels that match the selector, and are in one of the DomainPatterns. - Defaults to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - preloadPolicy: - description: |- - preloadPolicy directs the client to include hosts in its host preload list so that - it never needs to do an initial load to get the HSTS header (note that this is not defined - in RFC 6797 and is therefore client implementation-dependent). - enum: - - RequirePreload - - RequireNoPreload - - NoOpinion - type: string - required: - - domainPatterns - type: object - type: array - type: object - items: - description: |- - Items embeds the serialized configuration resources. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - type: object - x-kubernetes-preserve-unknown-fields: true - type: array - x-kubernetes-preserve-unknown-fields: true - network: - description: |- - Network holds cluster-wide information about the network. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. - Please view network.spec for an explanation on what applies when configuring this resource. - TODO (csrwng): Add validation here to exclude changes that conflict with networking settings in the HostedCluster.Spec.Networking field. - properties: - clusterNetwork: - description: |- - IP address pool to use for pod IPs. - This field is immutable after installation. - items: - description: |- - ClusterNetworkEntry is a contiguous block of IP addresses from which pod IPs - are allocated. - properties: - cidr: - description: The complete block for pod IPs. - type: string - hostPrefix: - description: |- - The size (prefix) of block to allocate to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - minimum: 0 - type: integer - type: object - type: array - x-kubernetes-list-type: atomic - externalIP: - description: |- - externalIP defines configuration for controllers that - affect Service.ExternalIP. If nil, then ExternalIP is - not allowed to be set. - properties: - autoAssignCIDRs: - description: |- - autoAssignCIDRs is a list of CIDRs from which to automatically assign - Service.ExternalIP. These are assigned when the service is of type - LoadBalancer. In general, this is only useful for bare-metal clusters. - In Openshift 3.x, this was misleadingly called "IngressIPs". - Automatically assigned External IPs are not affected by any - ExternalIPPolicy rules. - Currently, only one entry may be provided. - items: - type: string - type: array - x-kubernetes-list-type: atomic - policy: - description: |- - policy is a set of restrictions applied to the ExternalIP field. - If nil or empty, then ExternalIP is not allowed to be set. - properties: - allowedCIDRs: - description: allowedCIDRs is the list of allowed CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - rejectedCIDRs: - description: |- - rejectedCIDRs is the list of disallowed CIDRs. These take precedence - over allowedCIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkDiagnostics: - description: |- - networkDiagnostics defines network diagnostics configuration. - - - Takes precedence over spec.disableNetworkDiagnostics in network.operator.openshift.io. - If networkDiagnostics is not specified or is empty, - and the spec.disableNetworkDiagnostics flag in network.operator.openshift.io is set to true, - the network diagnostics feature will be disabled. - properties: - mode: - description: |- - mode controls the network diagnostics mode - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is All. - enum: - - "" - - All - - Disabled - type: string - sourcePlacement: - description: |- - sourcePlacement controls the scheduling of network diagnostics source deployment - - - See NetworkDiagnosticsSourcePlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is an empty list. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - targetPlacement: - description: |- - targetPlacement controls the scheduling of network diagnostics target daemonset - - - See NetworkDiagnosticsTargetPlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `- operator: "Exists"` which means that all taints are tolerated. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkType: - description: |- - NetworkType is the plugin that is to be deployed (e.g. OpenShiftSDN). - This should match a value that the cluster-network-operator understands, - or else no networking will be installed. - Currently supported values are: - - OpenShiftSDN - This field is immutable after installation. - type: string - serviceNetwork: - description: |- - IP address pool for services. - Currently, we only support a single entry here. - This field is immutable after installation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - serviceNodePortRange: - description: |- - The port range allowed for Services of type NodePort. - If not specified, the default of 30000-32767 will be used. - Such Services without a NodePort specified will have one - automatically allocated from this range. - This parameter can be updated after the cluster is - installed. - pattern: ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])-([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ - type: string - type: object - oauth: - description: |- - OAuth holds cluster-wide information about OAuth. - It is used to configure the integrated OAuth server. - This configuration is only honored when the top level Authentication config has type set to IntegratedOAuth. - properties: - identityProviders: - description: |- - identityProviders is an ordered list of ways for a user to identify themselves. - When this list is empty, no identities are provisioned for users. - items: - description: IdentityProvider provides identities for users - authenticating using credentials - properties: - basicAuth: - description: basicAuth contains configuration options - for the BasicAuth IdP - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - github: - description: github enables user authentication using - GitHub credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - This can only be configured when hostname is set to a non-empty value. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostname: - description: |- - hostname is the optional domain (e.g. "mycompany.com") for use with a hosted instance of - GitHub Enterprise. - It must match the GitHub Enterprise settings value configured at /setup/settings#hostname. - type: string - organizations: - description: organizations optionally restricts - which organizations are allowed to log in - items: - type: string - type: array - teams: - description: teams optionally restricts which teams - are allowed to log in. Format is /. - items: - type: string - type: array - type: object - gitlab: - description: gitlab enables user authentication using - GitLab credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the oauth server base URL - type: string - type: object - google: - description: google enables user authentication using - Google credentials - properties: - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostedDomain: - description: hostedDomain is the optional Google - App domain (e.g. "mycompany.com") to restrict - logins to - type: string - type: object - htpasswd: - description: htpasswd enables user authentication using - an HTPasswd file to validate credentials - properties: - fileData: - description: |- - fileData is a required reference to a secret by name containing the data to use as the htpasswd file. - The key "htpasswd" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - If the specified htpasswd data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - keystone: - description: keystone enables user authentication using - keystone password credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - domainName: - description: domainName is required for keystone - v3 - type: string - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - ldap: - description: ldap enables user authentication using - LDAP credentials - properties: - attributes: - description: attributes maps LDAP attributes to - identities - properties: - email: - description: |- - email is the list of attributes whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - id: - description: |- - id is the list of attributes whose values should be used as the user ID. Required. - First non-empty attribute is used. At least one attribute is required. If none of the listed - attribute have a value, authentication fails. - LDAP standard identity attribute is "dn" - items: - type: string - type: array - name: - description: |- - name is the list of attributes whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - LDAP standard display name attribute is "cn" - items: - type: string - type: array - preferredUsername: - description: |- - preferredUsername is the list of attributes whose values should be used as the preferred username. - LDAP standard login attribute is "uid" - items: - type: string - type: array - type: object - bindDN: - description: bindDN is an optional DN to bind with - during the search phase. - type: string - bindPassword: - description: |- - bindPassword is an optional reference to a secret by name - containing a password to bind with during the search phase. - The key "bindPassword" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - insecure: - description: |- - insecure, if true, indicates the connection should not use TLS - WARNING: Should not be set to `true` with the URL scheme "ldaps://" as "ldaps://" URLs always - attempt to connect using TLS, even when `insecure` is set to `true` - When `true`, "ldap://" URLS connect insecurely. When `false`, "ldap://" URLs are upgraded to - a TLS connection using StartTLS as specified in https://tools.ietf.org/html/rfc2830. - type: boolean - url: - description: |- - url is an RFC 2255 URL which specifies the LDAP search parameters to use. - The syntax of the URL is: - ldap://host:port/basedn?attribute?scope?filter - type: string - type: object - mappingMethod: - description: |- - mappingMethod determines how identities from this provider are mapped to users - Defaults to "claim" - type: string - name: - description: |- - name is used to qualify the identities returned by this provider. - - It MUST be unique and not shared by any other identity provider used - - It MUST be a valid path segment: name cannot equal "." or ".." or contain "/" or "%" or ":" - Ref: https://godoc.org/github.com/openshift/origin/pkg/user/apis/user/validation#ValidateIdentityProviderName - type: string - openID: - description: openID enables user authentication using - OpenID credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - claims: - description: claims mappings - properties: - email: - description: |- - email is the list of claims whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - groups: - description: |- - groups is the list of claims value of which should be used to synchronize groups - from the OIDC provider to OpenShift for the user. - If multiple claims are specified, the first one with a non-empty value is used. - items: - description: |- - OpenIDClaim represents a claim retrieved from an OpenID provider's tokens or userInfo - responses - minLength: 1 - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: |- - name is the list of claims whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - preferredUsername: - description: |- - preferredUsername is the list of claims whose values should be used as the preferred username. - If unspecified, the preferred username is determined from the value of the sub claim - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - extraAuthorizeParameters: - additionalProperties: - type: string - description: extraAuthorizeParameters are any custom - parameters to add to the authorize request. - type: object - extraScopes: - description: extraScopes are any scopes to request - in addition to the standard "openid" scope. - items: - type: string - type: array - issuer: - description: |- - issuer is the URL that the OpenID Provider asserts as its Issuer Identifier. - It must use the https scheme with no query or fragment component. - type: string - type: object - requestHeader: - description: requestHeader enables user authentication - using request header credentials - properties: - ca: - description: |- - ca is a required reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - Specifically, it allows verification of incoming requests to prevent header spoofing. - The key "ca.crt" is used to locate the data. - If the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - challengeURL: - description: |- - challengeURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect WWW-Authenticate challenges will be - redirected here. - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when challenge is set to true. - type: string - clientCommonNames: - description: |- - clientCommonNames is an optional list of common names to require a match from. If empty, any - client certificate validated against the clientCA bundle is considered authoritative. - items: - type: string - type: array - emailHeaders: - description: emailHeaders is the set of headers - to check for the email address - items: - type: string - type: array - headers: - description: headers is the set of headers to check - for identity information - items: - type: string - type: array - loginURL: - description: |- - loginURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect interactive logins will be redirected here - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when login is set to true. - type: string - nameHeaders: - description: nameHeaders is the set of headers to - check for the display name - items: - type: string - type: array - preferredUsernameHeaders: - description: preferredUsernameHeaders is the set - of headers to check for the preferred username - items: - type: string - type: array - type: object - type: - description: type identifies the identity provider type - for this entry. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - templates: - description: templates allow you to customize pages like the - login page. - properties: - error: - description: |- - error is the name of a secret that specifies a go template to use to render error pages - during the authentication or grant flow. - The key "errors.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default error page is used. - If the specified template is not valid, the default error page is used. - If unspecified, the default error page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - login: - description: |- - login is the name of a secret that specifies a go template to use to render the login page. - The key "login.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default login page is used. - If the specified template is not valid, the default login page is used. - If unspecified, the default login page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - providerSelection: - description: |- - providerSelection is the name of a secret that specifies a go template to use to render - the provider selection page. - The key "providers.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default provider selection page is used. - If the specified template is not valid, the default provider selection page is used. - If unspecified, the default provider selection page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - tokenConfig: - description: tokenConfig contains options for authorization - and access tokens - properties: - accessTokenInactivityTimeout: - description: |- - accessTokenInactivityTimeout defines the token inactivity timeout - for tokens granted by any client. - The value represents the maximum amount of time that can occur between - consecutive uses of the token. Tokens become invalid if they are not - used within this temporal window. The user will need to acquire a new - token to regain access once a token times out. Takes valid time - duration string such as "5m", "1.5h" or "2h45m". The minimum allowed - value for duration is 300s (5 minutes). If the timeout is configured - per client, then that value takes precedence. If the timeout value is - not specified and the client does not override the value, then tokens - are valid until their lifetime. - - - WARNING: existing tokens' timeout will not be affected (lowered) by changing this value - type: string - accessTokenInactivityTimeoutSeconds: - description: 'accessTokenInactivityTimeoutSeconds - DEPRECATED: - setting this field has no effect.' - format: int32 - type: integer - accessTokenMaxAgeSeconds: - description: accessTokenMaxAgeSeconds defines the maximum - age of access tokens - format: int32 - type: integer - type: object - type: object - operatorhub: - description: |- - OperatorHub specifies the configuration for the Operator Lifecycle Manager in the HostedCluster. This is only configured at deployment time but the controller are not reconcilling over it. - The OperatorHub configuration will be constantly reconciled if catalog placement is management, but only on cluster creation otherwise. - properties: - disableAllDefaultSources: - description: |- - disableAllDefaultSources allows you to disable all the default hub - sources. If this is true, a specific entry in sources can be used to - enable a default source. If this is false, a specific entry in - sources can be used to disable or enable a default source. - type: boolean - sources: - description: |- - sources is the list of default hub sources and their configuration. - If the list is empty, it implies that the default hub sources are - enabled on the cluster unless disableAllDefaultSources is true. - If disableAllDefaultSources is true and sources is not empty, - the configuration present in sources will take precedence. The list of - default hub sources and their current state will always be reflected in - the status block. - items: - description: HubSource is used to specify the hub source - and its configuration - properties: - disabled: - description: disabled is used to disable a default hub - source on cluster - type: boolean - name: - description: name is the name of one of the default - hub sources - maxLength: 253 - minLength: 1 - type: string - type: object - type: array - type: object - proxy: - description: Proxy holds cluster-wide information on how to configure - default proxies for the cluster. - properties: - httpProxy: - description: httpProxy is the URL of the proxy for HTTP requests. Empty - means unset and will not result in an env var. - type: string - httpsProxy: - description: httpsProxy is the URL of the proxy for HTTPS - requests. Empty means unset and will not result in an env - var. - type: string - noProxy: - description: |- - noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. - Empty means unset and will not result in an env var. - type: string - readinessEndpoints: - description: readinessEndpoints is a list of endpoints used - to verify readiness of the proxy. - items: - type: string - type: array - trustedCA: - description: |- - trustedCA is a reference to a ConfigMap containing a CA certificate bundle. - The trustedCA field should only be consumed by a proxy validator. The - validator is responsible for reading the certificate bundle from the required - key "ca-bundle.crt", merging it with the system default trust bundle, - and writing the merged trust bundle to a ConfigMap named "trusted-ca-bundle" - in the "openshift-config-managed" namespace. Clients that expect to make - proxy connections must use the trusted-ca-bundle for all HTTPS requests to - the proxy, and may use the trusted-ca-bundle for non-proxy HTTPS requests as - well. - - - The namespace for the ConfigMap referenced by trustedCA is - "openshift-config". Here is an example ConfigMap (in yaml): - - - apiVersion: v1 - kind: ConfigMap - metadata: - name: user-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - Custom CA certificate bundle. - -----END CERTIFICATE----- - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - type: object - scheduler: - description: |- - Scheduler holds cluster-wide config information to run the Kubernetes Scheduler - and influence its placement decisions. The canonical name for this config is `cluster`. - properties: - defaultNodeSelector: - description: |- - defaultNodeSelector helps set the cluster-wide default node selector to - restrict pod placement to specific nodes. This is applied to the pods - created in all namespaces and creates an intersection with any existing - nodeSelectors already set on a pod, additionally constraining that pod's selector. - For example, - defaultNodeSelector: "type=user-node,region=east" would set nodeSelector - field in pod spec to "type=user-node,region=east" to all pods created - in all namespaces. Namespaces having project-wide node selectors won't be - impacted even if this field is set. This adds an annotation section to - the namespace. - For example, if a new namespace is created with - node-selector='type=user-node,region=east', - the annotation openshift.io/node-selector: type=user-node,region=east - gets added to the project. When the openshift.io/node-selector annotation - is set on the project the value is used in preference to the value we are setting - for defaultNodeSelector field. - For instance, - openshift.io/node-selector: "type=user-node,region=west" means - that the default of "type=user-node,region=east" set in defaultNodeSelector - would not be applied. - type: string - mastersSchedulable: - description: |- - MastersSchedulable allows masters nodes to be schedulable. When this flag is - turned on, all the master nodes in the cluster will be made schedulable, - so that workload pods can run on them. The default value for this field is false, - meaning none of the master nodes are schedulable. - Important Note: Once the workload pods start running on the master nodes, - extreme care must be taken to ensure that cluster-critical control plane components - are not impacted. - Please turn on this field after doing due diligence. - type: boolean - policy: - description: |- - DEPRECATED: the scheduler Policy API has been deprecated and will be removed in a future release. - policy is a reference to a ConfigMap containing scheduler policy which has - user specified predicates and priorities. If this ConfigMap is not available - scheduler will default to use DefaultAlgorithmProvider. - The namespace for this configmap is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - profile: - description: |- - profile sets which scheduling profile should be set in order to configure scheduling - decisions for new pods. - - - Valid values are "LowNodeUtilization", "HighNodeUtilization", "NoScoring" - Defaults to "LowNodeUtilization" - enum: - - "" - - LowNodeUtilization - - HighNodeUtilization - - NoScoring - type: string - profileCustomizations: - description: profileCustomizations contains configuration - for modifying the default behavior of existing scheduler - profiles. - properties: - dynamicResourceAllocation: - description: |- - dynamicResourceAllocation allows to enable or disable dynamic resource allocation within the scheduler. - Dynamic resource allocation is an API for requesting and sharing resources between pods and containers inside a pod. - Third-party resource drivers are responsible for tracking and allocating resources. - Different kinds of resources support arbitrary parameters for defining requirements and initialization. - Valid values are Enabled, Disabled and omitted. - When omitted, this means no opinion and the platform is left to choose a reasonable default, - which is subject to change over time. - The current default is Disabled. - enum: - - "" - - Enabled - - Disabled - type: string - type: object - type: object - secretRefs: - description: |- - SecretRefs holds references to any secrets referenced by configuration - entries. Entries can reference the secrets using local object references. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - type: object - controlPlaneRelease: - description: |- - ControlPlaneRelease specifies the desired OCP release payload for - control plane components running on the management cluster. - Updating this field will trigger a rollout of the control plane. The - behavior of the rollout will be driven by the ControllerAvailabilityPolicy - and InfrastructureAvailabilityPolicy. - If not defined, Release is used - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - controllerAvailabilityPolicy: - default: HighlyAvailable - description: |- - ControllerAvailabilityPolicy specifies the availability policy applied to - critical control plane components. The default value is HighlyAvailable. - type: string - dns: - description: DNS specifies DNS configuration for the cluster. - properties: - baseDomain: - description: BaseDomain is the base domain of the cluster. - type: string - baseDomainPrefix: - description: |- - BaseDomainPrefix is the base domain prefix of the cluster. - defaults to clusterName if not set - type: string - privateZoneID: - description: |- - PrivateZoneID is the Hosted Zone ID where all the DNS records that are only - available internally to the cluster exist. - type: string - publicZoneID: - description: |- - PublicZoneID is the Hosted Zone ID where all the DNS records that are - publicly accessible to the internet exist. - type: string - required: - - baseDomain - type: object - etcd: - default: - managed: - storage: - persistentVolume: - size: 4Gi - type: PersistentVolume - managementType: Managed - description: |- - Etcd specifies configuration for the control plane etcd cluster. The - default ManagementType is Managed. Once set, the ManagementType cannot be - changed. - properties: - managed: - description: Managed specifies the behavior of an etcd cluster - managed by HyperShift. - properties: - storage: - description: Storage specifies how etcd data is persisted. - properties: - persistentVolume: - description: |- - PersistentVolume is the configuration for PersistentVolume etcd storage. - With this implementation, a PersistentVolume will be allocated for every - etcd member (either 1 or 3 depending on the HostedCluster control plane - availability configuration). - properties: - size: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Size is the minimum size of the data - volume for each etcd member. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: Etcd PV storage size is immutable - rule: self == oldSelf - storageClassName: - description: |- - StorageClassName is the StorageClass of the data volume for each etcd member. - - - See https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. - type: string - type: object - restoreSnapshotURL: - description: |- - RestoreSnapshotURL allows an optional URL to be provided where - an etcd snapshot can be downloaded, for example a pre-signed URL - referencing a storage service. - This snapshot will be restored on initial startup, only when the etcd PV - is empty. - items: - type: string - type: array - x-kubernetes-validations: - - message: RestoreSnapshotURL shouldn't contain more than - 1 entry - rule: self.size() <= 1 - type: - description: Type is the kind of persistent storage implementation - to use for etcd. - enum: - - PersistentVolume - type: string - required: - - type - type: object - required: - - storage - type: object - managementType: - description: ManagementType defines how the etcd cluster is managed. - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: |- - Unmanaged specifies configuration which enables the control plane to - integrate with an eternally managed etcd cluster. - properties: - endpoint: - description: |- - Endpoint is the full etcd cluster client endpoint URL. For example: - - - https://etcd-client:2379 - - - If the URL uses an HTTPS scheme, the TLS field is required. - pattern: ^https:// - type: string - tls: - description: TLS specifies TLS configuration for HTTPS etcd - client endpoints. - properties: - clientSecret: - description: |- - ClientSecret refers to a secret for client mTLS authentication with the etcd cluster. It - may have the following key/value pairs: - - - etcd-client-ca.crt: Certificate Authority value - etcd-client.crt: Client certificate value - etcd-client.key: Client certificate key value - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - clientSecret - type: object - required: - - endpoint - - tls - type: object - required: - - managementType - type: object - fips: - description: |- - FIPS indicates whether this cluster's nodes will be running in FIPS mode. - If set to true, the control plane's ignition server will be configured to - expect that nodes joining the cluster will be FIPS-enabled. - type: boolean - imageContentSources: - description: |- - ImageContentSources specifies image mirrors that can be used by cluster - nodes to pull content. - items: - description: |- - ImageContentSource specifies image mirrors that can be used by cluster nodes - to pull content. For cluster workloads, if a container image registry host of - the pullspec matches Source then one of the Mirrors are substituted as hosts - in the pullspec and tried in order to fetch the image. - properties: - mirrors: - description: Mirrors are one or more repositories that may also - contain the same images. - items: - type: string - type: array - source: - description: |- - Source is the repository that users refer to, e.g. in image pull - specifications. - type: string - required: - - source - type: object - type: array - infraID: - description: |- - InfraID is a globally unique identifier for the cluster. This identifier - will be used to associate various cloud resources with the HostedCluster - and its associated NodePools. - type: string - infrastructureAvailabilityPolicy: - default: SingleReplica - description: |- - InfrastructureAvailabilityPolicy specifies the availability policy applied - to infrastructure services which run on cluster nodes. The default value is - SingleReplica. - type: string - issuerURL: - default: https://kubernetes.default.svc - description: |- - IssuerURL is an OIDC issuer URL which is used as the issuer in all - ServiceAccount tokens generated by the control plane API server. The - default value is kubernetes.default.svc, which only works for in-cluster - validation. - format: uri - type: string - networking: - default: - clusterNetwork: - - cidr: 10.132.0.0/14 - networkType: OVNKubernetes - serviceNetwork: - - cidr: 172.31.0.0/16 - description: Networking specifies network configuration for the cluster. - properties: - apiServer: - description: |- - APIServer contains advanced network settings for the API server that affect - how the APIServer is exposed inside a cluster node. - properties: - advertiseAddress: - description: |- - AdvertiseAddress is the address that nodes will use to talk to the API - server. This is an address associated with the loopback adapter of each - node. If not specified, 172.20.0.1 is used. - type: string - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is an allow list of CIDR blocks that can access the APIServer - If not specified, traffic is allowed from all addresses. - This depends on underlying support by the cloud provider for Service LoadBalancerSourceRanges - items: - pattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$ - type: string - type: array - port: - description: |- - Port is the port at which the APIServer is exposed inside a node. Other - pods using host networking cannot listen on this port. If not specified, - 6443 is used. - format: int32 - type: integer - type: object - clusterNetwork: - default: - - cidr: 10.132.0.0/14 - description: |- - ClusterNetwork is the list of IP address pools for pods. - TODO: make this required in the next version of the API - items: - description: |- - ClusterNetworkEntry is a single IP address block for pod IP blocks. IP blocks - are allocated with size 2^HostSubnetLength. - properties: - cidr: - description: CIDR is the IP block address pool. - type: string - hostPrefix: - description: |- - HostPrefix is the prefix size to allocate to each node from the CIDR. - For example, 24 would allocate 2^8=256 adresses to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - type: integer - required: - - cidr - type: object - type: array - machineCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use MachineNetwork instead - format: cidr - type: string - machineNetwork: - description: |- - MachineNetwork is the list of IP address pools for machines. - TODO: make this required in the next version of the API - items: - description: MachineNetworkEntry is a single IP address block - for node IP blocks. - properties: - cidr: - description: CIDR is the IP block address pool for machines - within the cluster. - type: string - required: - - cidr - type: object - type: array - networkType: - default: OVNKubernetes - description: NetworkType specifies the SDN provider used for cluster - networking. - enum: - - OpenShiftSDN - - Calico - - OVNKubernetes - - Other - type: string - podCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use ClusterNetwork instead - format: cidr - type: string - serviceCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use ServiceNetwork instead - format: cidr - type: string - serviceNetwork: - default: - - cidr: 172.31.0.0/16 - description: |- - ServiceNetwork is the list of IP address pools for services. - NOTE: currently only one entry is supported. - TODO: make this required in the next version of the API - items: - description: ServiceNetworkEntry is a single IP address block - for the service network. - properties: - cidr: - description: CIDR is the IP block address pool for services - within the cluster. - type: string - required: - - cidr - type: object - type: array - required: - - networkType - type: object - nodeSelector: - additionalProperties: - type: string - description: NodeSelector when specified, must be true for the pods - managed by the HostedCluster to be scheduled. - type: object - olmCatalogPlacement: - default: management - description: |- - OLMCatalogPlacement specifies the placement of OLM catalog components. By default, - this is set to management and OLM catalog components are deployed onto the management - cluster. If set to guest, the OLM catalog components will be deployed onto the guest - cluster. - enum: - - management - - guest - type: string - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - Platform specifies the underlying infrastructure provider for the cluster - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies configuration for agent-based installations. - properties: - agentNamespace: - description: AgentNamespace is the namespace where to search - for Agents for this cluster - type: string - required: - - agentNamespace - type: object - aws: - description: AWS specifies configuration for clusters running - on Amazon Web Services. - properties: - additionalAllowedPrincipals: - description: |- - AdditionalAllowedPrincipals specifies a list of additional allowed principal ARNs - to be added to the hosted control plane's VPC Endpoint Service to enable additional - VPC Endpoint connection requests to be automatically accepted. - See https://docs.aws.amazon.com/vpc/latest/privatelink/configure-endpoint-service.html - for more details around VPC Endpoint Service allowed principals. - items: - type: string - type: array - cloudProviderConfig: - description: |- - CloudProviderConfig specifies AWS networking configuration for the control - plane. - This is mainly used for cloud provider controller config: - https://github.com/kubernetes/kubernetes/blob/f5be5052e3d0808abb904aebd3218fe4a5c2dd82/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L1347-L1364 - TODO(dan): should this be named AWSNetworkConfig? - properties: - subnet: - description: Subnet is the subnet to use for control plane - cloud resources. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify - an AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - vpc: - description: VPC is the VPC to use for control plane cloud - resources. - type: string - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - type: string - required: - - vpc - type: object - controlPlaneOperatorCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - endpointAccess: - default: Public - description: |- - EndpointAccess specifies the publishing scope of cluster endpoints. The - default is Public. - enum: - - Public - - PublicAndPrivate - - Private - type: string - kubeCloudControllerCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - multiArch: - default: false - description: |- - MultiArch specifies whether the Hosted Cluster will be expected to support NodePools with different - CPU architectures, i.e., supporting arm64 NodePools and supporting amd64 NodePools on the same Hosted Cluster. - type: boolean - nodePoolManagementCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the AWS region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot AMI for a given release. - type: string - resourceTags: - description: |- - ResourceTags is a list of additional tags to apply to AWS resources created - for the cluster. See - https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - roles: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - items: - properties: - arn: - type: string - name: - type: string - namespace: - type: string - required: - - arn - - name - - namespace - type: object - type: array - rolesRef: - description: |- - RolesRef contains references to various AWS IAM roles required to enable - integrations such as OIDC. - properties: - controlPlaneOperatorARN: - description: "ControlPlaneOperatorARN is an ARN value - referencing a role appropriate for the Control Plane - Operator.\n\n\nThe following is an example of a valid - policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"ec2:CreateVpcEndpoint\",\n\t\t\t\t\"ec2:DescribeVpcEndpoints\",\n\t\t\t\t\"ec2:ModifyVpcEndpoint\",\n\t\t\t\t\"ec2:DeleteVpcEndpoints\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\",\n\t\t\t\t\"route53:ListResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - \"arn:aws:route53:::%s\"\n\t\t}\n\t]\n}" - type: string - imageRegistryARN: - description: "ImageRegistryARN is an ARN value referencing - a role appropriate for the Image Registry Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"s3:CreateBucket\",\n\t\t\t\t\"s3:DeleteBucket\",\n\t\t\t\t\"s3:PutBucketTagging\",\n\t\t\t\t\"s3:GetBucketTagging\",\n\t\t\t\t\"s3:PutBucketPublicAccessBlock\",\n\t\t\t\t\"s3:GetBucketPublicAccessBlock\",\n\t\t\t\t\"s3:PutEncryptionConfiguration\",\n\t\t\t\t\"s3:GetEncryptionConfiguration\",\n\t\t\t\t\"s3:PutLifecycleConfiguration\",\n\t\t\t\t\"s3:GetLifecycleConfiguration\",\n\t\t\t\t\"s3:GetBucketLocation\",\n\t\t\t\t\"s3:ListBucket\",\n\t\t\t\t\"s3:GetObject\",\n\t\t\t\t\"s3:PutObject\",\n\t\t\t\t\"s3:DeleteObject\",\n\t\t\t\t\"s3:ListBucketMultipartUploads\",\n\t\t\t\t\"s3:AbortMultipartUpload\",\n\t\t\t\t\"s3:ListMultipartUploadParts\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - ingressARN: - description: "The referenced role must have a trust relationship - that allows it to be assumed via web identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ .ProviderName - }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nIngressARN - is an ARN value referencing a role appropriate for the - Ingress Operator.\n\n\nThe following is an example of - a valid policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"elasticloadbalancing:DescribeLoadBalancers\",\n\t\t\t\t\"tag:GetResources\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - [\n\t\t\t\t\"arn:aws:route53:::PUBLIC_ZONE_ID\",\n\t\t\t\t\"arn:aws:route53:::PRIVATE_ZONE_ID\"\n\t\t\t]\n\t\t}\n\t]\n}" - type: string - kubeCloudControllerARN: - description: |- - KubeCloudControllerARN is an ARN value referencing a role appropriate for the KCM/KCC. - - - The following is an example of a valid policy document: - - - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeImages", - "ec2:DescribeRegions", - "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVolumes", - "ec2:CreateSecurityGroup", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:ModifyInstanceAttribute", - "ec2:ModifyVolume", - "ec2:AttachVolume", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateRoute", - "ec2:DeleteRoute", - "ec2:DeleteSecurityGroup", - "ec2:DeleteVolume", - "ec2:DetachVolume", - "ec2:RevokeSecurityGroupIngress", - "ec2:DescribeVpcs", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:AttachLoadBalancerToSubnets", - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", - "elasticloadbalancing:CreateLoadBalancer", - "elasticloadbalancing:CreateLoadBalancerPolicy", - "elasticloadbalancing:CreateLoadBalancerListeners", - "elasticloadbalancing:ConfigureHealthCheck", - "elasticloadbalancing:DeleteLoadBalancer", - "elasticloadbalancing:DeleteLoadBalancerListeners", - "elasticloadbalancing:DescribeLoadBalancers", - "elasticloadbalancing:DescribeLoadBalancerAttributes", - "elasticloadbalancing:DetachLoadBalancerFromSubnets", - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:ModifyLoadBalancerAttributes", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:CreateListener", - "elasticloadbalancing:CreateTargetGroup", - "elasticloadbalancing:DeleteListener", - "elasticloadbalancing:DeleteTargetGroup", - "elasticloadbalancing:DescribeListeners", - "elasticloadbalancing:DescribeLoadBalancerPolicies", - "elasticloadbalancing:DescribeTargetGroups", - "elasticloadbalancing:DescribeTargetHealth", - "elasticloadbalancing:ModifyListener", - "elasticloadbalancing:ModifyTargetGroup", - "elasticloadbalancing:RegisterTargets", - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener", - "iam:CreateServiceLinkedRole", - "kms:DescribeKey" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ] - } - type: string - networkARN: - description: "NetworkARN is an ARN value referencing a - role appropriate for the Network Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInstanceStatus\",\n \"ec2:DescribeInstanceTypes\",\n - \ \"ec2:UnassignPrivateIpAddresses\",\n \"ec2:AssignPrivateIpAddresses\",\n - \ \"ec2:UnassignIpv6Addresses\",\n \"ec2:AssignIpv6Addresses\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeNetworkInterfaces\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - nodePoolManagementARN: - description: "NodePoolManagementARN is an ARN value referencing - a role appropriate for the CAPI Controller.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n - \ \"Version\": \"2012-10-17\",\n \"Statement\": [\n - \ {\n \"Action\": [\n \"ec2:AllocateAddress\",\n - \ \"ec2:AssociateRouteTable\",\n \"ec2:AttachInternetGateway\",\n - \ \"ec2:AuthorizeSecurityGroupIngress\",\n \"ec2:CreateInternetGateway\",\n - \ \"ec2:CreateNatGateway\",\n \"ec2:CreateRoute\",\n - \ \"ec2:CreateRouteTable\",\n \"ec2:CreateSecurityGroup\",\n - \ \"ec2:CreateSubnet\",\n \"ec2:CreateTags\",\n - \ \"ec2:DeleteInternetGateway\",\n \"ec2:DeleteNatGateway\",\n - \ \"ec2:DeleteRouteTable\",\n \"ec2:DeleteSecurityGroup\",\n - \ \"ec2:DeleteSubnet\",\n \"ec2:DeleteTags\",\n - \ \"ec2:DescribeAccountAttributes\",\n \"ec2:DescribeAddresses\",\n - \ \"ec2:DescribeAvailabilityZones\",\n \"ec2:DescribeImages\",\n - \ \"ec2:DescribeInstances\",\n \"ec2:DescribeInternetGateways\",\n - \ \"ec2:DescribeNatGateways\",\n \"ec2:DescribeNetworkInterfaces\",\n - \ \"ec2:DescribeNetworkInterfaceAttribute\",\n - \ \"ec2:DescribeRouteTables\",\n \"ec2:DescribeSecurityGroups\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeVpcs\",\n - \ \"ec2:DescribeVpcAttribute\",\n \"ec2:DescribeVolumes\",\n - \ \"ec2:DetachInternetGateway\",\n \"ec2:DisassociateRouteTable\",\n - \ \"ec2:DisassociateAddress\",\n \"ec2:ModifyInstanceAttribute\",\n - \ \"ec2:ModifyNetworkInterfaceAttribute\",\n \"ec2:ModifySubnetAttribute\",\n - \ \"ec2:ReleaseAddress\",\n \"ec2:RevokeSecurityGroupIngress\",\n - \ \"ec2:RunInstances\",\n \"ec2:TerminateInstances\",\n - \ \"tag:GetResources\",\n \"ec2:CreateLaunchTemplate\",\n - \ \"ec2:CreateLaunchTemplateVersion\",\n \"ec2:DescribeLaunchTemplates\",\n - \ \"ec2:DescribeLaunchTemplateVersions\",\n \"ec2:DeleteLaunchTemplate\",\n - \ \"ec2:DeleteLaunchTemplateVersions\"\n ],\n - \ \"Resource\": [\n \"*\"\n ],\n \"Effect\": - \"Allow\"\n },\n {\n \"Condition\": {\n \"StringLike\": - {\n \"iam:AWSServiceName\": \"elasticloadbalancing.amazonaws.com\"\n - \ }\n },\n \"Action\": [\n \"iam:CreateServiceLinkedRole\"\n - \ ],\n \"Resource\": [\n \"arn:*:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing\"\n - \ ],\n \"Effect\": \"Allow\"\n },\n {\n \"Action\": - [\n \"iam:PassRole\"\n ],\n \"Resource\": - [\n \"arn:*:iam::*:role/*-worker-role\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n\t {\n\t \t\"Effect\": - \"Allow\",\n\t \t\"Action\": [\n\t \t\t\"kms:Decrypt\",\n\t - \ \t\t\"kms:Encrypt\",\n\t \t\t\"kms:GenerateDataKey\",\n\t - \ \t\t\"kms:GenerateDataKeyWithoutPlainText\",\n\t \t\t\"kms:DescribeKey\"\n\t - \ \t],\n\t \t\"Resource\": \"*\"\n\t },\n\t {\n\t - \ \t\"Effect\": \"Allow\",\n\t \t\"Action\": [\n\t - \ \t\t\"kms:RevokeGrant\",\n\t \t\t\"kms:CreateGrant\",\n\t - \ \t\t\"kms:ListGrants\"\n\t \t],\n\t \t\"Resource\": - \"*\",\n\t \t\"Condition\": {\n\t \t\t\"Bool\": {\n\t - \ \t\t\t\"kms:GrantIsForAWSResource\": true\n\t \t\t}\n\t - \ \t}\n\t }\n ]\n}" - type: string - storageARN: - description: "StorageARN is an ARN value referencing a - role appropriate for the Storage Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:AttachVolume\",\n\t\t\t\t\"ec2:CreateSnapshot\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"ec2:CreateVolume\",\n\t\t\t\t\"ec2:DeleteSnapshot\",\n\t\t\t\t\"ec2:DeleteTags\",\n\t\t\t\t\"ec2:DeleteVolume\",\n\t\t\t\t\"ec2:DescribeInstances\",\n\t\t\t\t\"ec2:DescribeSnapshots\",\n\t\t\t\t\"ec2:DescribeTags\",\n\t\t\t\t\"ec2:DescribeVolumes\",\n\t\t\t\t\"ec2:DescribeVolumesModifications\",\n\t\t\t\t\"ec2:DetachVolume\",\n\t\t\t\t\"ec2:ModifyVolume\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - required: - - controlPlaneOperatorARN - - imageRegistryARN - - ingressARN - - kubeCloudControllerARN - - networkARN - - nodePoolManagementARN - - storageARN - type: object - serviceEndpoints: - description: |- - ServiceEndpoints specifies optional custom endpoints which will override - the default service endpoint of specific AWS Services. - - - There must be only one ServiceEndpoint for a given service name. - items: - description: |- - AWSServiceEndpoint stores the configuration for services to - override existing defaults of AWS Services. - properties: - name: - description: |- - Name is the name of the AWS service. - This must be provided and cannot be empty. - type: string - url: - description: |- - URL is fully qualified URI with scheme https, that overrides the default generated - endpoint for a client. - This must be provided and cannot be empty. - pattern: ^https:// - type: string - required: - - name - - url - type: object - type: array - required: - - controlPlaneOperatorCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - rolesRef - type: object - azure: - description: Azure defines azure specific settings - properties: - cloud: - default: AzurePublicCloud - description: 'The cloud environment identifier, valid values - could be found here: https://github.com/Azure/go-autorest/blob/4c0e21ca2bbb3251fe7853e6f9df6397f53dd419/autorest/azure/environments.go#L33' - enum: - - AzurePublicCloud - - AzureUSGovernmentCloud - - AzureChinaCloud - - AzureGermanCloud - type: string - credentials: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - location: - type: string - resourceGroup: - type: string - securityGroupID: - type: string - subnetID: - type: string - subscriptionID: - type: string - vnetID: - type: string - required: - - credentials - - location - - resourceGroup - - securityGroupID - - subnetID - - subscriptionID - - vnetID - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: KubeVirt defines KubeVirt specific settings for cluster - components. - properties: - baseDomainPassthrough: - description: |- - BaseDomainPassthrough toggles whether or not an automatically - generated base domain for the guest cluster should be used that - is a subdomain of the management cluster's *.apps DNS. - - - For the KubeVirt platform, the basedomain can be autogenerated using - the *.apps domain of the management/infra hosting cluster - This makes the guest cluster's base domain a subdomain of the - hypershift infra/mgmt cluster's base domain. - - - Example: - Infra/Mgmt cluster's DNS - Base: example.com - Cluster: mgmt-cluster.example.com - Apps: *.apps.mgmt-cluster.example.com - KubeVirt Guest cluster's DNS - Base: apps.mgmt-cluster.example.com - Cluster: guest.apps.mgmt-cluster.example.com - Apps: *.apps.guest.apps.mgmt-cluster.example.com - - - This is possible using OCP wildcard routes - type: boolean - x-kubernetes-validations: - - message: baseDomainPassthrough is immutable - rule: self == oldSelf - credentials: - description: |- - Credentials defines the client credentials used when creating KubeVirt virtual machines. - Defining credentials is only necessary when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - generateID: - description: |- - GenerateID is used to uniquely apply a name suffix to resources associated with - kubevirt infrastructure resources - maxLength: 11 - type: string - x-kubernetes-validations: - - message: Kubevirt GenerateID is immutable once set - rule: self == oldSelf - storageDriver: - description: |- - StorageDriver defines how the KubeVirt CSI driver exposes StorageClasses on - the infra cluster (hosting the VMs) to the guest cluster. - properties: - manual: - description: |- - Manual is used to explicilty define how the infra storageclasses are - mapped to guest storageclasses - properties: - storageClassMapping: - description: |- - StorageClassMapping maps StorageClasses on the infra cluster hosting - the KubeVirt VMs to StorageClasses that are made available within the - Guest Cluster. - - - NOTE: It is possible that not all capablities of an infra cluster's - storageclass will be present for the corresponding guest clusters storageclass. - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestStorageClassName: - description: |- - GuestStorageClassName is the name that the corresponding storageclass will - be called within the guest cluster - type: string - infraStorageClassName: - description: |- - InfraStorageClassName is the name of the infra cluster storage class that - will be exposed to the guest. - type: string - required: - - guestStorageClassName - - infraStorageClassName - type: object - type: array - x-kubernetes-validations: - - message: storageClassMapping is immutable - rule: self == oldSelf - volumeSnapshotClassMapping: - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestVolumeSnapshotClassName: - description: |- - GuestVolumeSnapshotClassName is the name that the corresponding volumeSnapshotClass will - be called within the guest cluster - type: string - infraVolumeSnapshotClassName: - description: |- - InfraStorageClassName is the name of the infra cluster volume snapshot class that - will be exposed to the guest. - type: string - required: - - guestVolumeSnapshotClassName - - infraVolumeSnapshotClassName - type: object - type: array - x-kubernetes-validations: - - message: volumeSnapshotClassMapping is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver.Manual is immutable - rule: self == oldSelf - type: - default: Default - description: Type represents the type of kubevirt csi - driver configuration to use - enum: - - None - - Default - - Manual - type: string - x-kubernetes-validations: - - message: storageDriver.Type is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: Kubevirt GenerateID is required once set - rule: '!has(oldSelf.generateID) || has(self.generateID)' - powervs: - description: |- - PowerVS specifies configuration for clusters running on IBMCloud Power VS Service. - This field is immutable. Once set, It can't be changed. - properties: - accountID: - description: |- - AccountID is the IBMCloud account id. - This field is immutable. Once set, It can't be changed. - type: string - cisInstanceCRN: - description: |- - CISInstanceCRN is the IBMCloud CIS Service Instance's Cloud Resource Name - This field is immutable. Once set, It can't be changed. - pattern: '^crn:' - type: string - imageRegistryOperatorCloudCreds: - description: |- - ImageRegistryOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for image registry operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - ingressOperatorCloudCreds: - description: |- - IngressOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for ingress operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeCloudControllerCreds: - description: |- - KubeCloudControllerCreds is a reference to a secret containing cloud - credentials with permissions matching the cloud controller policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "cloud controller policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - nodePoolManagementCreds: - description: |- - NodePoolManagementCreds is a reference to a secret containing cloud - credentials with permissions matching the node pool management policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "node pool management policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the IBMCloud region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot image for a given release. - This field is immutable. Once set, It can't be changed. - type: string - resourceGroup: - description: |- - ResourceGroup is the IBMCloud Resource Group in which the cluster resides. - This field is immutable. Once set, It can't be changed. - type: string - serviceInstanceID: - description: |- - ServiceInstance is the reference to the Power VS service on which the server instance(VM) will be created. - Power VS service is a container for all Power VS instances at a specific geographic region. - serviceInstance can be created via IBM Cloud catalog or CLI. - ServiceInstanceID is the unique identifier that can be obtained from IBM Cloud UI or IBM Cloud cli. - - - More detail about Power VS service instance. - https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server - - - This field is immutable. Once set, It can't be changed. - type: string - storageOperatorCloudCreds: - description: |- - StorageOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for storage operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - subnet: - description: |- - Subnet is the subnet to use for control plane cloud resources. - This field is immutable. Once set, It can't be changed. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - vpc: - description: |- - VPC specifies IBM Cloud PowerVS Load Balancing configuration for the control - plane. - This field is immutable. Once set, It can't be changed. - properties: - name: - description: |- - Name for VPC to used for all the service load balancer. - This field is immutable. Once set, It can't be changed. - type: string - region: - description: |- - Region is the IBMCloud region in which VPC gets created, this VPC used for all the ingress traffic - into the OCP cluster. - This field is immutable. Once set, It can't be changed. - type: string - subnet: - description: |- - Subnet is the subnet to use for load balancer. - This field is immutable. Once set, It can't be changed. - type: string - zone: - description: |- - Zone is the availability zone where load balancer cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - name - - region - type: object - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - accountID - - cisInstanceCRN - - imageRegistryOperatorCloudCreds - - ingressOperatorCloudCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - resourceGroup - - serviceInstanceID - - storageOperatorCloudCreds - - subnet - - vpc - - zone - type: object - type: - description: Type is the type of infrastructure provider for the - cluster. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - type: string - required: - - type - type: object - pullSecret: - description: |- - PullSecret references a pull secret to be injected into the container - runtime of all cluster nodes. The secret must have a key named - ".dockerconfigjson" whose value is the pull secret JSON. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - release: - description: |- - Release specifies the desired OCP release payload for the hosted cluster. - - - Updating this field will trigger a rollout of the control plane. The - behavior of the rollout will be driven by the ControllerAvailabilityPolicy - and InfrastructureAvailabilityPolicy. - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - secretEncryption: - description: |- - SecretEncryption specifies a Kubernetes secret encryption strategy for the - control plane. - properties: - aescbc: - description: AESCBC defines metadata about the AESCBC secret encryption - strategy - properties: - activeKey: - description: ActiveKey defines the active key used to encrypt - new secrets - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - activeKey - type: object - kms: - description: KMS defines metadata about the kms secret encryption - strategy - properties: - aws: - description: AWS defines metadata about the configuration - of the AWS KMS Secret Encryption provider - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - auth: - description: Auth defines metadata about the management - of credentials used to interact with AWS KMS - properties: - awsKms: - description: "The referenced role must have a trust - relationship that allows it to be assumed via web - identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ - .ProviderName }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nAWSKMSARN - is an ARN value referencing a role appropriate for - managing the auth via the AWS KMS key.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n \t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"kms:Encrypt\",\n\t\t\t\t\"kms:Decrypt\",\n\t\t\t\t\"kms:ReEncrypt*\",\n\t\t\t\t\"kms:GenerateDataKey*\",\n\t\t\t\t\"kms:DescribeKey\"\n\t\t\t],\n\t\t\t\"Resource\": - %q\n\t\t}\n\t]\n}" - type: string - credentials: - description: |- - Deprecated - This field is deprecated and will be removed in a future release. Use AWSKMSRoleARN instead. - Credentials contains the name of the secret that holds the aws credentials that can be used - to make the necessary KMS calls. It should at key AWSCredentialsFileSecretKey contain the - aws credentials file that can be used to configure AWS SDKs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - awsKms - - credentials - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - region: - description: Region contains the AWS region - type: string - required: - - activeKey - - auth - - region - type: object - azure: - description: Azure defines metadata about the configuration - of the Azure KMS Secret Encryption provider using Azure - key vault - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - required: - - activeKey - type: object - ibmcloud: - description: IBMCloud defines metadata for the IBM Cloud KMS - encryption strategy - properties: - auth: - description: Auth defines metadata for how authentication - is done with IBM Cloud KMS - properties: - managed: - description: |- - Managed defines metadata around the service to service authentication strategy for the IBM Cloud - KMS system (all provider managed). - type: object - type: - description: Type defines the IBM Cloud KMS authentication - strategy - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: Unmanaged defines the auth metadata the - customer provides to interact with IBM Cloud KMS - properties: - credentials: - description: |- - Credentials should reference a secret with a key field of IBMCloudIAMAPIKeySecretKey that contains a apikey to - call IBM Cloud KMS APIs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - credentials - type: object - required: - - type - type: object - keyList: - description: KeyList defines the list of keys used for - data encryption - items: - description: IBMCloudKMSKeyEntry defines metadata for - an IBM Cloud KMS encryption key - properties: - correlationID: - description: CorrelationID is an identifier used - to track all api call usage from hypershift - type: string - crkID: - description: CRKID is the customer rook key id - type: string - instanceID: - description: InstanceID is the id for the key protect - instance - type: string - keyVersion: - description: |- - KeyVersion is a unique number associated with the key. The number increments whenever a new - key is enabled for data encryption. - type: integer - url: - description: URL is the url to call key protect - apis over - pattern: ^https:// - type: string - required: - - correlationID - - crkID - - instanceID - - keyVersion - - url - type: object - type: array - region: - description: Region is the IBM Cloud region - type: string - required: - - auth - - keyList - - region - type: object - provider: - description: Provider defines the KMS provider - enum: - - IBMCloud - - AWS - - Azure - type: string - required: - - provider - type: object - type: - description: Type defines the type of kube secret encryption being - used - enum: - - kms - - aescbc - type: string - required: - - type - type: object - serviceAccountSigningKey: - description: |- - ServiceAccountSigningKey is a reference to a secret containing the private key - used by the service account token issuer. The secret is expected to contain - a single key named "key". If not specified, a service account signing key will - be generated automatically for the cluster. When specifying a service account - signing key, a IssuerURL must also be specified. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - services: - description: |- - Services specifies how individual control plane services are published from - the hosting cluster of the control plane. - - - If a given service is not present in this list, it will be exposed publicly - by default. - items: - description: |- - ServicePublishingStrategyMapping specifies how individual control plane - services are published from the hosting cluster of a control plane. - properties: - service: - description: Service identifies the type of service being published. - enum: - - APIServer - - OAuthServer - - OIDC - - Konnectivity - - Ignition - - OVNSbDb - type: string - servicePublishingStrategy: - description: ServicePublishingStrategy specifies how to publish - Service. - properties: - loadBalancer: - description: LoadBalancer configures exposing a service - using a LoadBalancer. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the LoadBalancer. - type: string - type: object - nodePort: - description: NodePort configures exposing a service using - a NodePort. - properties: - address: - description: Address is the host/ip that the NodePort - service is exposed over. - type: string - port: - description: |- - Port is the port of the NodePort service. If <=0, the port is dynamically - assigned when the service is created. - format: int32 - type: integer - required: - - address - type: object - route: - description: Route configures exposing a service using a - Route. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the Route. - type: string - type: object - type: - description: Type is the publishing strategy used for the - service. - enum: - - LoadBalancer - - NodePort - - Route - - None - - S3 - type: string - required: - - type - type: object - required: - - service - - servicePublishingStrategy - type: object - type: array - sshKey: - description: |- - SSHKey references an SSH key to be injected into all cluster node sshd - servers. The secret must have a single key "id_rsa.pub" whose value is the - public part of an SSH key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - tolerations: - description: Tolerations when specified, define what custome tolerations - are added to the hcp pods. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - updateService: - description: |- - updateService may be used to specify the preferred upstream update service. - By default it will use the appropriate update service for the cluster and region. - type: string - required: - - networking - - platform - - pullSecret - - release - - services - - sshKey - type: object - status: - description: Status is the latest observed status of the HostedCluster. - properties: - conditions: - description: |- - Conditions represents the latest available observations of a control - plane's current state. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint contains the endpoint information by which - external clients can access the control plane. This is populated - after the infrastructure is ready. - properties: - host: - description: Host is the hostname on which the API server is serving. - type: string - port: - description: Port is the port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - ignitionEndpoint: - description: |- - IgnitionEndpoint is the endpoint injected in the ign config userdata. - It exposes the config for instances to become kubernetes nodes. - type: string - kubeadminPassword: - description: |- - KubeadminPassword is a reference to the secret that contains the initial - kubeadmin user password for the guest cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeconfig: - description: |- - KubeConfig is a reference to the secret containing the default kubeconfig - for the cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - oauthCallbackURLTemplate: - description: |- - OAuthCallbackURLTemplate contains a template for the URL to use as a callback - for identity providers. The [identity-provider-name] placeholder must be replaced - with the name of an identity provider defined on the HostedCluster. - This is populated after the infrastructure is ready. - type: string - platform: - description: Platform contains platform-specific status of the HostedCluster - properties: - aws: - description: AWSPlatformStatus contains status specific to the - AWS platform - properties: - defaultWorkerSecurityGroupID: - description: |- - DefaultWorkerSecurityGroupID is the ID of a security group created by - the control plane operator. It is always added to worker machines in - addition to any security groups specified in the NodePool. - type: string - type: object - type: object - version: - description: |- - Version is the status of the release version applied to the - HostedCluster. - properties: - availableUpdates: - description: |- - availableUpdates contains updates recommended for this - cluster. Updates which appear in conditionalUpdates but not in - availableUpdates may expose this cluster to known issues. This list - may be empty if no updates are recommended, if the update service - is unavailable, or if an invalid channel has been specified. - items: - description: Release represents an OpenShift release image and - associated metadata. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - nullable: true - type: array - conditionalUpdates: - description: |- - conditionalUpdates contains the list of updates that may be - recommended for this cluster if it meets specific required - conditions. Consumers interested in the set of updates that are - actually recommended for this cluster should use - availableUpdates. This list may be empty if no updates are - recommended, if the update service is unavailable, or if an empty - or invalid channel has been specified. - items: - description: |- - ConditionalUpdate represents an update which is recommended to some - clusters on the version the current cluster is reconciling, but which - may not be recommended for the current cluster. - properties: - conditions: - description: |- - conditions represents the observations of the conditional update's - current status. Known types are: - * Recommended, for whether the update is recommended for the current cluster. - items: - description: "Condition contains details for one aspect - of the current state of this API Resource.\n---\nThis - struct is intended for direct use as an array at the - field path .status.conditions. For example,\n\n\n\ttype - FooStatus struct{\n\t // Represents the observations - of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t - \ // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t - \ // +listType=map\n\t // +listMapKey=type\n\t - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, - False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - release: - description: release is the target of the update. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - risks: - description: |- - risks represents the range of issues associated with - updating to the target release. The cluster-version - operator will evaluate all entries, and only recommend the - update if there is at least one entry and all entries - recommend the update. - items: - description: |- - ConditionalUpdateRisk represents a reason and cluster-state - for not recommending a conditional update. - properties: - matchingRules: - description: |- - matchingRules is a slice of conditions for deciding which - clusters match the risk and which do not. The slice is - ordered by decreasing precedence. The cluster-version - operator will walk the slice in order, and stop after the - first it can successfully evaluate. If no condition can be - successfully evaluated, the update will not be recommended. - items: - description: |- - ClusterCondition is a union of typed cluster conditions. The 'type' - property determines which of the type-specific properties are relevant. - When evaluated on a cluster, the condition may match, not match, or - fail to evaluate. - properties: - promql: - description: promQL represents a cluster condition - based on PromQL. - properties: - promql: - description: |- - PromQL is a PromQL query classifying clusters. This query - query should return a 1 in the match case and a 0 in the - does-not-match case. Queries which return no time - series, or which return values besides 0 or 1, are - evaluation failures. - type: string - required: - - promql - type: object - type: - description: |- - type represents the cluster-condition type. This defines - the members and semantics of any additional properties. - enum: - - Always - - PromQL - type: string - required: - - type - type: object - minItems: 1 - type: array - x-kubernetes-list-type: atomic - message: - description: |- - message provides additional information about the risk of - updating, in the event that matchingRules match the cluster - state. This is only to be consumed by humans. It may - contain Line Feed characters (U+000A), which should be - rendered as new lines. - minLength: 1 - type: string - name: - description: |- - name is the CamelCase reason for not recommending a - conditional update, in the event that matchingRules match the - cluster state. - minLength: 1 - type: string - url: - description: url contains information about this risk. - format: uri - minLength: 1 - type: string - required: - - matchingRules - - message - - name - - url - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - release - - risks - type: object - type: array - x-kubernetes-list-type: atomic - desired: - description: |- - desired is the version that the cluster is reconciling towards. - If the cluster is not yet fully initialized desired will be set - with the information available, which may be an image or a tag. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - history: - description: |- - history contains a list of the most recent versions applied to the cluster. - This value may be empty during cluster startup, and then will be updated - when a new update is being applied. The newest update is first in the - list and it is ordered by recency. Updates in the history have state - Completed if the rollout completed - if an update was failing or halfway - applied the state will be Partial. Only a limited amount of update history - is preserved. - items: - description: UpdateHistory is a single attempted update to the - cluster. - properties: - acceptedRisks: - description: |- - acceptedRisks records risks which were accepted to initiate the update. - For example, it may menition an Upgradeable=False or missing signature - that was overriden via desiredUpdate.force, or an update that was - initiated despite not being in the availableUpdates set of recommended - update targets. - type: string - completionTime: - description: |- - completionTime, if set, is when the update was fully applied. The update - that is currently being applied will have a null completion time. - Completion time will always be set for entries that are not the current - update (usually to the started time of the next update). - format: date-time - nullable: true - type: string - image: - description: |- - image is a container image location that contains the update. This value - is always populated. - type: string - startedTime: - description: startedTime is the time at which the update - was started. - format: date-time - type: string - state: - description: |- - state reflects whether the update was fully applied. The Partial state - indicates the update is not fully applied, while the Completed state - indicates the update was successfully rolled out at least once (all - parts of the update successfully applied). - type: string - verified: - description: |- - verified indicates whether the provided update was properly verified - before it was installed. If this is false the cluster may not be trusted. - Verified does not cover upgradeable checks that depend on the cluster - state at the time when the update target was accepted. - type: boolean - version: - description: |- - version is a semantic version identifying the update version. If the - requested image does not define a version, or if a failure occurs - retrieving the image, this value may be empty. - type: string - required: - - completionTime - - image - - startedTime - - state - - verified - type: object - type: array - observedGeneration: - description: |- - observedGeneration reports which version of the spec is being synced. - If this value is not equal to metadata.generation, then the desired - and conditions fields may represent a previous version. - format: int64 - type: integer - required: - - availableUpdates - - desired - - observedGeneration - type: object - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Version - jsonPath: .status.version.history[?(@.state=="Completed")].version - name: Version - type: string - - description: KubeConfig Secret - jsonPath: .status.kubeconfig.name - name: KubeConfig - type: string - - description: Progress - jsonPath: .status.version.history[?(@.state!="")].state - name: Progress - type: string - - description: Available - jsonPath: .status.conditions[?(@.type=="Available")].status - name: Available - type: string - - description: Progressing - jsonPath: .status.conditions[?(@.type=="Progressing")].status - name: Progressing - type: string - - description: Message - jsonPath: .status.conditions[?(@.type=="Available")].message - name: Message - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - HostedCluster is the primary representation of a HyperShift cluster and encapsulates - the control plane and common data plane configuration. Creating a HostedCluster - results in a fully functional OpenShift control plane with no attached nodes. - To support workloads (e.g. pods), a HostedCluster may have one or more associated - NodePool resources. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the desired behavior of the HostedCluster. - properties: - additionalTrustBundle: - description: |- - AdditionalTrustBundle is a reference to a ConfigMap containing a - PEM-encoded X.509 certificate bundle that will be added to the hosted controlplane and nodes - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - auditWebhook: - description: |- - AuditWebhook contains metadata for configuring an audit webhook endpoint - for a cluster to process cluster audit events. It references a secret that - contains the webhook information for the audit webhook endpoint. It is a - secret because if the endpoint has mTLS the kubeconfig will contain client - keys. The kubeconfig needs to be stored in the secret with a secret key - name that corresponds to the constant AuditWebhookKubeconfigKey. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - autoscaling: - description: |- - Autoscaling specifies auto-scaling behavior that applies to all NodePools - associated with the control plane. - properties: - maxNodeProvisionTime: - description: |- - MaxNodeProvisionTime is the maximum time to wait for node provisioning - before considering the provisioning to be unsuccessful, expressed as a Go - duration string. The default is 15 minutes. - pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ - type: string - maxNodesTotal: - description: |- - MaxNodesTotal is the maximum allowable number of nodes across all NodePools - for a HostedCluster. The autoscaler will not grow the cluster beyond this - number. - format: int32 - minimum: 0 - type: integer - maxPodGracePeriod: - description: |- - MaxPodGracePeriod is the maximum seconds to wait for graceful pod - termination before scaling down a NodePool. The default is 600 seconds. - format: int32 - minimum: 0 - type: integer - podPriorityThreshold: - description: |- - PodPriorityThreshold enables users to schedule "best-effort" pods, which - shouldn't trigger autoscaler actions, but only run when there are spare - resources available. The default is -10. - - - See the following for more details: - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-cluster-autoscaler-work-with-pod-priority-and-preemption - format: int32 - type: integer - type: object - channel: - description: |- - channel is an identifier for explicitly requesting that a non-default - set of updates be applied to this cluster. The default channel will be - contain stable updates that are appropriate for production clusters. - type: string - clusterID: - description: |- - ClusterID uniquely identifies this cluster. This is expected to be - an RFC4122 UUID value (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in - hexadecimal values). - As with a Kubernetes metadata.uid, this ID uniquely identifies this - cluster in space and time. - This value identifies the cluster in metrics pushed to telemetry and - metrics produced by the control plane operators. If a value is not - specified, an ID is generated. After initial creation, the value is - immutable. - pattern: '[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}' - type: string - configuration: - description: |- - Configuration specifies configuration for individual OCP components in the - cluster, represented as embedded resources that correspond to the openshift - configuration API. - properties: - apiServer: - description: |- - APIServer holds configuration (like serving certificates, client CA and CORS domains) - shared by all API servers in the system, among them especially kube-apiserver - and openshift-apiserver. - properties: - additionalCORSAllowedOrigins: - description: |- - additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the - API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth - server from JavaScript applications. - The values are regular expressions that correspond to the Golang regular expression language. - items: - type: string - type: array - audit: - default: - profile: Default - description: |- - audit specifies the settings for audit configuration to be applied to all OpenShift-provided - API servers in the cluster. - properties: - customRules: - description: |- - customRules specify profiles per group. These profile take precedence over the - top-level profile field if they apply. They are evaluation from top to bottom and - the first one that matches, applies. - items: - description: |- - AuditCustomRule describes a custom rule for an audit profile that takes precedence over - the top-level profile. - properties: - group: - description: group is a name of group a request - user must be member of in order to this profile - to apply. - minLength: 1 - type: string - profile: - description: |- - profile specifies the name of the desired audit policy configuration to be deployed to - all OpenShift-provided API servers in the cluster. - - - The following profiles are provided: - - Default: the existing default policy. - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - required: - - group - - profile - type: object - type: array - x-kubernetes-list-map-keys: - - group - x-kubernetes-list-type: map - profile: - default: Default - description: |- - profile specifies the name of the desired top-level audit profile to be applied to all requests - sent to any of the OpenShift-provided API servers in the cluster (kube-apiserver, - openshift-apiserver and oauth-apiserver), with the exception of those requests that match - one or more of the customRules. - - - The following profiles are provided: - - Default: default policy which means MetaData level logging with the exception of events - (not logged at all), oauthaccesstokens and oauthauthorizetokens (both logged at RequestBody - level). - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - Warning: It is not recommended to disable audit logging by using the `None` profile unless you - are fully aware of the risks of not logging data that can be beneficial when troubleshooting issues. - If you disable audit logging and a support situation arises, you might need to enable audit logging - and reproduce the issue in order to troubleshoot properly. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - type: object - clientCA: - description: |- - clientCA references a ConfigMap containing a certificate bundle for the signers that will be recognized for - incoming client certificates in addition to the operator managed signers. If this is empty, then only operator managed signers are valid. - You usually only have to set this if you have your own PKI you wish to honor client certificates from. - The ConfigMap must exist in the openshift-config namespace and contain the following required fields: - - ConfigMap.Data["ca-bundle.crt"] - CA bundle. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - encryption: - description: encryption allows the configuration of encryption - of resources at the datastore layer. - properties: - type: - description: |- - type defines what encryption type should be used to encrypt resources at the datastore layer. - When this field is unset (i.e. when it is set to the empty string), identity is implied. - The behavior of unset can and will change over time. Even if encryption is enabled by default, - the meaning of unset may change to a different encryption type based on changes in best practices. - - - When encryption is enabled, all sensitive resources shipped with the platform are encrypted. - This list of sensitive resources can and will change over time. The current authoritative list is: - - - 1. secrets - 2. configmaps - 3. routes.route.openshift.io - 4. oauthaccesstokens.oauth.openshift.io - 5. oauthauthorizetokens.oauth.openshift.io - enum: - - "" - - identity - - aescbc - - aesgcm - type: string - type: object - servingCerts: - description: |- - servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates - will be used for serving secure traffic. - properties: - namedCertificates: - description: |- - namedCertificates references secrets containing the TLS cert info for serving secure traffic to specific hostnames. - If no named certificates are provided, or no named certificates match the server name as understood by a client, - the defaultServingCertificate will be used. - items: - description: APIServerNamedServingCert maps a server - DNS name, as understood by a client, to a certificate. - properties: - names: - description: |- - names is a optional list of explicit DNS names (leading wildcards allowed) that should use this certificate to - serve secure traffic. If no names are provided, the implicit names will be extracted from the certificates. - Exact names trump over wildcard names. Explicit names defined here trump over extracted implicit names. - items: - type: string - type: array - servingCertificate: - description: |- - servingCertificate references a kubernetes.io/tls type secret containing the TLS cert info for serving secure traffic. - The secret must exist in the openshift-config namespace and contain the following required fields: - - Secret.Data["tls.key"] - TLS private key. - - Secret.Data["tls.crt"] - TLS certificate. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - type: array - type: object - tlsSecurityProfile: - description: |- - tlsSecurityProfile specifies settings for TLS connections for externally exposed servers. - - - If unset, a default (which may change between releases) is chosen. Note that only Old, - Intermediate and Custom profiles are currently supported, and the maximum available - minTLSVersion is VersionTLS12. - properties: - custom: - description: |- - custom is a user-defined TLS security profile. Be extremely careful using a custom - profile as invalid configurations can be catastrophic. An example custom profile - looks like this: - - - ciphers: - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - minTLSVersion: VersionTLS11 - nullable: true - properties: - ciphers: - description: |- - ciphers is used to specify the cipher algorithms that are negotiated - during the TLS handshake. Operators may remove entries their operands - do not support. For example, to use DES-CBC3-SHA (yaml): - - - ciphers: - - DES-CBC3-SHA - items: - type: string - type: array - minTLSVersion: - description: |- - minTLSVersion is used to specify the minimal version of the TLS protocol - that is negotiated during the TLS handshake. For example, to use TLS - versions 1.1, 1.2 and 1.3 (yaml): - - - minTLSVersion: VersionTLS11 - - - NOTE: currently the highest minTLSVersion allowed is VersionTLS12 - enum: - - VersionTLS10 - - VersionTLS11 - - VersionTLS12 - - VersionTLS13 - type: string - type: object - intermediate: - description: |- - intermediate is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - minTLSVersion: VersionTLS12 - nullable: true - type: object - modern: - description: |- - modern is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - minTLSVersion: VersionTLS13 - nullable: true - type: object - old: - description: |- - old is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - - DHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-ECDSA-AES128-SHA256 - - - - ECDHE-RSA-AES128-SHA256 - - - - ECDHE-ECDSA-AES128-SHA - - - - ECDHE-RSA-AES128-SHA - - - - ECDHE-ECDSA-AES256-SHA384 - - - - ECDHE-RSA-AES256-SHA384 - - - - ECDHE-ECDSA-AES256-SHA - - - - ECDHE-RSA-AES256-SHA - - - - DHE-RSA-AES128-SHA256 - - - - DHE-RSA-AES256-SHA256 - - - - AES128-GCM-SHA256 - - - - AES256-GCM-SHA384 - - - - AES128-SHA256 - - - - AES256-SHA256 - - - - AES128-SHA - - - - AES256-SHA - - - - DES-CBC3-SHA - - - minTLSVersion: VersionTLS10 - nullable: true - type: object - type: - description: |- - type is one of Old, Intermediate, Modern or Custom. Custom provides - the ability to specify individual TLS security profile parameters. - Old, Intermediate and Modern are TLS security profiles based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations - - - The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers - are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be - reduced. - - - Note that the Modern profile is currently not supported because it is not - yet well adopted by common software libraries. - enum: - - Old - - Intermediate - - Modern - - Custom - type: string - type: object - type: object - authentication: - description: |- - Authentication specifies cluster-wide settings for authentication (like OAuth and - webhook token authenticators). - properties: - oauthMetadata: - description: |- - oauthMetadata contains the discovery endpoint data for OAuth 2.0 - Authorization Server Metadata for an external OAuth server. - This discovery document can be viewed from its served location: - oc get --raw '/.well-known/oauth-authorization-server' - For further details, see the IETF Draft: - https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 - If oauthMetadata.name is non-empty, this value has precedence - over any metadata reference stored in status. - The key "oauthMetadata" is used to locate the data. - If specified and the config map or expected key is not found, no metadata is served. - If the specified metadata is not valid, no metadata is served. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - oidcProviders: - description: |- - OIDCProviders are OIDC identity providers that can issue tokens - for this cluster - Can only be set if "Type" is set to "OIDC". - - - At most one provider can be configured. - items: - properties: - claimMappings: - description: |- - ClaimMappings describes rules on how to transform information from an - ID token into a cluster identity - properties: - groups: - description: |- - Groups is a name of the claim that should be used to construct - groups for the cluster identity. - The referenced claim must use array of strings values. - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - description: |- - Prefix is a string to prefix the value from the token in the result of the - claim mapping. - - - By default, no prefixing occurs. - - - Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains - an array of strings "a", "b" and "c", the mapping will result in an - array of string "myoidc:a", "myoidc:b" and "myoidc:c". - type: string - required: - - claim - type: object - username: - description: |- - Username is a name of the claim that should be used to construct - usernames for the cluster identity. - - - Default value: "sub" - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - properties: - prefixString: - minLength: 1 - type: string - required: - - prefixString - type: object - prefixPolicy: - description: |- - PrefixPolicy specifies how a prefix should apply. - - - By default, claims other than `email` will be prefixed with the issuer URL to - prevent naming clashes with other plugins. - - - Set to "NoPrefix" to disable prefixing. - - - Example: - (1) `prefix` is set to "myoidc:" and `claim` is set to "username". - If the JWT claim `username` contains value `userA`, the resulting - mapped value will be "myoidc:userA". - (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the - JWT `email` claim contains value "userA@myoidc.tld", the resulting - mapped value will be "myoidc:userA@myoidc.tld". - (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`, - the JWT claims include "username":"userA" and "email":"userA@myoidc.tld", - and `claim` is set to: - (a) "username": the mapped value will be "https://myoidc.tld#userA" - (b) "email": the mapped value will be "userA@myoidc.tld" - enum: - - "" - - NoPrefix - - Prefix - type: string - required: - - claim - type: object - x-kubernetes-validations: - - message: prefix must be set if prefixPolicy is - 'Prefix', but must remain unset otherwise - rule: 'has(self.prefixPolicy) && self.prefixPolicy - == ''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString) - > 0) : !has(self.prefix)' - type: object - claimValidationRules: - description: ClaimValidationRules are rules that are - applied to validate token claims to authenticate users. - items: - properties: - requiredClaim: - description: |- - RequiredClaim allows configuring a required claim name and its expected - value - properties: - claim: - description: |- - Claim is a name of a required claim. Only claims with string values are - supported. - minLength: 1 - type: string - requiredValue: - description: RequiredValue is the required - value for the claim. - minLength: 1 - type: string - required: - - claim - - requiredValue - type: object - type: - default: RequiredClaim - description: Type sets the type of the validation - rule - enum: - - RequiredClaim - type: string - type: object - type: array - x-kubernetes-list-type: atomic - issuer: - description: Issuer describes atributes of the OIDC - token issuer - properties: - audiences: - description: |- - Audiences is an array of audiences that the token was issued for. - Valid tokens must include at least one of these values in their - "aud" claim. - Must be set to exactly one value. - items: - minLength: 1 - type: string - maxItems: 10 - minItems: 1 - type: array - x-kubernetes-list-type: set - issuerCertificateAuthority: - description: |- - CertificateAuthority is a reference to a config map in the - configuration namespace. The .data of the configMap must contain - the "ca-bundle.crt" key. - If unset, system trust is used instead. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - issuerURL: - description: |- - URL is the serving URL of the token issuer. - Must use the https:// scheme. - pattern: ^https:\/\/[^\s] - type: string - required: - - audiences - - issuerURL - type: object - name: - description: Name of the OIDC provider - minLength: 1 - type: string - oidcClients: - description: |- - OIDCClients contains configuration for the platform's clients that - need to request tokens from the issuer - items: - properties: - clientID: - description: ClientID is the identifier of the - OIDC client from the OIDC provider - minLength: 1 - type: string - clientSecret: - description: |- - ClientSecret refers to a secret in the `openshift-config` namespace that - contains the client secret in the `clientSecret` key of the `.data` field - properties: - name: - description: name is the metadata.name of - the referenced secret - type: string - required: - - name - type: object - componentName: - description: |- - ComponentName is the name of the component that is supposed to consume this - client configuration - maxLength: 256 - minLength: 1 - type: string - componentNamespace: - description: |- - ComponentNamespace is the namespace of the component that is supposed to consume this - client configuration - maxLength: 63 - minLength: 1 - type: string - extraScopes: - description: ExtraScopes is an optional set of - scopes to request tokens with. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - clientID - - componentName - - componentNamespace - type: object - maxItems: 20 - type: array - x-kubernetes-list-map-keys: - - componentNamespace - - componentName - x-kubernetes-list-type: map - required: - - issuer - - name - type: object - maxItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceAccountIssuer: - description: |- - serviceAccountIssuer is the identifier of the bound service account token - issuer. - The default is https://kubernetes.default.svc - WARNING: Updating this field will not result in immediate invalidation of all bound tokens with the - previous issuer value. Instead, the tokens issued by previous service account issuer will continue to - be trusted for a time period chosen by the platform (currently set to 24h). - This time period is subject to change over time. - This allows internal components to transition to use new service account issuer without service distruption. - type: string - type: - description: |- - type identifies the cluster managed, user facing authentication mode in use. - Specifically, it manages the component that responds to login attempts. - The default is IntegratedOAuth. - type: string - webhookTokenAuthenticator: - description: |- - webhookTokenAuthenticator configures a remote token reviewer. - These remote authentication webhooks can be used to verify bearer tokens - via the tokenreviews.authentication.k8s.io REST API. This is required to - honor bearer tokens that are provisioned by an external authentication service. - - - Can only be set if "Type" is set to "None". - properties: - kubeConfig: - description: |- - kubeConfig references a secret that contains kube config file data which - describes how to access the remote webhook service. - The namespace for the referenced secret is openshift-config. - - - For further details, see: - - - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - - - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - kubeConfig - type: object - webhookTokenAuthenticators: - description: webhookTokenAuthenticators is DEPRECATED, setting - it has no effect. - items: - description: |- - deprecatedWebhookTokenAuthenticator holds the necessary configuration options for a remote token authenticator. - It's the same as WebhookTokenAuthenticator but it's missing the 'required' validation on KubeConfig field. - properties: - kubeConfig: - description: |- - kubeConfig contains kube config file data which describes how to access the remote webhook service. - For further details, see: - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - The namespace for this secret is determined by the point of use. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - featureGate: - description: FeatureGate holds cluster-wide information about - feature gates. - properties: - customNoUpgrade: - description: |- - customNoUpgrade allows the enabling or disabling of any feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, and PREVENTS UPGRADES. - Because of its nature, this setting cannot be validated. If you have any typos or accidentally apply invalid combinations - your cluster may fail in an unrecoverable way. featureSet must equal "CustomNoUpgrade" must be set to use this field. - nullable: true - properties: - disabled: - description: disabled is a list of all feature gates that - you want to force off - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - enabled: - description: enabled is a list of all feature gates that - you want to force on - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - type: object - featureSet: - description: |- - featureSet changes the list of features in the cluster. The default is empty. Be very careful adjusting this setting. - Turning on or off features may cause irreversible changes in your cluster which cannot be undone. - type: string - x-kubernetes-validations: - - message: CustomNoUpgrade may not be changed - rule: 'oldSelf == ''CustomNoUpgrade'' ? self == ''CustomNoUpgrade'' - : true' - - message: TechPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''TechPreviewNoUpgrade'' ? self == ''TechPreviewNoUpgrade'' - : true' - - message: DevPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''DevPreviewNoUpgrade'' ? self == ''DevPreviewNoUpgrade'' - : true' - type: object - image: - description: |- - Image governs policies related to imagestream imports and runtime configuration - for external registries. It allows cluster admins to configure which registries - OpenShift is allowed to import images from, extra CA trust bundles for external - registries, and policies to block or allow registry hostnames. - When exposing OpenShift's image registry to the public, this also lets cluster - admins specify the external hostname. - properties: - additionalTrustedCA: - description: |- - additionalTrustedCA is a reference to a ConfigMap containing additional CAs that - should be trusted during imagestream import, pod image pull, build image pull, and - imageregistry pullthrough. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - allowedRegistriesForImport: - description: |- - allowedRegistriesForImport limits the container image registries that normal users may import - images from. Set this list to the registries that you trust to contain valid Docker - images and that you want applications to be able to import from. Users with - permission to create Images or ImageStreamMappings via the API are not affected by - this policy - typically only administrators or system integrations will have those - permissions. - items: - description: |- - RegistryLocation contains a location of the registry specified by the registry domain - name. The domain name might include wildcards, like '*' or '??'. - properties: - domainName: - description: |- - domainName specifies a domain name for the registry - In case the registry use non-standard (80 or 443) port, the port should be included - in the domain name as well. - type: string - insecure: - description: |- - insecure indicates whether the registry is secure (https) or insecure (http) - By default (if not specified) the registry is assumed as secure. - type: boolean - type: object - type: array - externalRegistryHostnames: - description: |- - externalRegistryHostnames provides the hostnames for the default external image - registry. The external hostname should be set only when the image registry - is exposed externally. The first value is used in 'publicDockerImageRepository' - field in ImageStreams. The value must be in "hostname[:port]" format. - items: - type: string - type: array - registrySources: - description: |- - registrySources contains configuration that determines how the container runtime - should treat individual registries when accessing images for builds+pods. (e.g. - whether or not to allow insecure access). It does not contain configuration for the - internal cluster registry. - properties: - allowedRegistries: - description: |- - allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - blockedRegistries: - description: |- - blockedRegistries cannot be used for image pull and push actions. All other registries are permitted. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - containerRuntimeSearchRegistries: - description: |- - containerRuntimeSearchRegistries are registries that will be searched when pulling images that do not have fully qualified - domains in their pull specs. Registries will be searched in the order provided in the list. - Note: this search list only works with the container runtime, i.e CRI-O. Will NOT work with builds or imagestream imports. - format: hostname - items: - type: string - minItems: 1 - type: array - x-kubernetes-list-type: set - insecureRegistries: - description: insecureRegistries are registries which do - not have a valid TLS certificates or only support HTTP - connections. - items: - type: string - type: array - type: object - type: object - ingress: - description: |- - Ingress holds cluster-wide information about ingress, including the default ingress domain - used for routes. - properties: - appsDomain: - description: |- - appsDomain is an optional domain to use instead of the one specified - in the domain field when a Route is created without specifying an explicit - host. If appsDomain is nonempty, this value is used to generate default - host values for Route. Unlike domain, appsDomain may be modified after - installation. - This assumes a new ingresscontroller has been setup with a wildcard - certificate. - type: string - componentRoutes: - description: |- - componentRoutes is an optional list of routes that are managed by OpenShift components - that a cluster-admin is able to configure the hostname and serving certificate for. - The namespace and name of each route in this list should match an existing entry in the - status.componentRoutes list. - - - To determine the set of configurable Routes, look at namespace and name of entries in the - .status.componentRoutes list, where participating operators write the status of - configurable routes. - items: - description: ComponentRouteSpec allows for configuration - of a route's hostname and serving certificate. - properties: - hostname: - description: hostname is the hostname that should be - used by the route. - pattern: ^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$|^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$ - type: string - name: - description: |- - name is the logical name of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 256 - minLength: 1 - type: string - namespace: - description: |- - namespace is the namespace of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - servingCertKeyPairSecret: - description: |- - servingCertKeyPairSecret is a reference to a secret of type `kubernetes.io/tls` in the openshift-config namespace. - The serving cert/key pair must match and will be used by the operator to fulfill the intent of serving with this name. - If the custom hostname uses the default routing suffix of the cluster, - the Secret specification for a serving certificate will not be needed. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - hostname - - name - - namespace - type: object - type: array - x-kubernetes-list-map-keys: - - namespace - - name - x-kubernetes-list-type: map - domain: - description: |- - domain is used to generate a default host name for a route when the - route's host name is empty. The generated host name will follow this - pattern: "..". - - - It is also used as the default wildcard domain suffix for ingress. The - default ingresscontroller domain will follow this pattern: "*.". - - - Once set, changing domain is not currently supported. - type: string - loadBalancer: - description: |- - loadBalancer contains the load balancer details in general which are not only specific to the underlying infrastructure - provider of the current cluster and are required for Ingress Controller to work on OpenShift. - properties: - platform: - description: |- - platform holds configuration specific to the underlying - infrastructure provider for the ingress load balancers. - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - properties: - aws: - description: aws contains settings specific to the - Amazon Web Services infrastructure provider. - properties: - type: - description: |- - type allows user to set a load balancer type. - When this field is set the default ingresscontroller will get created using the specified LBType. - If this field is not set then the default ingress controller of LBType Classic will be created. - Valid values are: - - - * "Classic": A Classic Load Balancer that makes routing decisions at either - the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See - the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb - - - * "NLB": A Network Load Balancer that makes routing decisions at the - transport layer (TCP/SSL). See the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb - enum: - - NLB - - Classic - type: string - required: - - type - type: object - type: - description: |- - type is the underlying infrastructure provider for the cluster. - Allowed values are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", - "OpenStack", "VSphere", "oVirt", "KubeVirt", "EquinixMetal", "PowerVS", - "AlibabaCloud", "Nutanix" and "None". Individual components may not support all platforms, - and must handle unrecognized platforms as None if they do not support that platform. - enum: - - "" - - AWS - - Azure - - BareMetal - - GCP - - Libvirt - - OpenStack - - None - - VSphere - - oVirt - - IBMCloud - - KubeVirt - - EquinixMetal - - PowerVS - - AlibabaCloud - - Nutanix - - External - type: string - type: object - type: object - requiredHSTSPolicies: - description: |- - requiredHSTSPolicies specifies HSTS policies that are required to be set on newly created or updated routes - matching the domainPattern/s and namespaceSelector/s that are specified in the policy. - Each requiredHSTSPolicy must have at least a domainPattern and a maxAge to validate a route HSTS Policy route - annotation, and affect route admission. - - - A candidate route is checked for HSTS Policies if it has the HSTS Policy route annotation: - "haproxy.router.openshift.io/hsts_header" - E.g. haproxy.router.openshift.io/hsts_header: max-age=31536000;preload;includeSubDomains - - - - For each candidate route, if it matches a requiredHSTSPolicy domainPattern and optional namespaceSelector, - then the maxAge, preloadPolicy, and includeSubdomainsPolicy must be valid to be admitted. Otherwise, the route - is rejected. - - The first match, by domainPattern and optional namespaceSelector, in the ordering of the RequiredHSTSPolicies - determines the route's admission status. - - If the candidate route doesn't match any requiredHSTSPolicy domainPattern and optional namespaceSelector, - then it may use any HSTS Policy annotation. - - - The HSTS policy configuration may be changed after routes have already been created. An update to a previously - admitted route may then fail if the updated route does not conform to the updated HSTS policy configuration. - However, changing the HSTS policy configuration will not cause a route that is already admitted to stop working. - - - Note that if there are no RequiredHSTSPolicies, any HSTS Policy annotation on the route is valid. - items: - properties: - domainPatterns: - description: |- - domainPatterns is a list of domains for which the desired HSTS annotations are required. - If domainPatterns is specified and a route is created with a spec.host matching one of the domains, - the route must specify the HSTS Policy components described in the matching RequiredHSTSPolicy. - - - The use of wildcards is allowed like this: *.foo.com matches everything under foo.com. - foo.com only matches foo.com, so to cover foo.com and everything under it, you must specify *both*. - items: - type: string - minItems: 1 - type: array - includeSubDomainsPolicy: - description: |- - includeSubDomainsPolicy means the HSTS Policy should apply to any subdomains of the host's - domain name. Thus, for the host bar.foo.com, if includeSubDomainsPolicy was set to RequireIncludeSubDomains: - - the host app.bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host foo.com would NOT inherit the HSTS Policy of bar.foo.com - - the host def.foo.com would NOT inherit the HSTS Policy of bar.foo.com - enum: - - RequireIncludeSubDomains - - RequireNoIncludeSubDomains - - NoOpinion - type: string - maxAge: - description: |- - maxAge is the delta time range in seconds during which hosts are regarded as HSTS hosts. - If set to 0, it negates the effect, and hosts are removed as HSTS hosts. - If set to 0 and includeSubdomains is specified, all subdomains of the host are also removed as HSTS hosts. - maxAge is a time-to-live value, and if this policy is not refreshed on a client, the HSTS - policy will eventually expire on that client. - properties: - largestMaxAge: - description: |- - The largest allowed value (in seconds) of the RequiredHSTSPolicy max-age - This value can be left unspecified, in which case no upper limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - smallestMaxAge: - description: |- - The smallest allowed value (in seconds) of the RequiredHSTSPolicy max-age - Setting max-age=0 allows the deletion of an existing HSTS header from a host. This is a necessary - tool for administrators to quickly correct mistakes. - This value can be left unspecified, in which case no lower limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - type: object - namespaceSelector: - description: |- - namespaceSelector specifies a label selector such that the policy applies only to those routes that - are in namespaces with labels that match the selector, and are in one of the DomainPatterns. - Defaults to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - preloadPolicy: - description: |- - preloadPolicy directs the client to include hosts in its host preload list so that - it never needs to do an initial load to get the HSTS header (note that this is not defined - in RFC 6797 and is therefore client implementation-dependent). - enum: - - RequirePreload - - RequireNoPreload - - NoOpinion - type: string - required: - - domainPatterns - type: object - type: array - type: object - network: - description: |- - Network holds cluster-wide information about the network. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. - Please view network.spec for an explanation on what applies when configuring this resource. - TODO (csrwng): Add validation here to exclude changes that conflict with networking settings in the HostedCluster.Spec.Networking field. - properties: - clusterNetwork: - description: |- - IP address pool to use for pod IPs. - This field is immutable after installation. - items: - description: |- - ClusterNetworkEntry is a contiguous block of IP addresses from which pod IPs - are allocated. - properties: - cidr: - description: The complete block for pod IPs. - type: string - hostPrefix: - description: |- - The size (prefix) of block to allocate to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - minimum: 0 - type: integer - type: object - type: array - x-kubernetes-list-type: atomic - externalIP: - description: |- - externalIP defines configuration for controllers that - affect Service.ExternalIP. If nil, then ExternalIP is - not allowed to be set. - properties: - autoAssignCIDRs: - description: |- - autoAssignCIDRs is a list of CIDRs from which to automatically assign - Service.ExternalIP. These are assigned when the service is of type - LoadBalancer. In general, this is only useful for bare-metal clusters. - In Openshift 3.x, this was misleadingly called "IngressIPs". - Automatically assigned External IPs are not affected by any - ExternalIPPolicy rules. - Currently, only one entry may be provided. - items: - type: string - type: array - x-kubernetes-list-type: atomic - policy: - description: |- - policy is a set of restrictions applied to the ExternalIP field. - If nil or empty, then ExternalIP is not allowed to be set. - properties: - allowedCIDRs: - description: allowedCIDRs is the list of allowed CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - rejectedCIDRs: - description: |- - rejectedCIDRs is the list of disallowed CIDRs. These take precedence - over allowedCIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkDiagnostics: - description: |- - networkDiagnostics defines network diagnostics configuration. - - - Takes precedence over spec.disableNetworkDiagnostics in network.operator.openshift.io. - If networkDiagnostics is not specified or is empty, - and the spec.disableNetworkDiagnostics flag in network.operator.openshift.io is set to true, - the network diagnostics feature will be disabled. - properties: - mode: - description: |- - mode controls the network diagnostics mode - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is All. - enum: - - "" - - All - - Disabled - type: string - sourcePlacement: - description: |- - sourcePlacement controls the scheduling of network diagnostics source deployment - - - See NetworkDiagnosticsSourcePlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is an empty list. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - targetPlacement: - description: |- - targetPlacement controls the scheduling of network diagnostics target daemonset - - - See NetworkDiagnosticsTargetPlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `- operator: "Exists"` which means that all taints are tolerated. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkType: - description: |- - NetworkType is the plugin that is to be deployed (e.g. OpenShiftSDN). - This should match a value that the cluster-network-operator understands, - or else no networking will be installed. - Currently supported values are: - - OpenShiftSDN - This field is immutable after installation. - type: string - serviceNetwork: - description: |- - IP address pool for services. - Currently, we only support a single entry here. - This field is immutable after installation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - serviceNodePortRange: - description: |- - The port range allowed for Services of type NodePort. - If not specified, the default of 30000-32767 will be used. - Such Services without a NodePort specified will have one - automatically allocated from this range. - This parameter can be updated after the cluster is - installed. - pattern: ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])-([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ - type: string - type: object - oauth: - description: |- - OAuth holds cluster-wide information about OAuth. - It is used to configure the integrated OAuth server. - This configuration is only honored when the top level Authentication config has type set to IntegratedOAuth. - properties: - identityProviders: - description: |- - identityProviders is an ordered list of ways for a user to identify themselves. - When this list is empty, no identities are provisioned for users. - items: - description: IdentityProvider provides identities for users - authenticating using credentials - properties: - basicAuth: - description: basicAuth contains configuration options - for the BasicAuth IdP - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - github: - description: github enables user authentication using - GitHub credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - This can only be configured when hostname is set to a non-empty value. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostname: - description: |- - hostname is the optional domain (e.g. "mycompany.com") for use with a hosted instance of - GitHub Enterprise. - It must match the GitHub Enterprise settings value configured at /setup/settings#hostname. - type: string - organizations: - description: organizations optionally restricts - which organizations are allowed to log in - items: - type: string - type: array - teams: - description: teams optionally restricts which teams - are allowed to log in. Format is /. - items: - type: string - type: array - type: object - gitlab: - description: gitlab enables user authentication using - GitLab credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the oauth server base URL - type: string - type: object - google: - description: google enables user authentication using - Google credentials - properties: - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostedDomain: - description: hostedDomain is the optional Google - App domain (e.g. "mycompany.com") to restrict - logins to - type: string - type: object - htpasswd: - description: htpasswd enables user authentication using - an HTPasswd file to validate credentials - properties: - fileData: - description: |- - fileData is a required reference to a secret by name containing the data to use as the htpasswd file. - The key "htpasswd" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - If the specified htpasswd data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - keystone: - description: keystone enables user authentication using - keystone password credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - domainName: - description: domainName is required for keystone - v3 - type: string - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - ldap: - description: ldap enables user authentication using - LDAP credentials - properties: - attributes: - description: attributes maps LDAP attributes to - identities - properties: - email: - description: |- - email is the list of attributes whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - id: - description: |- - id is the list of attributes whose values should be used as the user ID. Required. - First non-empty attribute is used. At least one attribute is required. If none of the listed - attribute have a value, authentication fails. - LDAP standard identity attribute is "dn" - items: - type: string - type: array - name: - description: |- - name is the list of attributes whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - LDAP standard display name attribute is "cn" - items: - type: string - type: array - preferredUsername: - description: |- - preferredUsername is the list of attributes whose values should be used as the preferred username. - LDAP standard login attribute is "uid" - items: - type: string - type: array - type: object - bindDN: - description: bindDN is an optional DN to bind with - during the search phase. - type: string - bindPassword: - description: |- - bindPassword is an optional reference to a secret by name - containing a password to bind with during the search phase. - The key "bindPassword" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - insecure: - description: |- - insecure, if true, indicates the connection should not use TLS - WARNING: Should not be set to `true` with the URL scheme "ldaps://" as "ldaps://" URLs always - attempt to connect using TLS, even when `insecure` is set to `true` - When `true`, "ldap://" URLS connect insecurely. When `false`, "ldap://" URLs are upgraded to - a TLS connection using StartTLS as specified in https://tools.ietf.org/html/rfc2830. - type: boolean - url: - description: |- - url is an RFC 2255 URL which specifies the LDAP search parameters to use. - The syntax of the URL is: - ldap://host:port/basedn?attribute?scope?filter - type: string - type: object - mappingMethod: - description: |- - mappingMethod determines how identities from this provider are mapped to users - Defaults to "claim" - type: string - name: - description: |- - name is used to qualify the identities returned by this provider. - - It MUST be unique and not shared by any other identity provider used - - It MUST be a valid path segment: name cannot equal "." or ".." or contain "/" or "%" or ":" - Ref: https://godoc.org/github.com/openshift/origin/pkg/user/apis/user/validation#ValidateIdentityProviderName - type: string - openID: - description: openID enables user authentication using - OpenID credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - claims: - description: claims mappings - properties: - email: - description: |- - email is the list of claims whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - groups: - description: |- - groups is the list of claims value of which should be used to synchronize groups - from the OIDC provider to OpenShift for the user. - If multiple claims are specified, the first one with a non-empty value is used. - items: - description: |- - OpenIDClaim represents a claim retrieved from an OpenID provider's tokens or userInfo - responses - minLength: 1 - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: |- - name is the list of claims whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - preferredUsername: - description: |- - preferredUsername is the list of claims whose values should be used as the preferred username. - If unspecified, the preferred username is determined from the value of the sub claim - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - extraAuthorizeParameters: - additionalProperties: - type: string - description: extraAuthorizeParameters are any custom - parameters to add to the authorize request. - type: object - extraScopes: - description: extraScopes are any scopes to request - in addition to the standard "openid" scope. - items: - type: string - type: array - issuer: - description: |- - issuer is the URL that the OpenID Provider asserts as its Issuer Identifier. - It must use the https scheme with no query or fragment component. - type: string - type: object - requestHeader: - description: requestHeader enables user authentication - using request header credentials - properties: - ca: - description: |- - ca is a required reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - Specifically, it allows verification of incoming requests to prevent header spoofing. - The key "ca.crt" is used to locate the data. - If the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - challengeURL: - description: |- - challengeURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect WWW-Authenticate challenges will be - redirected here. - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when challenge is set to true. - type: string - clientCommonNames: - description: |- - clientCommonNames is an optional list of common names to require a match from. If empty, any - client certificate validated against the clientCA bundle is considered authoritative. - items: - type: string - type: array - emailHeaders: - description: emailHeaders is the set of headers - to check for the email address - items: - type: string - type: array - headers: - description: headers is the set of headers to check - for identity information - items: - type: string - type: array - loginURL: - description: |- - loginURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect interactive logins will be redirected here - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when login is set to true. - type: string - nameHeaders: - description: nameHeaders is the set of headers to - check for the display name - items: - type: string - type: array - preferredUsernameHeaders: - description: preferredUsernameHeaders is the set - of headers to check for the preferred username - items: - type: string - type: array - type: object - type: - description: type identifies the identity provider type - for this entry. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - templates: - description: templates allow you to customize pages like the - login page. - properties: - error: - description: |- - error is the name of a secret that specifies a go template to use to render error pages - during the authentication or grant flow. - The key "errors.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default error page is used. - If the specified template is not valid, the default error page is used. - If unspecified, the default error page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - login: - description: |- - login is the name of a secret that specifies a go template to use to render the login page. - The key "login.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default login page is used. - If the specified template is not valid, the default login page is used. - If unspecified, the default login page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - providerSelection: - description: |- - providerSelection is the name of a secret that specifies a go template to use to render - the provider selection page. - The key "providers.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default provider selection page is used. - If the specified template is not valid, the default provider selection page is used. - If unspecified, the default provider selection page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - tokenConfig: - description: tokenConfig contains options for authorization - and access tokens - properties: - accessTokenInactivityTimeout: - description: |- - accessTokenInactivityTimeout defines the token inactivity timeout - for tokens granted by any client. - The value represents the maximum amount of time that can occur between - consecutive uses of the token. Tokens become invalid if they are not - used within this temporal window. The user will need to acquire a new - token to regain access once a token times out. Takes valid time - duration string such as "5m", "1.5h" or "2h45m". The minimum allowed - value for duration is 300s (5 minutes). If the timeout is configured - per client, then that value takes precedence. If the timeout value is - not specified and the client does not override the value, then tokens - are valid until their lifetime. - - - WARNING: existing tokens' timeout will not be affected (lowered) by changing this value - type: string - accessTokenInactivityTimeoutSeconds: - description: 'accessTokenInactivityTimeoutSeconds - DEPRECATED: - setting this field has no effect.' - format: int32 - type: integer - accessTokenMaxAgeSeconds: - description: accessTokenMaxAgeSeconds defines the maximum - age of access tokens - format: int32 - type: integer - type: object - type: object - x-kubernetes-validations: - - message: spec.configuration.oauth.tokenConfig.accessTokenInactivityTimeout - minimum acceptable token timeout value is 300 seconds - rule: '!has(self.tokenConfig) || !has(self.tokenConfig.accessTokenInactivityTimeout) - || duration(self.tokenConfig.accessTokenInactivityTimeout).getSeconds() - >= 300' - operatorhub: - description: |- - OperatorHub specifies the configuration for the Operator Lifecycle Manager in the HostedCluster. This is only configured at deployment time but the controller are not reconcilling over it. - The OperatorHub configuration will be constantly reconciled if catalog placement is management, but only on cluster creation otherwise. - properties: - disableAllDefaultSources: - description: |- - disableAllDefaultSources allows you to disable all the default hub - sources. If this is true, a specific entry in sources can be used to - enable a default source. If this is false, a specific entry in - sources can be used to disable or enable a default source. - type: boolean - sources: - description: |- - sources is the list of default hub sources and their configuration. - If the list is empty, it implies that the default hub sources are - enabled on the cluster unless disableAllDefaultSources is true. - If disableAllDefaultSources is true and sources is not empty, - the configuration present in sources will take precedence. The list of - default hub sources and their current state will always be reflected in - the status block. - items: - description: HubSource is used to specify the hub source - and its configuration - properties: - disabled: - description: disabled is used to disable a default hub - source on cluster - type: boolean - name: - description: name is the name of one of the default - hub sources - maxLength: 253 - minLength: 1 - type: string - type: object - type: array - type: object - proxy: - description: Proxy holds cluster-wide information on how to configure - default proxies for the cluster. - properties: - httpProxy: - description: httpProxy is the URL of the proxy for HTTP requests. Empty - means unset and will not result in an env var. - type: string - httpsProxy: - description: httpsProxy is the URL of the proxy for HTTPS - requests. Empty means unset and will not result in an env - var. - type: string - noProxy: - description: |- - noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. - Empty means unset and will not result in an env var. - type: string - readinessEndpoints: - description: readinessEndpoints is a list of endpoints used - to verify readiness of the proxy. - items: - type: string - type: array - trustedCA: - description: |- - trustedCA is a reference to a ConfigMap containing a CA certificate bundle. - The trustedCA field should only be consumed by a proxy validator. The - validator is responsible for reading the certificate bundle from the required - key "ca-bundle.crt", merging it with the system default trust bundle, - and writing the merged trust bundle to a ConfigMap named "trusted-ca-bundle" - in the "openshift-config-managed" namespace. Clients that expect to make - proxy connections must use the trusted-ca-bundle for all HTTPS requests to - the proxy, and may use the trusted-ca-bundle for non-proxy HTTPS requests as - well. - - - The namespace for the ConfigMap referenced by trustedCA is - "openshift-config". Here is an example ConfigMap (in yaml): - - - apiVersion: v1 - kind: ConfigMap - metadata: - name: user-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - Custom CA certificate bundle. - -----END CERTIFICATE----- - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - type: object - scheduler: - description: |- - Scheduler holds cluster-wide config information to run the Kubernetes Scheduler - and influence its placement decisions. The canonical name for this config is `cluster`. - properties: - defaultNodeSelector: - description: |- - defaultNodeSelector helps set the cluster-wide default node selector to - restrict pod placement to specific nodes. This is applied to the pods - created in all namespaces and creates an intersection with any existing - nodeSelectors already set on a pod, additionally constraining that pod's selector. - For example, - defaultNodeSelector: "type=user-node,region=east" would set nodeSelector - field in pod spec to "type=user-node,region=east" to all pods created - in all namespaces. Namespaces having project-wide node selectors won't be - impacted even if this field is set. This adds an annotation section to - the namespace. - For example, if a new namespace is created with - node-selector='type=user-node,region=east', - the annotation openshift.io/node-selector: type=user-node,region=east - gets added to the project. When the openshift.io/node-selector annotation - is set on the project the value is used in preference to the value we are setting - for defaultNodeSelector field. - For instance, - openshift.io/node-selector: "type=user-node,region=west" means - that the default of "type=user-node,region=east" set in defaultNodeSelector - would not be applied. - type: string - mastersSchedulable: - description: |- - MastersSchedulable allows masters nodes to be schedulable. When this flag is - turned on, all the master nodes in the cluster will be made schedulable, - so that workload pods can run on them. The default value for this field is false, - meaning none of the master nodes are schedulable. - Important Note: Once the workload pods start running on the master nodes, - extreme care must be taken to ensure that cluster-critical control plane components - are not impacted. - Please turn on this field after doing due diligence. - type: boolean - policy: - description: |- - DEPRECATED: the scheduler Policy API has been deprecated and will be removed in a future release. - policy is a reference to a ConfigMap containing scheduler policy which has - user specified predicates and priorities. If this ConfigMap is not available - scheduler will default to use DefaultAlgorithmProvider. - The namespace for this configmap is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - profile: - description: |- - profile sets which scheduling profile should be set in order to configure scheduling - decisions for new pods. - - - Valid values are "LowNodeUtilization", "HighNodeUtilization", "NoScoring" - Defaults to "LowNodeUtilization" - enum: - - "" - - LowNodeUtilization - - HighNodeUtilization - - NoScoring - type: string - profileCustomizations: - description: profileCustomizations contains configuration - for modifying the default behavior of existing scheduler - profiles. - properties: - dynamicResourceAllocation: - description: |- - dynamicResourceAllocation allows to enable or disable dynamic resource allocation within the scheduler. - Dynamic resource allocation is an API for requesting and sharing resources between pods and containers inside a pod. - Third-party resource drivers are responsible for tracking and allocating resources. - Different kinds of resources support arbitrary parameters for defining requirements and initialization. - Valid values are Enabled, Disabled and omitted. - When omitted, this means no opinion and the platform is left to choose a reasonable default, - which is subject to change over time. - The current default is Disabled. - enum: - - "" - - Enabled - - Disabled - type: string - type: object - type: object - type: object - controlPlaneRelease: - description: |- - ControlPlaneRelease specifies the desired OCP release payload for - control plane components running on the management cluster. - Updating this field will trigger a rollout of the control plane. The - behavior of the rollout will be driven by the ControllerAvailabilityPolicy - and InfrastructureAvailabilityPolicy. - If not defined, Release is used - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - controllerAvailabilityPolicy: - default: HighlyAvailable - description: |- - ControllerAvailabilityPolicy specifies the availability policy applied to - critical control plane components. The default value is HighlyAvailable. - type: string - dns: - description: DNS specifies DNS configuration for the cluster. - properties: - baseDomain: - description: BaseDomain is the base domain of the cluster. - type: string - baseDomainPrefix: - description: |- - BaseDomainPrefix is the base domain prefix of the cluster. - defaults to clusterName if not set. Set it to "" if you don't want a prefix to be prepended to BaseDomain. - type: string - privateZoneID: - description: |- - PrivateZoneID is the Hosted Zone ID where all the DNS records that are only - available internally to the cluster exist. - type: string - publicZoneID: - description: |- - PublicZoneID is the Hosted Zone ID where all the DNS records that are - publicly accessible to the internet exist. - type: string - required: - - baseDomain - type: object - etcd: - default: - managed: - storage: - persistentVolume: - size: 8Gi - type: PersistentVolume - managementType: Managed - description: |- - Etcd specifies configuration for the control plane etcd cluster. The - default ManagementType is Managed. Once set, the ManagementType cannot be - changed. - properties: - managed: - description: Managed specifies the behavior of an etcd cluster - managed by HyperShift. - properties: - storage: - description: Storage specifies how etcd data is persisted. - properties: - persistentVolume: - description: |- - PersistentVolume is the configuration for PersistentVolume etcd storage. - With this implementation, a PersistentVolume will be allocated for every - etcd member (either 1 or 3 depending on the HostedCluster control plane - availability configuration). - properties: - size: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Size is the minimum size of the data - volume for each etcd member. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: Etcd PV storage size is immutable - rule: self == oldSelf - storageClassName: - description: |- - StorageClassName is the StorageClass of the data volume for each etcd member. - - - See https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. - type: string - type: object - restoreSnapshotURL: - description: |- - RestoreSnapshotURL allows an optional URL to be provided where - an etcd snapshot can be downloaded, for example a pre-signed URL - referencing a storage service. - This snapshot will be restored on initial startup, only when the etcd PV - is empty. - items: - type: string - type: array - x-kubernetes-validations: - - message: RestoreSnapshotURL shouldn't contain more than - 1 entry - rule: self.size() <= 1 - type: - description: Type is the kind of persistent storage implementation - to use for etcd. - enum: - - PersistentVolume - type: string - required: - - type - type: object - required: - - storage - type: object - managementType: - description: ManagementType defines how the etcd cluster is managed. - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: |- - Unmanaged specifies configuration which enables the control plane to - integrate with an eternally managed etcd cluster. - properties: - endpoint: - description: |- - Endpoint is the full etcd cluster client endpoint URL. For example: - - - https://etcd-client:2379 - - - If the URL uses an HTTPS scheme, the TLS field is required. - pattern: ^https:// - type: string - tls: - description: TLS specifies TLS configuration for HTTPS etcd - client endpoints. - properties: - clientSecret: - description: |- - ClientSecret refers to a secret for client mTLS authentication with the etcd cluster. It - may have the following key/value pairs: - - - etcd-client-ca.crt: Certificate Authority value - etcd-client.crt: Client certificate value - etcd-client.key: Client certificate key value - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - clientSecret - type: object - required: - - endpoint - - tls - type: object - required: - - managementType - type: object - fips: - description: |- - FIPS indicates whether this cluster's nodes will be running in FIPS mode. - If set to true, the control plane's ignition server will be configured to - expect that nodes joining the cluster will be FIPS-enabled. - type: boolean - imageContentSources: - description: |- - ImageContentSources specifies image mirrors that can be used by cluster - nodes to pull content. - items: - description: |- - ImageContentSource specifies image mirrors that can be used by cluster nodes - to pull content. For cluster workloads, if a container image registry host of - the pullspec matches Source then one of the Mirrors are substituted as hosts - in the pullspec and tried in order to fetch the image. - properties: - mirrors: - description: Mirrors are one or more repositories that may also - contain the same images. - items: - type: string - type: array - source: - description: |- - Source is the repository that users refer to, e.g. in image pull - specifications. - type: string - required: - - source - type: object - type: array - infraID: - description: |- - InfraID is a globally unique identifier for the cluster. This identifier - will be used to associate various cloud resources with the HostedCluster - and its associated NodePools. - type: string - infrastructureAvailabilityPolicy: - default: SingleReplica - description: |- - InfrastructureAvailabilityPolicy specifies the availability policy applied - to infrastructure services which run on cluster nodes. The default value is - SingleReplica. - type: string - issuerURL: - default: https://kubernetes.default.svc - description: |- - IssuerURL is an OIDC issuer URL which is used as the issuer in all - ServiceAccount tokens generated by the control plane API server. The - default value is kubernetes.default.svc, which only works for in-cluster - validation. - format: uri - type: string - networking: - default: - clusterNetwork: - - cidr: 10.132.0.0/14 - networkType: OVNKubernetes - serviceNetwork: - - cidr: 172.31.0.0/16 - description: Networking specifies network configuration for the cluster. - properties: - apiServer: - description: |- - APIServer contains advanced network settings for the API server that affect - how the APIServer is exposed inside a cluster node. - properties: - advertiseAddress: - description: |- - AdvertiseAddress is the address that nodes will use to talk to the API - server. This is an address associated with the loopback adapter of each - node. If not specified, the controller will take default values. - The default values will be set as 172.20.0.1 or fd00::1. - type: string - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is an allow list of CIDR blocks that can access the APIServer - If not specified, traffic is allowed from all addresses. - This depends on underlying support by the cloud provider for Service LoadBalancerSourceRanges - items: - pattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$ - type: string - type: array - port: - description: |- - Port is the port at which the APIServer is exposed inside a node. Other - pods using host networking cannot listen on this port. - If unset 6443 is used. - This is useful to choose a port other than the default one which might interfere with customer environments e.g. https://github.com/openshift/hypershift/pull/356. - Setting this to 443 is possible only for backward compatibility reasons and it's discouraged. - Doing so, it would result in the controller overriding the KAS endpoint in the guest cluster having a discrepancy with the KAS Pod and potentially causing temporarily network failures. - format: int32 - type: integer - type: object - clusterNetwork: - default: - - cidr: 10.132.0.0/14 - description: ClusterNetwork is the list of IP address pools for - pods. - items: - description: |- - ClusterNetworkEntry is a single IP address block for pod IP blocks. IP blocks - are allocated with size 2^HostSubnetLength. - properties: - cidr: - description: CIDR is the IP block address pool. - type: string - hostPrefix: - description: |- - HostPrefix is the prefix size to allocate to each node from the CIDR. - For example, 24 would allocate 2^8=256 adresses to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - type: integer - required: - - cidr - type: object - type: array - machineNetwork: - description: MachineNetwork is the list of IP address pools for - machines. - items: - description: MachineNetworkEntry is a single IP address block - for node IP blocks. - properties: - cidr: - description: CIDR is the IP block address pool for machines - within the cluster. - type: string - required: - - cidr - type: object - type: array - networkType: - default: OVNKubernetes - description: NetworkType specifies the SDN provider used for cluster - networking. - enum: - - OpenShiftSDN - - Calico - - OVNKubernetes - - Other - type: string - serviceNetwork: - default: - - cidr: 172.31.0.0/16 - description: |- - ServiceNetwork is the list of IP address pools for services. - NOTE: currently only one entry is supported. - items: - description: ServiceNetworkEntry is a single IP address block - for the service network. - properties: - cidr: - description: CIDR is the IP block address pool for services - within the cluster. - type: string - required: - - cidr - type: object - type: array - required: - - clusterNetwork - - networkType - type: object - nodeSelector: - additionalProperties: - type: string - description: NodeSelector when specified, must be true for the pods - managed by the HostedCluster to be scheduled. - type: object - olmCatalogPlacement: - default: management - description: |- - OLMCatalogPlacement specifies the placement of OLM catalog components. By default, - this is set to management and OLM catalog components are deployed onto the management - cluster. If set to guest, the OLM catalog components will be deployed onto the guest - cluster. - enum: - - management - - guest - type: string - x-kubernetes-validations: - - message: OLMCatalogPlacement is immutable - rule: self == oldSelf - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - Platform specifies the underlying infrastructure provider for the cluster - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies configuration for agent-based installations. - properties: - agentNamespace: - description: AgentNamespace is the namespace where to search - for Agents for this cluster - type: string - required: - - agentNamespace - type: object - aws: - description: AWS specifies configuration for clusters running - on Amazon Web Services. - properties: - additionalAllowedPrincipals: - description: |- - AdditionalAllowedPrincipals specifies a list of additional allowed principal ARNs - to be added to the hosted control plane's VPC Endpoint Service to enable additional - VPC Endpoint connection requests to be automatically accepted. - See https://docs.aws.amazon.com/vpc/latest/privatelink/configure-endpoint-service.html - for more details around VPC Endpoint Service allowed principals. - items: - type: string - type: array - cloudProviderConfig: - description: |- - CloudProviderConfig specifies AWS networking configuration for the control - plane. - This is mainly used for cloud provider controller config: - https://github.com/kubernetes/kubernetes/blob/f5be5052e3d0808abb904aebd3218fe4a5c2dd82/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L1347-L1364 - TODO(dan): should this be named AWSNetworkConfig? - properties: - subnet: - description: Subnet is the subnet to use for control plane - cloud resources. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify - an AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - vpc: - description: VPC is the VPC to use for control plane cloud - resources. - type: string - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - type: string - required: - - vpc - type: object - endpointAccess: - default: Public - description: |- - EndpointAccess specifies the publishing scope of cluster endpoints. The - default is Public. - enum: - - Public - - PublicAndPrivate - - Private - type: string - multiArch: - default: false - description: |- - MultiArch specifies whether the Hosted Cluster will be expected to support NodePools with different - CPU architectures, i.e., supporting arm64 NodePools and supporting amd64 NodePools on the same Hosted Cluster. - type: boolean - region: - description: |- - Region is the AWS region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot AMI for a given release. - type: string - resourceTags: - description: |- - ResourceTags is a list of additional tags to apply to AWS resources created - for the cluster. See - https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - rolesRef: - description: |- - RolesRef contains references to various AWS IAM roles required to enable - integrations such as OIDC. - properties: - controlPlaneOperatorARN: - description: "ControlPlaneOperatorARN is an ARN value - referencing a role appropriate for the Control Plane - Operator.\n\n\nThe following is an example of a valid - policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"ec2:CreateVpcEndpoint\",\n\t\t\t\t\"ec2:DescribeVpcEndpoints\",\n\t\t\t\t\"ec2:ModifyVpcEndpoint\",\n\t\t\t\t\"ec2:DeleteVpcEndpoints\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"route53:ListHostedZones\",\n\t\t\t\t\"ec2:CreateSecurityGroup\",\n\t\t\t\t\"ec2:AuthorizeSecurityGroupIngress\",\n\t\t\t\t\"ec2:AuthorizeSecurityGroupEgress\",\n\t\t\t\t\"ec2:DeleteSecurityGroup\",\n\t\t\t\t\"ec2:RevokeSecurityGroupIngress\",\n\t\t\t\t\"ec2:RevokeSecurityGroupEgress\",\n\t\t\t\t\"ec2:DescribeSecurityGroups\",\n\t\t\t\t\"ec2:DescribeVpcs\",\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\",\n\t\t\t\t\"route53:ListResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - \"arn:aws:route53:::%s\"\n\t\t}\n\t]\n}" - type: string - imageRegistryARN: - description: "ImageRegistryARN is an ARN value referencing - a role appropriate for the Image Registry Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"s3:CreateBucket\",\n\t\t\t\t\"s3:DeleteBucket\",\n\t\t\t\t\"s3:PutBucketTagging\",\n\t\t\t\t\"s3:GetBucketTagging\",\n\t\t\t\t\"s3:PutBucketPublicAccessBlock\",\n\t\t\t\t\"s3:GetBucketPublicAccessBlock\",\n\t\t\t\t\"s3:PutEncryptionConfiguration\",\n\t\t\t\t\"s3:GetEncryptionConfiguration\",\n\t\t\t\t\"s3:PutLifecycleConfiguration\",\n\t\t\t\t\"s3:GetLifecycleConfiguration\",\n\t\t\t\t\"s3:GetBucketLocation\",\n\t\t\t\t\"s3:ListBucket\",\n\t\t\t\t\"s3:GetObject\",\n\t\t\t\t\"s3:PutObject\",\n\t\t\t\t\"s3:DeleteObject\",\n\t\t\t\t\"s3:ListBucketMultipartUploads\",\n\t\t\t\t\"s3:AbortMultipartUpload\",\n\t\t\t\t\"s3:ListMultipartUploadParts\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - ingressARN: - description: "The referenced role must have a trust relationship - that allows it to be assumed via web identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ .ProviderName - }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nIngressARN - is an ARN value referencing a role appropriate for the - Ingress Operator.\n\n\nThe following is an example of - a valid policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"elasticloadbalancing:DescribeLoadBalancers\",\n\t\t\t\t\"tag:GetResources\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - [\n\t\t\t\t\"arn:aws:route53:::PUBLIC_ZONE_ID\",\n\t\t\t\t\"arn:aws:route53:::PRIVATE_ZONE_ID\"\n\t\t\t]\n\t\t}\n\t]\n}" - type: string - kubeCloudControllerARN: - description: |- - KubeCloudControllerARN is an ARN value referencing a role appropriate for the KCM/KCC. - Source: https://cloud-provider-aws.sigs.k8s.io/prerequisites/#iam-policies - - - The following is an example of a valid policy document: - - - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingGroups", - "autoscaling:DescribeLaunchConfigurations", - "autoscaling:DescribeTags", - "ec2:DescribeAvailabilityZones", - "ec2:DescribeInstances", - "ec2:DescribeImages", - "ec2:DescribeRegions", - "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVolumes", - "ec2:CreateSecurityGroup", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:ModifyInstanceAttribute", - "ec2:ModifyVolume", - "ec2:AttachVolume", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateRoute", - "ec2:DeleteRoute", - "ec2:DeleteSecurityGroup", - "ec2:DeleteVolume", - "ec2:DetachVolume", - "ec2:RevokeSecurityGroupIngress", - "ec2:DescribeVpcs", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:AttachLoadBalancerToSubnets", - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", - "elasticloadbalancing:CreateLoadBalancer", - "elasticloadbalancing:CreateLoadBalancerPolicy", - "elasticloadbalancing:CreateLoadBalancerListeners", - "elasticloadbalancing:ConfigureHealthCheck", - "elasticloadbalancing:DeleteLoadBalancer", - "elasticloadbalancing:DeleteLoadBalancerListeners", - "elasticloadbalancing:DescribeLoadBalancers", - "elasticloadbalancing:DescribeLoadBalancerAttributes", - "elasticloadbalancing:DetachLoadBalancerFromSubnets", - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:ModifyLoadBalancerAttributes", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:CreateListener", - "elasticloadbalancing:CreateTargetGroup", - "elasticloadbalancing:DeleteListener", - "elasticloadbalancing:DeleteTargetGroup", - "elasticloadbalancing:DeregisterTargets", - "elasticloadbalancing:DescribeListeners", - "elasticloadbalancing:DescribeLoadBalancerPolicies", - "elasticloadbalancing:DescribeTargetGroups", - "elasticloadbalancing:DescribeTargetHealth", - "elasticloadbalancing:ModifyListener", - "elasticloadbalancing:ModifyTargetGroup", - "elasticloadbalancing:RegisterTargets", - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener", - "iam:CreateServiceLinkedRole", - "kms:DescribeKey" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ] - } - type: string - networkARN: - description: "NetworkARN is an ARN value referencing a - role appropriate for the Network Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInstanceStatus\",\n \"ec2:DescribeInstanceTypes\",\n - \ \"ec2:UnassignPrivateIpAddresses\",\n \"ec2:AssignPrivateIpAddresses\",\n - \ \"ec2:UnassignIpv6Addresses\",\n \"ec2:AssignIpv6Addresses\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeNetworkInterfaces\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - nodePoolManagementARN: - description: "NodePoolManagementARN is an ARN value referencing - a role appropriate for the CAPI Controller.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n - \ \"Version\": \"2012-10-17\",\n \"Statement\": [\n - \ {\n \"Action\": [\n \"ec2:AssociateRouteTable\",\n - \ \"ec2:AttachInternetGateway\",\n \"ec2:AuthorizeSecurityGroupIngress\",\n - \ \"ec2:CreateInternetGateway\",\n \"ec2:CreateNatGateway\",\n - \ \"ec2:CreateRoute\",\n \"ec2:CreateRouteTable\",\n - \ \"ec2:CreateSecurityGroup\",\n \"ec2:CreateSubnet\",\n - \ \"ec2:CreateTags\",\n \"ec2:DeleteInternetGateway\",\n - \ \"ec2:DeleteNatGateway\",\n \"ec2:DeleteRouteTable\",\n - \ \"ec2:DeleteSecurityGroup\",\n \"ec2:DeleteSubnet\",\n - \ \"ec2:DeleteTags\",\n \"ec2:DescribeAccountAttributes\",\n - \ \"ec2:DescribeAddresses\",\n \"ec2:DescribeAvailabilityZones\",\n - \ \"ec2:DescribeImages\",\n \"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInternetGateways\",\n \"ec2:DescribeNatGateways\",\n - \ \"ec2:DescribeNetworkInterfaces\",\n \"ec2:DescribeNetworkInterfaceAttribute\",\n - \ \"ec2:DescribeRouteTables\",\n \"ec2:DescribeSecurityGroups\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeVpcs\",\n - \ \"ec2:DescribeVpcAttribute\",\n \"ec2:DescribeVolumes\",\n - \ \"ec2:DetachInternetGateway\",\n \"ec2:DisassociateRouteTable\",\n - \ \"ec2:DisassociateAddress\",\n \"ec2:ModifyInstanceAttribute\",\n - \ \"ec2:ModifyNetworkInterfaceAttribute\",\n \"ec2:ModifySubnetAttribute\",\n - \ \"ec2:RevokeSecurityGroupIngress\",\n \"ec2:RunInstances\",\n - \ \"ec2:TerminateInstances\",\n \"tag:GetResources\",\n - \ \"ec2:CreateLaunchTemplate\",\n \"ec2:CreateLaunchTemplateVersion\",\n - \ \"ec2:DescribeLaunchTemplates\",\n \"ec2:DescribeLaunchTemplateVersions\",\n - \ \"ec2:DeleteLaunchTemplate\",\n \"ec2:DeleteLaunchTemplateVersions\"\n - \ ],\n \"Resource\": [\n \"*\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n {\n \"Condition\": - {\n \"StringLike\": {\n \"iam:AWSServiceName\": - \"elasticloadbalancing.amazonaws.com\"\n }\n },\n - \ \"Action\": [\n \"iam:CreateServiceLinkedRole\"\n - \ ],\n \"Resource\": [\n \"arn:*:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing\"\n - \ ],\n \"Effect\": \"Allow\"\n },\n {\n \"Action\": - [\n \"iam:PassRole\"\n ],\n \"Resource\": - [\n \"arn:*:iam::*:role/*-worker-role\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n\t {\n\t \t\"Effect\": - \"Allow\",\n\t \t\"Action\": [\n\t \t\t\"kms:Decrypt\",\n\t - \ \t\t\"kms:ReEncrypt\",\n\t \t\t\"kms:GenerateDataKeyWithoutPlainText\",\n\t - \ \t\t\"kms:DescribeKey\"\n\t \t],\n\t \t\"Resource\": - \"*\"\n\t },\n\t {\n\t \t\"Effect\": \"Allow\",\n\t - \ \t\"Action\": [\n\t \t\t\"kms:CreateGrant\"\n\t \t],\n\t - \ \t\"Resource\": \"*\",\n\t \t\"Condition\": {\n\t - \ \t\t\"Bool\": {\n\t \t\t\t\"kms:GrantIsForAWSResource\": - true\n\t \t\t}\n\t \t}\n\t }\n ]\n}" - type: string - storageARN: - description: "StorageARN is an ARN value referencing a - role appropriate for the Storage Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:AttachVolume\",\n\t\t\t\t\"ec2:CreateSnapshot\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"ec2:CreateVolume\",\n\t\t\t\t\"ec2:DeleteSnapshot\",\n\t\t\t\t\"ec2:DeleteTags\",\n\t\t\t\t\"ec2:DeleteVolume\",\n\t\t\t\t\"ec2:DescribeInstances\",\n\t\t\t\t\"ec2:DescribeSnapshots\",\n\t\t\t\t\"ec2:DescribeTags\",\n\t\t\t\t\"ec2:DescribeVolumes\",\n\t\t\t\t\"ec2:DescribeVolumesModifications\",\n\t\t\t\t\"ec2:DetachVolume\",\n\t\t\t\t\"ec2:ModifyVolume\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - required: - - controlPlaneOperatorARN - - imageRegistryARN - - ingressARN - - kubeCloudControllerARN - - networkARN - - nodePoolManagementARN - - storageARN - type: object - serviceEndpoints: - description: |- - ServiceEndpoints specifies optional custom endpoints which will override - the default service endpoint of specific AWS Services. - - - There must be only one ServiceEndpoint for a given service name. - items: - description: |- - AWSServiceEndpoint stores the configuration for services to - override existing defaults of AWS Services. - properties: - name: - description: |- - Name is the name of the AWS service. - This must be provided and cannot be empty. - type: string - url: - description: |- - URL is fully qualified URI with scheme https, that overrides the default generated - endpoint for a client. - This must be provided and cannot be empty. - pattern: ^https:// - type: string - required: - - name - - url - type: object - type: array - required: - - region - - rolesRef - type: object - azure: - description: Azure defines azure specific settings - properties: - cloud: - default: AzurePublicCloud - description: 'Cloud is the cloud environment identifier, valid - values could be found here: https://github.com/Azure/go-autorest/blob/4c0e21ca2bbb3251fe7853e6f9df6397f53dd419/autorest/azure/environments.go#L33' - enum: - - AzurePublicCloud - - AzureUSGovernmentCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureStackCloud - type: string - credentials: - description: |- - Credentials is the object containing existing Azure credentials needed for creating and managing cloud - infrastructure resources. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - location: - description: |- - Location is the Azure region in where all the cloud infrastructure resources will be created. - - - Example: eastus - type: string - x-kubernetes-validations: - - message: Location is immutable - rule: self == oldSelf - resourceGroup: - default: default - description: |- - ResourceGroupName is the name of an existing resource group where all cloud resources created by the Hosted - Cluster are to be placed. The resource group is expected to exist under the same subscription as SubscriptionID. - - - In ARO HCP, this will be the managed resource group where customer cloud resources will be created. - - - Resource group naming requirements can be found here: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ResourceGroup.Name/. - - - Example: if your resource group ID is /subscriptions//resourceGroups/, your - ResourceGroupName is . - pattern: ^[a-zA-Z0-9_()\-\.]{1,89}[a-zA-Z0-9_()\-]$ - type: string - x-kubernetes-validations: - - message: ResourceGroupName is immutable - rule: self == oldSelf - securityGroupID: - description: |- - SecurityGroupID is the ID of an existing security group on the SubnetID. This field is provided as part of the - configuration for the Azure cloud provider, aka Azure cloud controller manager (CCM). This security group is - expected to exist under the same subscription as SubscriptionID. - type: string - x-kubernetes-validations: - - message: SecurityGroupID is immutable - rule: self == oldSelf - subnetID: - description: |- - SubnetID is the subnet ID of an existing subnet where the load balancer for node egress will be created. This - subnet is expected to be a subnet within the VNET specified in VnetID. This subnet is expected to exist under the - same subscription as SubscriptionID. - - - In ARO HCP, managed services will create the aforementioned load balancer in ResourceGroupName. - type: string - x-kubernetes-validations: - - message: SubnetID is immutable - rule: self == oldSelf - subscriptionID: - description: SubscriptionID is a unique identifier for an - Azure subscription used to manage resources. - type: string - x-kubernetes-validations: - - message: SubscriptionID is immutable - rule: self == oldSelf - vnetID: - description: |- - VnetID is the ID of an existing VNET to use in creating VMs. The VNET can exist in a different resource group - other than the one specified in ResourceGroupName, but it must exist under the same subscription as - SubscriptionID. - - - In ARO HCP, this will be the ID of the customer provided VNET. - - - Example: /subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/ - type: string - x-kubernetes-validations: - - message: VnetID is immutable - rule: self == oldSelf - required: - - credentials - - location - - resourceGroup - - subnetID - - subscriptionID - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: KubeVirt defines KubeVirt specific settings for cluster - components. - properties: - baseDomainPassthrough: - description: |- - BaseDomainPassthrough toggles whether or not an automatically - generated base domain for the guest cluster should be used that - is a subdomain of the management cluster's *.apps DNS. - - - For the KubeVirt platform, the basedomain can be autogenerated using - the *.apps domain of the management/infra hosting cluster - This makes the guest cluster's base domain a subdomain of the - hypershift infra/mgmt cluster's base domain. - - - Example: - Infra/Mgmt cluster's DNS - Base: example.com - Cluster: mgmt-cluster.example.com - Apps: *.apps.mgmt-cluster.example.com - KubeVirt Guest cluster's DNS - Base: apps.mgmt-cluster.example.com - Cluster: guest.apps.mgmt-cluster.example.com - Apps: *.apps.guest.apps.mgmt-cluster.example.com - - - This is possible using OCP wildcard routes - type: boolean - x-kubernetes-validations: - - message: baseDomainPassthrough is immutable - rule: self == oldSelf - credentials: - description: |- - Credentials defines the client credentials used when creating KubeVirt virtual machines. - Defining credentials is only necessary when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - generateID: - description: |- - GenerateID is used to uniquely apply a name suffix to resources associated with - kubevirt infrastructure resources - maxLength: 11 - type: string - x-kubernetes-validations: - - message: Kubevirt GenerateID is immutable once set - rule: self == oldSelf - storageDriver: - description: |- - StorageDriver defines how the KubeVirt CSI driver exposes StorageClasses on - the infra cluster (hosting the VMs) to the guest cluster. - properties: - manual: - description: |- - Manual is used to explicilty define how the infra storageclasses are - mapped to guest storageclasses - properties: - storageClassMapping: - description: |- - StorageClassMapping maps StorageClasses on the infra cluster hosting - the KubeVirt VMs to StorageClasses that are made available within the - Guest Cluster. - - - NOTE: It is possible that not all capablities of an infra cluster's - storageclass will be present for the corresponding guest clusters storageclass. - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestStorageClassName: - description: |- - GuestStorageClassName is the name that the corresponding storageclass will - be called within the guest cluster - type: string - infraStorageClassName: - description: |- - InfraStorageClassName is the name of the infra cluster storage class that - will be exposed to the guest. - type: string - required: - - guestStorageClassName - - infraStorageClassName - type: object - type: array - x-kubernetes-validations: - - message: storageClassMapping is immutable - rule: self == oldSelf - volumeSnapshotClassMapping: - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestVolumeSnapshotClassName: - description: |- - GuestVolumeSnapshotClassName is the name that the corresponding volumeSnapshotClass will - be called within the guest cluster - type: string - infraVolumeSnapshotClassName: - description: |- - InfraStorageClassName is the name of the infra cluster volume snapshot class that - will be exposed to the guest. - type: string - required: - - guestVolumeSnapshotClassName - - infraVolumeSnapshotClassName - type: object - type: array - x-kubernetes-validations: - - message: volumeSnapshotClassMapping is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver.Manual is immutable - rule: self == oldSelf - type: - default: Default - description: Type represents the type of kubevirt csi - driver configuration to use - enum: - - None - - Default - - Manual - type: string - x-kubernetes-validations: - - message: storageDriver.Type is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: Kubevirt GenerateID is required once set - rule: '!has(oldSelf.generateID) || has(self.generateID)' - openstack: - description: OpenStack specifies configuration for clusters running - on OpenStack. - properties: - disableExternalNetwork: - description: |- - DisableExternalNetwork specifies whether or not to attempt to connect the cluster - to an external network. This allows for the creation of clusters when connecting - to an external network is not possible or desirable, e.g. if using a provider network. - type: boolean - externalNetwork: - description: |- - ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. - This option is ignored if DisableExternalNetwork is set to true. - - - If ExternalNetwork is defined it must refer to exactly one external network. - - - If ExternalNetwork is not defined or is empty the controller will use any - existing external network as long as there is only one. It is an - error if ExternalNetwork is not defined and there are multiple - external networks unless DisableExternalNetwork is also set. - - - If ExternalNetwork is not defined and there are no external networks - the controller will proceed as though DisableExternalNetwork was set. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - network to filter by. - type: string - name: - description: Name is the name of the network to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the network - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling the hosted cluster. - properties: - cloudName: - description: CloudName specifies the name of the entry - in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - ingressFloatingIP: - description: |- - IngressFloatingIP is an available floating IP in your OpenStack cluster that will - be associated with the OpenShift ingress port. - type: string - managedSubnets: - description: |- - ManagedSubnets describe the OpenStack Subnet to be created. Cluster actuator will create a network, - and a subnet with the defined DNSNameservers, AllocationPools and the CIDR defined in the HostedCluster - MachineNetwork, and a router connected to the subnet. Currently only one IPv4 - subnet is supported. - items: - properties: - allocationPools: - description: |- - AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. - If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from - outside of these ranges manually. - items: - properties: - end: - description: End represents the end of the AlloctionPool, - that is the highest IP of the pool. - type: string - start: - description: Start represents the start of the - AllocationPool, that is the lowest IP of the - pool. - type: string - required: - - end - - start - type: object - type: array - dnsNameservers: - description: |- - DNSNameservers holds a list of DNS server addresses that will be provided when creating - the subnet. These addresses need to have the same IP version as CIDR. - items: - type: string - type: array - type: object - maxItems: 1 - type: array - x-kubernetes-list-type: atomic - network: - description: |- - Network specifies an existing network to use if no ManagedSubnets - are specified. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - network to filter by. - type: string - name: - description: Name is the name of the network to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the network - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - networkMTU: - description: |- - NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. - This value will be used only if the Cluster actuator creates the network. - If left empty, the network will have the default MTU defined in Openstack network service. - To use this field, the Openstack installation requires the net-mtu neutron API extension. - type: integer - router: - description: |- - Router specifies an existing router to be used if ManagedSubnets are - specified. If specified, no new router will be created. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - router. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - router to filter by. - type: string - name: - description: Name is the name of the router to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the router - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the router to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - subnets: - description: |- - Subnets specifies existing subnets to use if not ManagedSubnets are - specified. All subnets must be in the network specified by Network. - There can be zero, one, or two subnets. If no subnets are specified, - all subnets in Network will be used. If 2 subnets are specified, one - must be IPv4 and the other IPv6. - items: - description: SubnetParam specifies an OpenStack subnet to - use. It may be specified by either ID or filter, but not - both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the - subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - description: CIDR is the CIDR of the subnet to filter - by. - type: string - description: - description: Description is the description of the - subnet to filter by. - type: string - gatewayIP: - description: GatewayIP is the gateway IP of the - subnet to filter by. - type: string - ipVersion: - description: IPVersion is the IP version of the - subnet to filter by. - type: integer - ipv6AddressMode: - description: IPv6AddressMode is the IPv6 address - mode of the subnet to filter by. - type: string - ipv6RAMode: - description: IPv6RAMode is the IPv6 RA mode of the - subnet to filter by. - type: string - name: - description: Name is the name of the subnet to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the - subnet to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not - be validated. - format: uuid - type: string - type: object - maxItems: 2 - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags to set on all resources in cluster which - support tags - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - identityRef - type: object - powervs: - description: |- - PowerVS specifies configuration for clusters running on IBMCloud Power VS Service. - This field is immutable. Once set, It can't be changed. - properties: - accountID: - description: |- - AccountID is the IBMCloud account id. - This field is immutable. Once set, It can't be changed. - type: string - cisInstanceCRN: - description: |- - CISInstanceCRN is the IBMCloud CIS Service Instance's Cloud Resource Name - This field is immutable. Once set, It can't be changed. - pattern: '^crn:' - type: string - imageRegistryOperatorCloudCreds: - description: |- - ImageRegistryOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for image registry operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - ingressOperatorCloudCreds: - description: |- - IngressOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for ingress operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeCloudControllerCreds: - description: |- - KubeCloudControllerCreds is a reference to a secret containing cloud - credentials with permissions matching the cloud controller policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "cloud controller policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - nodePoolManagementCreds: - description: |- - NodePoolManagementCreds is a reference to a secret containing cloud - credentials with permissions matching the node pool management policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "node pool management policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the IBMCloud region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot image for a given release. - This field is immutable. Once set, It can't be changed. - type: string - resourceGroup: - description: |- - ResourceGroup is the IBMCloud Resource Group in which the cluster resides. - This field is immutable. Once set, It can't be changed. - type: string - serviceInstanceID: - description: |- - ServiceInstance is the reference to the Power VS service on which the server instance(VM) will be created. - Power VS service is a container for all Power VS instances at a specific geographic region. - serviceInstance can be created via IBM Cloud catalog or CLI. - ServiceInstanceID is the unique identifier that can be obtained from IBM Cloud UI or IBM Cloud cli. - - - More detail about Power VS service instance. - https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server - - - This field is immutable. Once set, It can't be changed. - type: string - storageOperatorCloudCreds: - description: |- - StorageOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for storage operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - subnet: - description: |- - Subnet is the subnet to use for control plane cloud resources. - This field is immutable. Once set, It can't be changed. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - vpc: - description: |- - VPC specifies IBM Cloud PowerVS Load Balancing configuration for the control - plane. - This field is immutable. Once set, It can't be changed. - properties: - name: - description: |- - Name for VPC to used for all the service load balancer. - This field is immutable. Once set, It can't be changed. - type: string - region: - description: |- - Region is the IBMCloud region in which VPC gets created, this VPC used for all the ingress traffic - into the OCP cluster. - This field is immutable. Once set, It can't be changed. - type: string - subnet: - description: |- - Subnet is the subnet to use for load balancer. - This field is immutable. Once set, It can't be changed. - type: string - zone: - description: |- - Zone is the availability zone where load balancer cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - name - - region - type: object - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - accountID - - cisInstanceCRN - - imageRegistryOperatorCloudCreds - - ingressOperatorCloudCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - resourceGroup - - serviceInstanceID - - storageOperatorCloudCreds - - subnet - - vpc - - zone - type: object - type: - description: Type is the type of infrastructure provider for the - cluster. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - - OpenStack - type: string - required: - - type - type: object - pullSecret: - description: |- - PullSecret references a pull secret to be injected into the container - runtime of all cluster nodes. The secret must have a key named - ".dockerconfigjson" whose value is the pull secret JSON. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - release: - description: |- - Release specifies the desired OCP release payload for the hosted cluster. - - - Updating this field will trigger a rollout of the control plane. The - behavior of the rollout will be driven by the ControllerAvailabilityPolicy - and InfrastructureAvailabilityPolicy. - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - secretEncryption: - description: |- - SecretEncryption specifies a Kubernetes secret encryption strategy for the - control plane. - properties: - aescbc: - description: AESCBC defines metadata about the AESCBC secret encryption - strategy - properties: - activeKey: - description: ActiveKey defines the active key used to encrypt - new secrets - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - activeKey - type: object - kms: - description: KMS defines metadata about the kms secret encryption - strategy - properties: - aws: - description: AWS defines metadata about the configuration - of the AWS KMS Secret Encryption provider - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - auth: - description: Auth defines metadata about the management - of credentials used to interact with AWS KMS - properties: - awsKms: - description: "The referenced role must have a trust - relationship that allows it to be assumed via web - identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ - .ProviderName }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nAWSKMSARN - is an ARN value referencing a role appropriate for - managing the auth via the AWS KMS key.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n \t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"kms:Encrypt\",\n\t\t\t\t\"kms:Decrypt\",\n\t\t\t\t\"kms:ReEncrypt*\",\n\t\t\t\t\"kms:GenerateDataKey*\",\n\t\t\t\t\"kms:DescribeKey\"\n\t\t\t],\n\t\t\t\"Resource\": - %q\n\t\t}\n\t]\n}" - type: string - required: - - awsKms - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - region: - description: Region contains the AWS region - type: string - required: - - activeKey - - auth - - region - type: object - azure: - description: Azure defines metadata about the configuration - of the Azure KMS Secret Encryption provider using Azure - key vault - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - required: - - activeKey - type: object - ibmcloud: - description: IBMCloud defines metadata for the IBM Cloud KMS - encryption strategy - properties: - auth: - description: Auth defines metadata for how authentication - is done with IBM Cloud KMS - properties: - managed: - description: |- - Managed defines metadata around the service to service authentication strategy for the IBM Cloud - KMS system (all provider managed). - type: object - type: - description: Type defines the IBM Cloud KMS authentication - strategy - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: Unmanaged defines the auth metadata the - customer provides to interact with IBM Cloud KMS - properties: - credentials: - description: |- - Credentials should reference a secret with a key field of IBMCloudIAMAPIKeySecretKey that contains a apikey to - call IBM Cloud KMS APIs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - credentials - type: object - required: - - type - type: object - keyList: - description: KeyList defines the list of keys used for - data encryption - items: - description: IBMCloudKMSKeyEntry defines metadata for - an IBM Cloud KMS encryption key - properties: - correlationID: - description: CorrelationID is an identifier used - to track all api call usage from hypershift - type: string - crkID: - description: CRKID is the customer rook key id - type: string - instanceID: - description: InstanceID is the id for the key protect - instance - type: string - keyVersion: - description: |- - KeyVersion is a unique number associated with the key. The number increments whenever a new - key is enabled for data encryption. - type: integer - url: - description: URL is the url to call key protect - apis over - pattern: ^https:// - type: string - required: - - correlationID - - crkID - - instanceID - - keyVersion - - url - type: object - type: array - region: - description: Region is the IBM Cloud region - type: string - required: - - auth - - keyList - - region - type: object - provider: - description: Provider defines the KMS provider - enum: - - IBMCloud - - AWS - - Azure - type: string - required: - - provider - type: object - type: - description: Type defines the type of kube secret encryption being - used - enum: - - kms - - aescbc - type: string - required: - - type - type: object - serviceAccountSigningKey: - description: |- - ServiceAccountSigningKey is a reference to a secret containing the private key - used by the service account token issuer. The secret is expected to contain - a single key named "key". If not specified, a service account signing key will - be generated automatically for the cluster. When specifying a service account - signing key, a IssuerURL must also be specified. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - services: - description: |- - Services specifies how individual control plane services are published from - the hosting cluster of the control plane. - - - If a given service is not present in this list, it will be exposed publicly - by default. - items: - description: |- - ServicePublishingStrategyMapping specifies how individual control plane - services are published from the hosting cluster of a control plane. - properties: - service: - description: Service identifies the type of service being published. - enum: - - APIServer - - OAuthServer - - OIDC - - Konnectivity - - Ignition - - OVNSbDb - type: string - servicePublishingStrategy: - description: ServicePublishingStrategy specifies how to publish - Service. - properties: - loadBalancer: - description: LoadBalancer configures exposing a service - using a LoadBalancer. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the LoadBalancer. - type: string - type: object - nodePort: - description: NodePort configures exposing a service using - a NodePort. - properties: - address: - description: Address is the host/ip that the NodePort - service is exposed over. - type: string - port: - description: |- - Port is the port of the NodePort service. If <=0, the port is dynamically - assigned when the service is created. - format: int32 - type: integer - required: - - address - type: object - route: - description: Route configures exposing a service using a - Route. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the Route. - type: string - type: object - type: - description: Type is the publishing strategy used for the - service. - enum: - - LoadBalancer - - NodePort - - Route - - None - - S3 - type: string - required: - - type - type: object - required: - - service - - servicePublishingStrategy - type: object - type: array - sshKey: - description: |- - SSHKey references an SSH key to be injected into all cluster node sshd - servers. The secret must have a single key "id_rsa.pub" whose value is the - public part of an SSH key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - tolerations: - description: Tolerations when specified, define what custome tolerations - are added to the hcp pods. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - updateService: - description: |- - updateService may be used to specify the preferred upstream update service. - By default it will use the appropriate update service for the cluster and region. - type: string - required: - - networking - - platform - - pullSecret - - release - - services - - sshKey - type: object - x-kubernetes-validations: - - message: Services is immutable. Changes might result in unpredictable - and disruptive behavior. - rule: 'self.platform.type != "IBMCloud" ? self.services == oldSelf.services - : true' - - message: Azure platform requires APIServer Route service with a hostname - to be defined - rule: 'self.platform.type == "Azure" ? self.services.exists(s, s.service - == "APIServer" && s.servicePublishingStrategy.type == "Route" && s.servicePublishingStrategy.route.hostname - != "") : true' - - message: Azure platform requires OAuthServer Route service with a hostname - to be defined - rule: 'self.platform.type == "Azure" ? self.services.exists(s, s.service - == "OAuthServer" && s.servicePublishingStrategy.type == "Route" && - s.servicePublishingStrategy.route.hostname != "") : true' - - message: Azure platform requires Konnectivity Route service with a hostname - to be defined - rule: 'self.platform.type == "Azure" ? self.services.exists(s, s.service - == "Konnectivity" && s.servicePublishingStrategy.type == "Route" && - s.servicePublishingStrategy.route.hostname != "") : true' - - message: Azure platform requires Ignition Route service with a hostname - to be defined - rule: 'self.platform.type == "Azure" ? self.services.exists(s, s.service - == "Ignition" && s.servicePublishingStrategy.type == "Route" && s.servicePublishingStrategy.route.hostname - != "") : true' - status: - description: Status is the latest observed status of the HostedCluster. - properties: - conditions: - description: |- - Conditions represents the latest available observations of a control - plane's current state. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint contains the endpoint information by which - external clients can access the control plane. This is populated - after the infrastructure is ready. - properties: - host: - description: Host is the hostname on which the API server is serving. - type: string - port: - description: Port is the port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - ignitionEndpoint: - description: |- - IgnitionEndpoint is the endpoint injected in the ign config userdata. - It exposes the config for instances to become kubernetes nodes. - type: string - kubeadminPassword: - description: |- - KubeadminPassword is a reference to the secret that contains the initial - kubeadmin user password for the guest cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeconfig: - description: |- - KubeConfig is a reference to the secret containing the default kubeconfig - for the cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - oauthCallbackURLTemplate: - description: |- - OAuthCallbackURLTemplate contains a template for the URL to use as a callback - for identity providers. The [identity-provider-name] placeholder must be replaced - with the name of an identity provider defined on the HostedCluster. - This is populated after the infrastructure is ready. - type: string - platform: - description: Platform contains platform-specific status of the HostedCluster - properties: - aws: - description: AWSPlatformStatus contains status specific to the - AWS platform - properties: - defaultWorkerSecurityGroupID: - description: |- - DefaultWorkerSecurityGroupID is the ID of a security group created by - the control plane operator. It is always added to worker machines in - addition to any security groups specified in the NodePool. - type: string - type: object - type: object - version: - description: |- - Version is the status of the release version applied to the - HostedCluster. - properties: - availableUpdates: - description: |- - availableUpdates contains updates recommended for this - cluster. Updates which appear in conditionalUpdates but not in - availableUpdates may expose this cluster to known issues. This list - may be empty if no updates are recommended, if the update service - is unavailable, or if an invalid channel has been specified. - items: - description: Release represents an OpenShift release image and - associated metadata. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - nullable: true - type: array - conditionalUpdates: - description: |- - conditionalUpdates contains the list of updates that may be - recommended for this cluster if it meets specific required - conditions. Consumers interested in the set of updates that are - actually recommended for this cluster should use - availableUpdates. This list may be empty if no updates are - recommended, if the update service is unavailable, or if an empty - or invalid channel has been specified. - items: - description: |- - ConditionalUpdate represents an update which is recommended to some - clusters on the version the current cluster is reconciling, but which - may not be recommended for the current cluster. - properties: - conditions: - description: |- - conditions represents the observations of the conditional update's - current status. Known types are: - * Recommended, for whether the update is recommended for the current cluster. - items: - description: "Condition contains details for one aspect - of the current state of this API Resource.\n---\nThis - struct is intended for direct use as an array at the - field path .status.conditions. For example,\n\n\n\ttype - FooStatus struct{\n\t // Represents the observations - of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t - \ // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t - \ // +listType=map\n\t // +listMapKey=type\n\t - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, - False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - release: - description: release is the target of the update. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - risks: - description: |- - risks represents the range of issues associated with - updating to the target release. The cluster-version - operator will evaluate all entries, and only recommend the - update if there is at least one entry and all entries - recommend the update. - items: - description: |- - ConditionalUpdateRisk represents a reason and cluster-state - for not recommending a conditional update. - properties: - matchingRules: - description: |- - matchingRules is a slice of conditions for deciding which - clusters match the risk and which do not. The slice is - ordered by decreasing precedence. The cluster-version - operator will walk the slice in order, and stop after the - first it can successfully evaluate. If no condition can be - successfully evaluated, the update will not be recommended. - items: - description: |- - ClusterCondition is a union of typed cluster conditions. The 'type' - property determines which of the type-specific properties are relevant. - When evaluated on a cluster, the condition may match, not match, or - fail to evaluate. - properties: - promql: - description: promQL represents a cluster condition - based on PromQL. - properties: - promql: - description: |- - PromQL is a PromQL query classifying clusters. This query - query should return a 1 in the match case and a 0 in the - does-not-match case. Queries which return no time - series, or which return values besides 0 or 1, are - evaluation failures. - type: string - required: - - promql - type: object - type: - description: |- - type represents the cluster-condition type. This defines - the members and semantics of any additional properties. - enum: - - Always - - PromQL - type: string - required: - - type - type: object - minItems: 1 - type: array - x-kubernetes-list-type: atomic - message: - description: |- - message provides additional information about the risk of - updating, in the event that matchingRules match the cluster - state. This is only to be consumed by humans. It may - contain Line Feed characters (U+000A), which should be - rendered as new lines. - minLength: 1 - type: string - name: - description: |- - name is the CamelCase reason for not recommending a - conditional update, in the event that matchingRules match the - cluster state. - minLength: 1 - type: string - url: - description: url contains information about this risk. - format: uri - minLength: 1 - type: string - required: - - matchingRules - - message - - name - - url - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - release - - risks - type: object - type: array - x-kubernetes-list-type: atomic - desired: - description: |- - desired is the version that the cluster is reconciling towards. - If the cluster is not yet fully initialized desired will be set - with the information available, which may be an image or a tag. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - history: - description: |- - history contains a list of the most recent versions applied to the cluster. - This value may be empty during cluster startup, and then will be updated - when a new update is being applied. The newest update is first in the - list and it is ordered by recency. Updates in the history have state - Completed if the rollout completed - if an update was failing or halfway - applied the state will be Partial. Only a limited amount of update history - is preserved. - items: - description: UpdateHistory is a single attempted update to the - cluster. - properties: - acceptedRisks: - description: |- - acceptedRisks records risks which were accepted to initiate the update. - For example, it may menition an Upgradeable=False or missing signature - that was overriden via desiredUpdate.force, or an update that was - initiated despite not being in the availableUpdates set of recommended - update targets. - type: string - completionTime: - description: |- - completionTime, if set, is when the update was fully applied. The update - that is currently being applied will have a null completion time. - Completion time will always be set for entries that are not the current - update (usually to the started time of the next update). - format: date-time - nullable: true - type: string - image: - description: |- - image is a container image location that contains the update. This value - is always populated. - type: string - startedTime: - description: startedTime is the time at which the update - was started. - format: date-time - type: string - state: - description: |- - state reflects whether the update was fully applied. The Partial state - indicates the update is not fully applied, while the Completed state - indicates the update was successfully rolled out at least once (all - parts of the update successfully applied). - type: string - verified: - description: |- - verified indicates whether the provided update was properly verified - before it was installed. If this is false the cluster may not be trusted. - Verified does not cover upgradeable checks that depend on the cluster - state at the time when the update target was accepted. - type: boolean - version: - description: |- - version is a semantic version identifying the update version. If the - requested image does not define a version, or if a failure occurs - retrieving the image, this value may be empty. - type: string - required: - - completionTime - - image - - startedTime - - state - - verified - type: object - type: array - observedGeneration: - description: |- - observedGeneration reports which version of the spec is being synced. - If this value is not equal to metadata.generation, then the desired - and conditions fields may represent a previous version. - format: int64 - type: integer - required: - - availableUpdates - - desired - - observedGeneration - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-hostedcontrolplanes.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-hostedcontrolplanes.hypershift.openshift.io.yaml deleted file mode 100644 index d217204b0..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-hostedcontrolplanes.hypershift.openshift.io.yaml +++ /dev/null @@ -1,10227 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: hostedcontrolplanes.hypershift.openshift.io -spec: - group: hypershift.openshift.io - names: - categories: - - cluster-api - kind: HostedControlPlane - listKind: HostedControlPlaneList - plural: hostedcontrolplanes - shortNames: - - hcp - - hcps - singular: hostedcontrolplane - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: HostedControlPlane defines the desired state of HostedControlPlane - 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: HostedControlPlaneSpec defines the desired state of HostedControlPlane - properties: - additionalTrustBundle: - description: AdditionalTrustBundle references a ConfigMap containing - a PEM-encoded X.509 certificate bundle - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - apiAdvertiseAddress: - description: |- - deprecated - use networking.apiServer.AdvertiseAddress - APIAdvertiseAddress is the address at which the APIServer listens - inside a worker. - type: string - apiAllowedCIDRBlocks: - description: |- - deprecated - use networking.apiServer.APIAllowedCIDRBlocks - APIAllowedCIDRBlocks is an allow list of CIDR blocks that can access the APIServer - If not specified, traffic is allowed from all addresses. - This depends on underlying support by the cloud provider for Service LoadBalancerSourceRanges - items: - pattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$ - type: string - type: array - apiPort: - description: |- - deprecated - use networking.apiServer.APIPort - APIPort is the port at which the APIServer listens inside a worker - format: int32 - type: integer - auditWebhook: - description: |- - AuditWebhook contains metadata for configuring an audit webhook - endpoint for a cluster to process cluster audit events. It references - a secret that contains the webhook information for the audit webhook endpoint. - It is a secret because if the endpoint has MTLS the kubeconfig will contain client - keys. This is currently only supported in IBM Cloud. The kubeconfig needs to be stored - in the secret with a secret key name that corresponds to the constant AuditWebhookKubeconfigKey. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - autoscaling: - description: |- - Autoscaling specifies auto-scaling behavior that applies to all NodePools - associated with the control plane. - properties: - maxNodeProvisionTime: - description: |- - MaxNodeProvisionTime is the maximum time to wait for node provisioning - before considering the provisioning to be unsuccessful, expressed as a Go - duration string. The default is 15 minutes. - pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ - type: string - maxNodesTotal: - description: |- - MaxNodesTotal is the maximum allowable number of nodes across all NodePools - for a HostedCluster. The autoscaler will not grow the cluster beyond this - number. - format: int32 - minimum: 0 - type: integer - maxPodGracePeriod: - description: |- - MaxPodGracePeriod is the maximum seconds to wait for graceful pod - termination before scaling down a NodePool. The default is 600 seconds. - format: int32 - minimum: 0 - type: integer - podPriorityThreshold: - description: |- - PodPriorityThreshold enables users to schedule "best-effort" pods, which - shouldn't trigger autoscaler actions, but only run when there are spare - resources available. The default is -10. - - - See the following for more details: - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-cluster-autoscaler-work-with-pod-priority-and-preemption - format: int32 - type: integer - type: object - channel: - description: |- - channel is an identifier for explicitly requesting that a non-default - set of updates be applied to this cluster. The default channel will be - contain stable updates that are appropriate for production clusters. - type: string - clusterID: - description: |- - ClusterID is the unique id that identifies the cluster externally. - Making it optional here allows us to keep compatibility with previous - versions of the control-plane-operator that have no knowledge of this - field. - type: string - configuration: - description: |- - Configuration embeds resources that correspond to the openshift configuration API: - https://docs.openshift.com/container-platform/4.7/rest_api/config_apis/config-apis-index.html - properties: - apiServer: - description: |- - APIServer holds configuration (like serving certificates, client CA and CORS domains) - shared by all API servers in the system, among them especially kube-apiserver - and openshift-apiserver. - properties: - additionalCORSAllowedOrigins: - description: |- - additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the - API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth - server from JavaScript applications. - The values are regular expressions that correspond to the Golang regular expression language. - items: - type: string - type: array - audit: - default: - profile: Default - description: |- - audit specifies the settings for audit configuration to be applied to all OpenShift-provided - API servers in the cluster. - properties: - customRules: - description: |- - customRules specify profiles per group. These profile take precedence over the - top-level profile field if they apply. They are evaluation from top to bottom and - the first one that matches, applies. - items: - description: |- - AuditCustomRule describes a custom rule for an audit profile that takes precedence over - the top-level profile. - properties: - group: - description: group is a name of group a request - user must be member of in order to this profile - to apply. - minLength: 1 - type: string - profile: - description: |- - profile specifies the name of the desired audit policy configuration to be deployed to - all OpenShift-provided API servers in the cluster. - - - The following profiles are provided: - - Default: the existing default policy. - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - required: - - group - - profile - type: object - type: array - x-kubernetes-list-map-keys: - - group - x-kubernetes-list-type: map - profile: - default: Default - description: |- - profile specifies the name of the desired top-level audit profile to be applied to all requests - sent to any of the OpenShift-provided API servers in the cluster (kube-apiserver, - openshift-apiserver and oauth-apiserver), with the exception of those requests that match - one or more of the customRules. - - - The following profiles are provided: - - Default: default policy which means MetaData level logging with the exception of events - (not logged at all), oauthaccesstokens and oauthauthorizetokens (both logged at RequestBody - level). - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - Warning: It is not recommended to disable audit logging by using the `None` profile unless you - are fully aware of the risks of not logging data that can be beneficial when troubleshooting issues. - If you disable audit logging and a support situation arises, you might need to enable audit logging - and reproduce the issue in order to troubleshoot properly. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - type: object - clientCA: - description: |- - clientCA references a ConfigMap containing a certificate bundle for the signers that will be recognized for - incoming client certificates in addition to the operator managed signers. If this is empty, then only operator managed signers are valid. - You usually only have to set this if you have your own PKI you wish to honor client certificates from. - The ConfigMap must exist in the openshift-config namespace and contain the following required fields: - - ConfigMap.Data["ca-bundle.crt"] - CA bundle. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - encryption: - description: encryption allows the configuration of encryption - of resources at the datastore layer. - properties: - type: - description: |- - type defines what encryption type should be used to encrypt resources at the datastore layer. - When this field is unset (i.e. when it is set to the empty string), identity is implied. - The behavior of unset can and will change over time. Even if encryption is enabled by default, - the meaning of unset may change to a different encryption type based on changes in best practices. - - - When encryption is enabled, all sensitive resources shipped with the platform are encrypted. - This list of sensitive resources can and will change over time. The current authoritative list is: - - - 1. secrets - 2. configmaps - 3. routes.route.openshift.io - 4. oauthaccesstokens.oauth.openshift.io - 5. oauthauthorizetokens.oauth.openshift.io - enum: - - "" - - identity - - aescbc - - aesgcm - type: string - type: object - servingCerts: - description: |- - servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates - will be used for serving secure traffic. - properties: - namedCertificates: - description: |- - namedCertificates references secrets containing the TLS cert info for serving secure traffic to specific hostnames. - If no named certificates are provided, or no named certificates match the server name as understood by a client, - the defaultServingCertificate will be used. - items: - description: APIServerNamedServingCert maps a server - DNS name, as understood by a client, to a certificate. - properties: - names: - description: |- - names is a optional list of explicit DNS names (leading wildcards allowed) that should use this certificate to - serve secure traffic. If no names are provided, the implicit names will be extracted from the certificates. - Exact names trump over wildcard names. Explicit names defined here trump over extracted implicit names. - items: - type: string - type: array - servingCertificate: - description: |- - servingCertificate references a kubernetes.io/tls type secret containing the TLS cert info for serving secure traffic. - The secret must exist in the openshift-config namespace and contain the following required fields: - - Secret.Data["tls.key"] - TLS private key. - - Secret.Data["tls.crt"] - TLS certificate. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - type: array - type: object - tlsSecurityProfile: - description: |- - tlsSecurityProfile specifies settings for TLS connections for externally exposed servers. - - - If unset, a default (which may change between releases) is chosen. Note that only Old, - Intermediate and Custom profiles are currently supported, and the maximum available - minTLSVersion is VersionTLS12. - properties: - custom: - description: |- - custom is a user-defined TLS security profile. Be extremely careful using a custom - profile as invalid configurations can be catastrophic. An example custom profile - looks like this: - - - ciphers: - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - minTLSVersion: VersionTLS11 - nullable: true - properties: - ciphers: - description: |- - ciphers is used to specify the cipher algorithms that are negotiated - during the TLS handshake. Operators may remove entries their operands - do not support. For example, to use DES-CBC3-SHA (yaml): - - - ciphers: - - DES-CBC3-SHA - items: - type: string - type: array - minTLSVersion: - description: |- - minTLSVersion is used to specify the minimal version of the TLS protocol - that is negotiated during the TLS handshake. For example, to use TLS - versions 1.1, 1.2 and 1.3 (yaml): - - - minTLSVersion: VersionTLS11 - - - NOTE: currently the highest minTLSVersion allowed is VersionTLS12 - enum: - - VersionTLS10 - - VersionTLS11 - - VersionTLS12 - - VersionTLS13 - type: string - type: object - intermediate: - description: |- - intermediate is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - minTLSVersion: VersionTLS12 - nullable: true - type: object - modern: - description: |- - modern is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - minTLSVersion: VersionTLS13 - nullable: true - type: object - old: - description: |- - old is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - - DHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-ECDSA-AES128-SHA256 - - - - ECDHE-RSA-AES128-SHA256 - - - - ECDHE-ECDSA-AES128-SHA - - - - ECDHE-RSA-AES128-SHA - - - - ECDHE-ECDSA-AES256-SHA384 - - - - ECDHE-RSA-AES256-SHA384 - - - - ECDHE-ECDSA-AES256-SHA - - - - ECDHE-RSA-AES256-SHA - - - - DHE-RSA-AES128-SHA256 - - - - DHE-RSA-AES256-SHA256 - - - - AES128-GCM-SHA256 - - - - AES256-GCM-SHA384 - - - - AES128-SHA256 - - - - AES256-SHA256 - - - - AES128-SHA - - - - AES256-SHA - - - - DES-CBC3-SHA - - - minTLSVersion: VersionTLS10 - nullable: true - type: object - type: - description: |- - type is one of Old, Intermediate, Modern or Custom. Custom provides - the ability to specify individual TLS security profile parameters. - Old, Intermediate and Modern are TLS security profiles based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations - - - The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers - are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be - reduced. - - - Note that the Modern profile is currently not supported because it is not - yet well adopted by common software libraries. - enum: - - Old - - Intermediate - - Modern - - Custom - type: string - type: object - type: object - authentication: - description: |- - Authentication specifies cluster-wide settings for authentication (like OAuth and - webhook token authenticators). - properties: - oauthMetadata: - description: |- - oauthMetadata contains the discovery endpoint data for OAuth 2.0 - Authorization Server Metadata for an external OAuth server. - This discovery document can be viewed from its served location: - oc get --raw '/.well-known/oauth-authorization-server' - For further details, see the IETF Draft: - https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 - If oauthMetadata.name is non-empty, this value has precedence - over any metadata reference stored in status. - The key "oauthMetadata" is used to locate the data. - If specified and the config map or expected key is not found, no metadata is served. - If the specified metadata is not valid, no metadata is served. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - oidcProviders: - description: |- - OIDCProviders are OIDC identity providers that can issue tokens - for this cluster - Can only be set if "Type" is set to "OIDC". - - - At most one provider can be configured. - items: - properties: - claimMappings: - description: |- - ClaimMappings describes rules on how to transform information from an - ID token into a cluster identity - properties: - groups: - description: |- - Groups is a name of the claim that should be used to construct - groups for the cluster identity. - The referenced claim must use array of strings values. - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - description: |- - Prefix is a string to prefix the value from the token in the result of the - claim mapping. - - - By default, no prefixing occurs. - - - Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains - an array of strings "a", "b" and "c", the mapping will result in an - array of string "myoidc:a", "myoidc:b" and "myoidc:c". - type: string - required: - - claim - type: object - username: - description: |- - Username is a name of the claim that should be used to construct - usernames for the cluster identity. - - - Default value: "sub" - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - properties: - prefixString: - minLength: 1 - type: string - required: - - prefixString - type: object - prefixPolicy: - description: |- - PrefixPolicy specifies how a prefix should apply. - - - By default, claims other than `email` will be prefixed with the issuer URL to - prevent naming clashes with other plugins. - - - Set to "NoPrefix" to disable prefixing. - - - Example: - (1) `prefix` is set to "myoidc:" and `claim` is set to "username". - If the JWT claim `username` contains value `userA`, the resulting - mapped value will be "myoidc:userA". - (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the - JWT `email` claim contains value "userA@myoidc.tld", the resulting - mapped value will be "myoidc:userA@myoidc.tld". - (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`, - the JWT claims include "username":"userA" and "email":"userA@myoidc.tld", - and `claim` is set to: - (a) "username": the mapped value will be "https://myoidc.tld#userA" - (b) "email": the mapped value will be "userA@myoidc.tld" - enum: - - "" - - NoPrefix - - Prefix - type: string - required: - - claim - type: object - x-kubernetes-validations: - - message: prefix must be set if prefixPolicy is - 'Prefix', but must remain unset otherwise - rule: 'has(self.prefixPolicy) && self.prefixPolicy - == ''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString) - > 0) : !has(self.prefix)' - type: object - claimValidationRules: - description: ClaimValidationRules are rules that are - applied to validate token claims to authenticate users. - items: - properties: - requiredClaim: - description: |- - RequiredClaim allows configuring a required claim name and its expected - value - properties: - claim: - description: |- - Claim is a name of a required claim. Only claims with string values are - supported. - minLength: 1 - type: string - requiredValue: - description: RequiredValue is the required - value for the claim. - minLength: 1 - type: string - required: - - claim - - requiredValue - type: object - type: - default: RequiredClaim - description: Type sets the type of the validation - rule - enum: - - RequiredClaim - type: string - type: object - type: array - x-kubernetes-list-type: atomic - issuer: - description: Issuer describes atributes of the OIDC - token issuer - properties: - audiences: - description: |- - Audiences is an array of audiences that the token was issued for. - Valid tokens must include at least one of these values in their - "aud" claim. - Must be set to exactly one value. - items: - minLength: 1 - type: string - maxItems: 10 - minItems: 1 - type: array - x-kubernetes-list-type: set - issuerCertificateAuthority: - description: |- - CertificateAuthority is a reference to a config map in the - configuration namespace. The .data of the configMap must contain - the "ca-bundle.crt" key. - If unset, system trust is used instead. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - issuerURL: - description: |- - URL is the serving URL of the token issuer. - Must use the https:// scheme. - pattern: ^https:\/\/[^\s] - type: string - required: - - audiences - - issuerURL - type: object - name: - description: Name of the OIDC provider - minLength: 1 - type: string - oidcClients: - description: |- - OIDCClients contains configuration for the platform's clients that - need to request tokens from the issuer - items: - properties: - clientID: - description: ClientID is the identifier of the - OIDC client from the OIDC provider - minLength: 1 - type: string - clientSecret: - description: |- - ClientSecret refers to a secret in the `openshift-config` namespace that - contains the client secret in the `clientSecret` key of the `.data` field - properties: - name: - description: name is the metadata.name of - the referenced secret - type: string - required: - - name - type: object - componentName: - description: |- - ComponentName is the name of the component that is supposed to consume this - client configuration - maxLength: 256 - minLength: 1 - type: string - componentNamespace: - description: |- - ComponentNamespace is the namespace of the component that is supposed to consume this - client configuration - maxLength: 63 - minLength: 1 - type: string - extraScopes: - description: ExtraScopes is an optional set of - scopes to request tokens with. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - clientID - - componentName - - componentNamespace - type: object - maxItems: 20 - type: array - x-kubernetes-list-map-keys: - - componentNamespace - - componentName - x-kubernetes-list-type: map - required: - - issuer - - name - type: object - maxItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceAccountIssuer: - description: |- - serviceAccountIssuer is the identifier of the bound service account token - issuer. - The default is https://kubernetes.default.svc - WARNING: Updating this field will not result in immediate invalidation of all bound tokens with the - previous issuer value. Instead, the tokens issued by previous service account issuer will continue to - be trusted for a time period chosen by the platform (currently set to 24h). - This time period is subject to change over time. - This allows internal components to transition to use new service account issuer without service distruption. - type: string - type: - description: |- - type identifies the cluster managed, user facing authentication mode in use. - Specifically, it manages the component that responds to login attempts. - The default is IntegratedOAuth. - type: string - webhookTokenAuthenticator: - description: |- - webhookTokenAuthenticator configures a remote token reviewer. - These remote authentication webhooks can be used to verify bearer tokens - via the tokenreviews.authentication.k8s.io REST API. This is required to - honor bearer tokens that are provisioned by an external authentication service. - - - Can only be set if "Type" is set to "None". - properties: - kubeConfig: - description: |- - kubeConfig references a secret that contains kube config file data which - describes how to access the remote webhook service. - The namespace for the referenced secret is openshift-config. - - - For further details, see: - - - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - - - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - kubeConfig - type: object - webhookTokenAuthenticators: - description: webhookTokenAuthenticators is DEPRECATED, setting - it has no effect. - items: - description: |- - deprecatedWebhookTokenAuthenticator holds the necessary configuration options for a remote token authenticator. - It's the same as WebhookTokenAuthenticator but it's missing the 'required' validation on KubeConfig field. - properties: - kubeConfig: - description: |- - kubeConfig contains kube config file data which describes how to access the remote webhook service. - For further details, see: - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - The namespace for this secret is determined by the point of use. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - configMapRefs: - description: |- - ConfigMapRefs holds references to any configmaps referenced by - configuration entries. Entries can reference the configmaps using local - object references. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - featureGate: - description: FeatureGate holds cluster-wide information about - feature gates. - properties: - customNoUpgrade: - description: |- - customNoUpgrade allows the enabling or disabling of any feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, and PREVENTS UPGRADES. - Because of its nature, this setting cannot be validated. If you have any typos or accidentally apply invalid combinations - your cluster may fail in an unrecoverable way. featureSet must equal "CustomNoUpgrade" must be set to use this field. - nullable: true - properties: - disabled: - description: disabled is a list of all feature gates that - you want to force off - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - enabled: - description: enabled is a list of all feature gates that - you want to force on - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - type: object - featureSet: - description: |- - featureSet changes the list of features in the cluster. The default is empty. Be very careful adjusting this setting. - Turning on or off features may cause irreversible changes in your cluster which cannot be undone. - type: string - x-kubernetes-validations: - - message: CustomNoUpgrade may not be changed - rule: 'oldSelf == ''CustomNoUpgrade'' ? self == ''CustomNoUpgrade'' - : true' - - message: TechPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''TechPreviewNoUpgrade'' ? self == ''TechPreviewNoUpgrade'' - : true' - - message: DevPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''DevPreviewNoUpgrade'' ? self == ''DevPreviewNoUpgrade'' - : true' - type: object - image: - description: |- - Image governs policies related to imagestream imports and runtime configuration - for external registries. It allows cluster admins to configure which registries - OpenShift is allowed to import images from, extra CA trust bundles for external - registries, and policies to block or allow registry hostnames. - When exposing OpenShift's image registry to the public, this also lets cluster - admins specify the external hostname. - properties: - additionalTrustedCA: - description: |- - additionalTrustedCA is a reference to a ConfigMap containing additional CAs that - should be trusted during imagestream import, pod image pull, build image pull, and - imageregistry pullthrough. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - allowedRegistriesForImport: - description: |- - allowedRegistriesForImport limits the container image registries that normal users may import - images from. Set this list to the registries that you trust to contain valid Docker - images and that you want applications to be able to import from. Users with - permission to create Images or ImageStreamMappings via the API are not affected by - this policy - typically only administrators or system integrations will have those - permissions. - items: - description: |- - RegistryLocation contains a location of the registry specified by the registry domain - name. The domain name might include wildcards, like '*' or '??'. - properties: - domainName: - description: |- - domainName specifies a domain name for the registry - In case the registry use non-standard (80 or 443) port, the port should be included - in the domain name as well. - type: string - insecure: - description: |- - insecure indicates whether the registry is secure (https) or insecure (http) - By default (if not specified) the registry is assumed as secure. - type: boolean - type: object - type: array - externalRegistryHostnames: - description: |- - externalRegistryHostnames provides the hostnames for the default external image - registry. The external hostname should be set only when the image registry - is exposed externally. The first value is used in 'publicDockerImageRepository' - field in ImageStreams. The value must be in "hostname[:port]" format. - items: - type: string - type: array - registrySources: - description: |- - registrySources contains configuration that determines how the container runtime - should treat individual registries when accessing images for builds+pods. (e.g. - whether or not to allow insecure access). It does not contain configuration for the - internal cluster registry. - properties: - allowedRegistries: - description: |- - allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - blockedRegistries: - description: |- - blockedRegistries cannot be used for image pull and push actions. All other registries are permitted. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - containerRuntimeSearchRegistries: - description: |- - containerRuntimeSearchRegistries are registries that will be searched when pulling images that do not have fully qualified - domains in their pull specs. Registries will be searched in the order provided in the list. - Note: this search list only works with the container runtime, i.e CRI-O. Will NOT work with builds or imagestream imports. - format: hostname - items: - type: string - minItems: 1 - type: array - x-kubernetes-list-type: set - insecureRegistries: - description: insecureRegistries are registries which do - not have a valid TLS certificates or only support HTTP - connections. - items: - type: string - type: array - type: object - type: object - ingress: - description: |- - Ingress holds cluster-wide information about ingress, including the default ingress domain - used for routes. - properties: - appsDomain: - description: |- - appsDomain is an optional domain to use instead of the one specified - in the domain field when a Route is created without specifying an explicit - host. If appsDomain is nonempty, this value is used to generate default - host values for Route. Unlike domain, appsDomain may be modified after - installation. - This assumes a new ingresscontroller has been setup with a wildcard - certificate. - type: string - componentRoutes: - description: |- - componentRoutes is an optional list of routes that are managed by OpenShift components - that a cluster-admin is able to configure the hostname and serving certificate for. - The namespace and name of each route in this list should match an existing entry in the - status.componentRoutes list. - - - To determine the set of configurable Routes, look at namespace and name of entries in the - .status.componentRoutes list, where participating operators write the status of - configurable routes. - items: - description: ComponentRouteSpec allows for configuration - of a route's hostname and serving certificate. - properties: - hostname: - description: hostname is the hostname that should be - used by the route. - pattern: ^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$|^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$ - type: string - name: - description: |- - name is the logical name of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 256 - minLength: 1 - type: string - namespace: - description: |- - namespace is the namespace of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - servingCertKeyPairSecret: - description: |- - servingCertKeyPairSecret is a reference to a secret of type `kubernetes.io/tls` in the openshift-config namespace. - The serving cert/key pair must match and will be used by the operator to fulfill the intent of serving with this name. - If the custom hostname uses the default routing suffix of the cluster, - the Secret specification for a serving certificate will not be needed. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - hostname - - name - - namespace - type: object - type: array - x-kubernetes-list-map-keys: - - namespace - - name - x-kubernetes-list-type: map - domain: - description: |- - domain is used to generate a default host name for a route when the - route's host name is empty. The generated host name will follow this - pattern: "..". - - - It is also used as the default wildcard domain suffix for ingress. The - default ingresscontroller domain will follow this pattern: "*.". - - - Once set, changing domain is not currently supported. - type: string - loadBalancer: - description: |- - loadBalancer contains the load balancer details in general which are not only specific to the underlying infrastructure - provider of the current cluster and are required for Ingress Controller to work on OpenShift. - properties: - platform: - description: |- - platform holds configuration specific to the underlying - infrastructure provider for the ingress load balancers. - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - properties: - aws: - description: aws contains settings specific to the - Amazon Web Services infrastructure provider. - properties: - type: - description: |- - type allows user to set a load balancer type. - When this field is set the default ingresscontroller will get created using the specified LBType. - If this field is not set then the default ingress controller of LBType Classic will be created. - Valid values are: - - - * "Classic": A Classic Load Balancer that makes routing decisions at either - the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See - the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb - - - * "NLB": A Network Load Balancer that makes routing decisions at the - transport layer (TCP/SSL). See the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb - enum: - - NLB - - Classic - type: string - required: - - type - type: object - type: - description: |- - type is the underlying infrastructure provider for the cluster. - Allowed values are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", - "OpenStack", "VSphere", "oVirt", "KubeVirt", "EquinixMetal", "PowerVS", - "AlibabaCloud", "Nutanix" and "None". Individual components may not support all platforms, - and must handle unrecognized platforms as None if they do not support that platform. - enum: - - "" - - AWS - - Azure - - BareMetal - - GCP - - Libvirt - - OpenStack - - None - - VSphere - - oVirt - - IBMCloud - - KubeVirt - - EquinixMetal - - PowerVS - - AlibabaCloud - - Nutanix - - External - type: string - type: object - type: object - requiredHSTSPolicies: - description: |- - requiredHSTSPolicies specifies HSTS policies that are required to be set on newly created or updated routes - matching the domainPattern/s and namespaceSelector/s that are specified in the policy. - Each requiredHSTSPolicy must have at least a domainPattern and a maxAge to validate a route HSTS Policy route - annotation, and affect route admission. - - - A candidate route is checked for HSTS Policies if it has the HSTS Policy route annotation: - "haproxy.router.openshift.io/hsts_header" - E.g. haproxy.router.openshift.io/hsts_header: max-age=31536000;preload;includeSubDomains - - - - For each candidate route, if it matches a requiredHSTSPolicy domainPattern and optional namespaceSelector, - then the maxAge, preloadPolicy, and includeSubdomainsPolicy must be valid to be admitted. Otherwise, the route - is rejected. - - The first match, by domainPattern and optional namespaceSelector, in the ordering of the RequiredHSTSPolicies - determines the route's admission status. - - If the candidate route doesn't match any requiredHSTSPolicy domainPattern and optional namespaceSelector, - then it may use any HSTS Policy annotation. - - - The HSTS policy configuration may be changed after routes have already been created. An update to a previously - admitted route may then fail if the updated route does not conform to the updated HSTS policy configuration. - However, changing the HSTS policy configuration will not cause a route that is already admitted to stop working. - - - Note that if there are no RequiredHSTSPolicies, any HSTS Policy annotation on the route is valid. - items: - properties: - domainPatterns: - description: |- - domainPatterns is a list of domains for which the desired HSTS annotations are required. - If domainPatterns is specified and a route is created with a spec.host matching one of the domains, - the route must specify the HSTS Policy components described in the matching RequiredHSTSPolicy. - - - The use of wildcards is allowed like this: *.foo.com matches everything under foo.com. - foo.com only matches foo.com, so to cover foo.com and everything under it, you must specify *both*. - items: - type: string - minItems: 1 - type: array - includeSubDomainsPolicy: - description: |- - includeSubDomainsPolicy means the HSTS Policy should apply to any subdomains of the host's - domain name. Thus, for the host bar.foo.com, if includeSubDomainsPolicy was set to RequireIncludeSubDomains: - - the host app.bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host foo.com would NOT inherit the HSTS Policy of bar.foo.com - - the host def.foo.com would NOT inherit the HSTS Policy of bar.foo.com - enum: - - RequireIncludeSubDomains - - RequireNoIncludeSubDomains - - NoOpinion - type: string - maxAge: - description: |- - maxAge is the delta time range in seconds during which hosts are regarded as HSTS hosts. - If set to 0, it negates the effect, and hosts are removed as HSTS hosts. - If set to 0 and includeSubdomains is specified, all subdomains of the host are also removed as HSTS hosts. - maxAge is a time-to-live value, and if this policy is not refreshed on a client, the HSTS - policy will eventually expire on that client. - properties: - largestMaxAge: - description: |- - The largest allowed value (in seconds) of the RequiredHSTSPolicy max-age - This value can be left unspecified, in which case no upper limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - smallestMaxAge: - description: |- - The smallest allowed value (in seconds) of the RequiredHSTSPolicy max-age - Setting max-age=0 allows the deletion of an existing HSTS header from a host. This is a necessary - tool for administrators to quickly correct mistakes. - This value can be left unspecified, in which case no lower limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - type: object - namespaceSelector: - description: |- - namespaceSelector specifies a label selector such that the policy applies only to those routes that - are in namespaces with labels that match the selector, and are in one of the DomainPatterns. - Defaults to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - preloadPolicy: - description: |- - preloadPolicy directs the client to include hosts in its host preload list so that - it never needs to do an initial load to get the HSTS header (note that this is not defined - in RFC 6797 and is therefore client implementation-dependent). - enum: - - RequirePreload - - RequireNoPreload - - NoOpinion - type: string - required: - - domainPatterns - type: object - type: array - type: object - items: - description: |- - Items embeds the serialized configuration resources. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - type: object - x-kubernetes-preserve-unknown-fields: true - type: array - x-kubernetes-preserve-unknown-fields: true - network: - description: |- - Network holds cluster-wide information about the network. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. - Please view network.spec for an explanation on what applies when configuring this resource. - TODO (csrwng): Add validation here to exclude changes that conflict with networking settings in the HostedCluster.Spec.Networking field. - properties: - clusterNetwork: - description: |- - IP address pool to use for pod IPs. - This field is immutable after installation. - items: - description: |- - ClusterNetworkEntry is a contiguous block of IP addresses from which pod IPs - are allocated. - properties: - cidr: - description: The complete block for pod IPs. - type: string - hostPrefix: - description: |- - The size (prefix) of block to allocate to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - minimum: 0 - type: integer - type: object - type: array - x-kubernetes-list-type: atomic - externalIP: - description: |- - externalIP defines configuration for controllers that - affect Service.ExternalIP. If nil, then ExternalIP is - not allowed to be set. - properties: - autoAssignCIDRs: - description: |- - autoAssignCIDRs is a list of CIDRs from which to automatically assign - Service.ExternalIP. These are assigned when the service is of type - LoadBalancer. In general, this is only useful for bare-metal clusters. - In Openshift 3.x, this was misleadingly called "IngressIPs". - Automatically assigned External IPs are not affected by any - ExternalIPPolicy rules. - Currently, only one entry may be provided. - items: - type: string - type: array - x-kubernetes-list-type: atomic - policy: - description: |- - policy is a set of restrictions applied to the ExternalIP field. - If nil or empty, then ExternalIP is not allowed to be set. - properties: - allowedCIDRs: - description: allowedCIDRs is the list of allowed CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - rejectedCIDRs: - description: |- - rejectedCIDRs is the list of disallowed CIDRs. These take precedence - over allowedCIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkDiagnostics: - description: |- - networkDiagnostics defines network diagnostics configuration. - - - Takes precedence over spec.disableNetworkDiagnostics in network.operator.openshift.io. - If networkDiagnostics is not specified or is empty, - and the spec.disableNetworkDiagnostics flag in network.operator.openshift.io is set to true, - the network diagnostics feature will be disabled. - properties: - mode: - description: |- - mode controls the network diagnostics mode - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is All. - enum: - - "" - - All - - Disabled - type: string - sourcePlacement: - description: |- - sourcePlacement controls the scheduling of network diagnostics source deployment - - - See NetworkDiagnosticsSourcePlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is an empty list. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - targetPlacement: - description: |- - targetPlacement controls the scheduling of network diagnostics target daemonset - - - See NetworkDiagnosticsTargetPlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `- operator: "Exists"` which means that all taints are tolerated. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkType: - description: |- - NetworkType is the plugin that is to be deployed (e.g. OpenShiftSDN). - This should match a value that the cluster-network-operator understands, - or else no networking will be installed. - Currently supported values are: - - OpenShiftSDN - This field is immutable after installation. - type: string - serviceNetwork: - description: |- - IP address pool for services. - Currently, we only support a single entry here. - This field is immutable after installation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - serviceNodePortRange: - description: |- - The port range allowed for Services of type NodePort. - If not specified, the default of 30000-32767 will be used. - Such Services without a NodePort specified will have one - automatically allocated from this range. - This parameter can be updated after the cluster is - installed. - pattern: ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])-([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ - type: string - type: object - oauth: - description: |- - OAuth holds cluster-wide information about OAuth. - It is used to configure the integrated OAuth server. - This configuration is only honored when the top level Authentication config has type set to IntegratedOAuth. - properties: - identityProviders: - description: |- - identityProviders is an ordered list of ways for a user to identify themselves. - When this list is empty, no identities are provisioned for users. - items: - description: IdentityProvider provides identities for users - authenticating using credentials - properties: - basicAuth: - description: basicAuth contains configuration options - for the BasicAuth IdP - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - github: - description: github enables user authentication using - GitHub credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - This can only be configured when hostname is set to a non-empty value. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostname: - description: |- - hostname is the optional domain (e.g. "mycompany.com") for use with a hosted instance of - GitHub Enterprise. - It must match the GitHub Enterprise settings value configured at /setup/settings#hostname. - type: string - organizations: - description: organizations optionally restricts - which organizations are allowed to log in - items: - type: string - type: array - teams: - description: teams optionally restricts which teams - are allowed to log in. Format is /. - items: - type: string - type: array - type: object - gitlab: - description: gitlab enables user authentication using - GitLab credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the oauth server base URL - type: string - type: object - google: - description: google enables user authentication using - Google credentials - properties: - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostedDomain: - description: hostedDomain is the optional Google - App domain (e.g. "mycompany.com") to restrict - logins to - type: string - type: object - htpasswd: - description: htpasswd enables user authentication using - an HTPasswd file to validate credentials - properties: - fileData: - description: |- - fileData is a required reference to a secret by name containing the data to use as the htpasswd file. - The key "htpasswd" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - If the specified htpasswd data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - keystone: - description: keystone enables user authentication using - keystone password credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - domainName: - description: domainName is required for keystone - v3 - type: string - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - ldap: - description: ldap enables user authentication using - LDAP credentials - properties: - attributes: - description: attributes maps LDAP attributes to - identities - properties: - email: - description: |- - email is the list of attributes whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - id: - description: |- - id is the list of attributes whose values should be used as the user ID. Required. - First non-empty attribute is used. At least one attribute is required. If none of the listed - attribute have a value, authentication fails. - LDAP standard identity attribute is "dn" - items: - type: string - type: array - name: - description: |- - name is the list of attributes whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - LDAP standard display name attribute is "cn" - items: - type: string - type: array - preferredUsername: - description: |- - preferredUsername is the list of attributes whose values should be used as the preferred username. - LDAP standard login attribute is "uid" - items: - type: string - type: array - type: object - bindDN: - description: bindDN is an optional DN to bind with - during the search phase. - type: string - bindPassword: - description: |- - bindPassword is an optional reference to a secret by name - containing a password to bind with during the search phase. - The key "bindPassword" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - insecure: - description: |- - insecure, if true, indicates the connection should not use TLS - WARNING: Should not be set to `true` with the URL scheme "ldaps://" as "ldaps://" URLs always - attempt to connect using TLS, even when `insecure` is set to `true` - When `true`, "ldap://" URLS connect insecurely. When `false`, "ldap://" URLs are upgraded to - a TLS connection using StartTLS as specified in https://tools.ietf.org/html/rfc2830. - type: boolean - url: - description: |- - url is an RFC 2255 URL which specifies the LDAP search parameters to use. - The syntax of the URL is: - ldap://host:port/basedn?attribute?scope?filter - type: string - type: object - mappingMethod: - description: |- - mappingMethod determines how identities from this provider are mapped to users - Defaults to "claim" - type: string - name: - description: |- - name is used to qualify the identities returned by this provider. - - It MUST be unique and not shared by any other identity provider used - - It MUST be a valid path segment: name cannot equal "." or ".." or contain "/" or "%" or ":" - Ref: https://godoc.org/github.com/openshift/origin/pkg/user/apis/user/validation#ValidateIdentityProviderName - type: string - openID: - description: openID enables user authentication using - OpenID credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - claims: - description: claims mappings - properties: - email: - description: |- - email is the list of claims whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - groups: - description: |- - groups is the list of claims value of which should be used to synchronize groups - from the OIDC provider to OpenShift for the user. - If multiple claims are specified, the first one with a non-empty value is used. - items: - description: |- - OpenIDClaim represents a claim retrieved from an OpenID provider's tokens or userInfo - responses - minLength: 1 - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: |- - name is the list of claims whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - preferredUsername: - description: |- - preferredUsername is the list of claims whose values should be used as the preferred username. - If unspecified, the preferred username is determined from the value of the sub claim - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - extraAuthorizeParameters: - additionalProperties: - type: string - description: extraAuthorizeParameters are any custom - parameters to add to the authorize request. - type: object - extraScopes: - description: extraScopes are any scopes to request - in addition to the standard "openid" scope. - items: - type: string - type: array - issuer: - description: |- - issuer is the URL that the OpenID Provider asserts as its Issuer Identifier. - It must use the https scheme with no query or fragment component. - type: string - type: object - requestHeader: - description: requestHeader enables user authentication - using request header credentials - properties: - ca: - description: |- - ca is a required reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - Specifically, it allows verification of incoming requests to prevent header spoofing. - The key "ca.crt" is used to locate the data. - If the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - challengeURL: - description: |- - challengeURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect WWW-Authenticate challenges will be - redirected here. - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when challenge is set to true. - type: string - clientCommonNames: - description: |- - clientCommonNames is an optional list of common names to require a match from. If empty, any - client certificate validated against the clientCA bundle is considered authoritative. - items: - type: string - type: array - emailHeaders: - description: emailHeaders is the set of headers - to check for the email address - items: - type: string - type: array - headers: - description: headers is the set of headers to check - for identity information - items: - type: string - type: array - loginURL: - description: |- - loginURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect interactive logins will be redirected here - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when login is set to true. - type: string - nameHeaders: - description: nameHeaders is the set of headers to - check for the display name - items: - type: string - type: array - preferredUsernameHeaders: - description: preferredUsernameHeaders is the set - of headers to check for the preferred username - items: - type: string - type: array - type: object - type: - description: type identifies the identity provider type - for this entry. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - templates: - description: templates allow you to customize pages like the - login page. - properties: - error: - description: |- - error is the name of a secret that specifies a go template to use to render error pages - during the authentication or grant flow. - The key "errors.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default error page is used. - If the specified template is not valid, the default error page is used. - If unspecified, the default error page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - login: - description: |- - login is the name of a secret that specifies a go template to use to render the login page. - The key "login.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default login page is used. - If the specified template is not valid, the default login page is used. - If unspecified, the default login page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - providerSelection: - description: |- - providerSelection is the name of a secret that specifies a go template to use to render - the provider selection page. - The key "providers.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default provider selection page is used. - If the specified template is not valid, the default provider selection page is used. - If unspecified, the default provider selection page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - tokenConfig: - description: tokenConfig contains options for authorization - and access tokens - properties: - accessTokenInactivityTimeout: - description: |- - accessTokenInactivityTimeout defines the token inactivity timeout - for tokens granted by any client. - The value represents the maximum amount of time that can occur between - consecutive uses of the token. Tokens become invalid if they are not - used within this temporal window. The user will need to acquire a new - token to regain access once a token times out. Takes valid time - duration string such as "5m", "1.5h" or "2h45m". The minimum allowed - value for duration is 300s (5 minutes). If the timeout is configured - per client, then that value takes precedence. If the timeout value is - not specified and the client does not override the value, then tokens - are valid until their lifetime. - - - WARNING: existing tokens' timeout will not be affected (lowered) by changing this value - type: string - accessTokenInactivityTimeoutSeconds: - description: 'accessTokenInactivityTimeoutSeconds - DEPRECATED: - setting this field has no effect.' - format: int32 - type: integer - accessTokenMaxAgeSeconds: - description: accessTokenMaxAgeSeconds defines the maximum - age of access tokens - format: int32 - type: integer - type: object - type: object - operatorhub: - description: |- - OperatorHub specifies the configuration for the Operator Lifecycle Manager in the HostedCluster. This is only configured at deployment time but the controller are not reconcilling over it. - The OperatorHub configuration will be constantly reconciled if catalog placement is management, but only on cluster creation otherwise. - properties: - disableAllDefaultSources: - description: |- - disableAllDefaultSources allows you to disable all the default hub - sources. If this is true, a specific entry in sources can be used to - enable a default source. If this is false, a specific entry in - sources can be used to disable or enable a default source. - type: boolean - sources: - description: |- - sources is the list of default hub sources and their configuration. - If the list is empty, it implies that the default hub sources are - enabled on the cluster unless disableAllDefaultSources is true. - If disableAllDefaultSources is true and sources is not empty, - the configuration present in sources will take precedence. The list of - default hub sources and their current state will always be reflected in - the status block. - items: - description: HubSource is used to specify the hub source - and its configuration - properties: - disabled: - description: disabled is used to disable a default hub - source on cluster - type: boolean - name: - description: name is the name of one of the default - hub sources - maxLength: 253 - minLength: 1 - type: string - type: object - type: array - type: object - proxy: - description: Proxy holds cluster-wide information on how to configure - default proxies for the cluster. - properties: - httpProxy: - description: httpProxy is the URL of the proxy for HTTP requests. Empty - means unset and will not result in an env var. - type: string - httpsProxy: - description: httpsProxy is the URL of the proxy for HTTPS - requests. Empty means unset and will not result in an env - var. - type: string - noProxy: - description: |- - noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. - Empty means unset and will not result in an env var. - type: string - readinessEndpoints: - description: readinessEndpoints is a list of endpoints used - to verify readiness of the proxy. - items: - type: string - type: array - trustedCA: - description: |- - trustedCA is a reference to a ConfigMap containing a CA certificate bundle. - The trustedCA field should only be consumed by a proxy validator. The - validator is responsible for reading the certificate bundle from the required - key "ca-bundle.crt", merging it with the system default trust bundle, - and writing the merged trust bundle to a ConfigMap named "trusted-ca-bundle" - in the "openshift-config-managed" namespace. Clients that expect to make - proxy connections must use the trusted-ca-bundle for all HTTPS requests to - the proxy, and may use the trusted-ca-bundle for non-proxy HTTPS requests as - well. - - - The namespace for the ConfigMap referenced by trustedCA is - "openshift-config". Here is an example ConfigMap (in yaml): - - - apiVersion: v1 - kind: ConfigMap - metadata: - name: user-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - Custom CA certificate bundle. - -----END CERTIFICATE----- - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - type: object - scheduler: - description: |- - Scheduler holds cluster-wide config information to run the Kubernetes Scheduler - and influence its placement decisions. The canonical name for this config is `cluster`. - properties: - defaultNodeSelector: - description: |- - defaultNodeSelector helps set the cluster-wide default node selector to - restrict pod placement to specific nodes. This is applied to the pods - created in all namespaces and creates an intersection with any existing - nodeSelectors already set on a pod, additionally constraining that pod's selector. - For example, - defaultNodeSelector: "type=user-node,region=east" would set nodeSelector - field in pod spec to "type=user-node,region=east" to all pods created - in all namespaces. Namespaces having project-wide node selectors won't be - impacted even if this field is set. This adds an annotation section to - the namespace. - For example, if a new namespace is created with - node-selector='type=user-node,region=east', - the annotation openshift.io/node-selector: type=user-node,region=east - gets added to the project. When the openshift.io/node-selector annotation - is set on the project the value is used in preference to the value we are setting - for defaultNodeSelector field. - For instance, - openshift.io/node-selector: "type=user-node,region=west" means - that the default of "type=user-node,region=east" set in defaultNodeSelector - would not be applied. - type: string - mastersSchedulable: - description: |- - MastersSchedulable allows masters nodes to be schedulable. When this flag is - turned on, all the master nodes in the cluster will be made schedulable, - so that workload pods can run on them. The default value for this field is false, - meaning none of the master nodes are schedulable. - Important Note: Once the workload pods start running on the master nodes, - extreme care must be taken to ensure that cluster-critical control plane components - are not impacted. - Please turn on this field after doing due diligence. - type: boolean - policy: - description: |- - DEPRECATED: the scheduler Policy API has been deprecated and will be removed in a future release. - policy is a reference to a ConfigMap containing scheduler policy which has - user specified predicates and priorities. If this ConfigMap is not available - scheduler will default to use DefaultAlgorithmProvider. - The namespace for this configmap is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - profile: - description: |- - profile sets which scheduling profile should be set in order to configure scheduling - decisions for new pods. - - - Valid values are "LowNodeUtilization", "HighNodeUtilization", "NoScoring" - Defaults to "LowNodeUtilization" - enum: - - "" - - LowNodeUtilization - - HighNodeUtilization - - NoScoring - type: string - profileCustomizations: - description: profileCustomizations contains configuration - for modifying the default behavior of existing scheduler - profiles. - properties: - dynamicResourceAllocation: - description: |- - dynamicResourceAllocation allows to enable or disable dynamic resource allocation within the scheduler. - Dynamic resource allocation is an API for requesting and sharing resources between pods and containers inside a pod. - Third-party resource drivers are responsible for tracking and allocating resources. - Different kinds of resources support arbitrary parameters for defining requirements and initialization. - Valid values are Enabled, Disabled and omitted. - When omitted, this means no opinion and the platform is left to choose a reasonable default, - which is subject to change over time. - The current default is Disabled. - enum: - - "" - - Enabled - - Disabled - type: string - type: object - type: object - secretRefs: - description: |- - SecretRefs holds references to any secrets referenced by configuration - entries. Entries can reference the secrets using local object references. - - - Deprecated - This field is deprecated and will be removed in a future release - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - type: object - controlPlaneReleaseImage: - description: |- - ControlPlaneReleaseImage specifies the desired OCP release payload for - control plane components running on the management cluster. - If not defined, ReleaseImage is used - type: string - controllerAvailabilityPolicy: - default: SingleReplica - description: |- - ControllerAvailabilityPolicy specifies the availability policy applied to - critical control plane components. The default value is SingleReplica. - type: string - x-kubernetes-validations: - - message: ControllerAvailabilityPolicy is immutable - rule: self == oldSelf - dns: - description: DNSSpec specifies the DNS configuration in the cluster. - properties: - baseDomain: - description: BaseDomain is the base domain of the cluster. - type: string - baseDomainPrefix: - description: |- - BaseDomainPrefix is the base domain prefix of the cluster. - defaults to clusterName if not set - type: string - privateZoneID: - description: |- - PrivateZoneID is the Hosted Zone ID where all the DNS records that are only - available internally to the cluster exist. - type: string - publicZoneID: - description: |- - PublicZoneID is the Hosted Zone ID where all the DNS records that are - publicly accessible to the internet exist. - type: string - required: - - baseDomain - type: object - etcd: - description: |- - Etcd contains metadata about the etcd cluster the hypershift managed Openshift control plane components - use to store data. - properties: - managed: - description: Managed specifies the behavior of an etcd cluster - managed by HyperShift. - properties: - storage: - description: Storage specifies how etcd data is persisted. - properties: - persistentVolume: - description: |- - PersistentVolume is the configuration for PersistentVolume etcd storage. - With this implementation, a PersistentVolume will be allocated for every - etcd member (either 1 or 3 depending on the HostedCluster control plane - availability configuration). - properties: - size: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Size is the minimum size of the data - volume for each etcd member. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: Etcd PV storage size is immutable - rule: self == oldSelf - storageClassName: - description: |- - StorageClassName is the StorageClass of the data volume for each etcd member. - - - See https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. - type: string - type: object - restoreSnapshotURL: - description: |- - RestoreSnapshotURL allows an optional URL to be provided where - an etcd snapshot can be downloaded, for example a pre-signed URL - referencing a storage service. - This snapshot will be restored on initial startup, only when the etcd PV - is empty. - items: - type: string - type: array - x-kubernetes-validations: - - message: RestoreSnapshotURL shouldn't contain more than - 1 entry - rule: self.size() <= 1 - type: - description: Type is the kind of persistent storage implementation - to use for etcd. - enum: - - PersistentVolume - type: string - required: - - type - type: object - required: - - storage - type: object - managementType: - description: ManagementType defines how the etcd cluster is managed. - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: |- - Unmanaged specifies configuration which enables the control plane to - integrate with an eternally managed etcd cluster. - properties: - endpoint: - description: |- - Endpoint is the full etcd cluster client endpoint URL. For example: - - - https://etcd-client:2379 - - - If the URL uses an HTTPS scheme, the TLS field is required. - pattern: ^https:// - type: string - tls: - description: TLS specifies TLS configuration for HTTPS etcd - client endpoints. - properties: - clientSecret: - description: |- - ClientSecret refers to a secret for client mTLS authentication with the etcd cluster. It - may have the following key/value pairs: - - - etcd-client-ca.crt: Certificate Authority value - etcd-client.crt: Client certificate value - etcd-client.key: Client certificate key value - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - clientSecret - type: object - required: - - endpoint - - tls - type: object - required: - - managementType - type: object - fips: - description: FIPS specifies if the nodes for the cluster will be running - in FIPS mode - type: boolean - imageContentSources: - description: ImageContentSources lists sources/repositories for the - release-image content. - items: - description: |- - ImageContentSource specifies image mirrors that can be used by cluster nodes - to pull content. For cluster workloads, if a container image registry host of - the pullspec matches Source then one of the Mirrors are substituted as hosts - in the pullspec and tried in order to fetch the image. - properties: - mirrors: - description: Mirrors are one or more repositories that may also - contain the same images. - items: - type: string - type: array - source: - description: |- - Source is the repository that users refer to, e.g. in image pull - specifications. - type: string - required: - - source - type: object - type: array - infraID: - type: string - infrastructureAvailabilityPolicy: - default: SingleReplica - description: |- - InfrastructureAvailabilityPolicy specifies the availability policy applied - to infrastructure services which run on cluster nodes. The default value is - SingleReplica. - type: string - issuerURL: - description: |- - IssuerURL is an OIDC issuer URL which is used as the issuer in all - ServiceAccount tokens generated by the control plane API server. The - default value is kubernetes.default.svc, which only works for in-cluster - validation. - type: string - kubeconfig: - description: KubeConfig specifies the name and key for the kubeconfig - secret - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - machineCIDR: - description: |- - deprecated - use networking.MachineNetwork - type: string - networkType: - description: |- - deprecated - use networking.NetworkType - NetworkType specifies the SDN provider used for cluster networking. - enum: - - OpenShiftSDN - - Calico - - OVNKubernetes - - Other - type: string - networking: - description: |- - Networking specifies network configuration for the cluster. - Temporarily optional for backward compatibility, required in future releases. - properties: - apiServer: - description: |- - APIServer contains advanced network settings for the API server that affect - how the APIServer is exposed inside a cluster node. - properties: - advertiseAddress: - description: |- - AdvertiseAddress is the address that nodes will use to talk to the API - server. This is an address associated with the loopback adapter of each - node. If not specified, 172.20.0.1 is used. - type: string - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is an allow list of CIDR blocks that can access the APIServer - If not specified, traffic is allowed from all addresses. - This depends on underlying support by the cloud provider for Service LoadBalancerSourceRanges - items: - pattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$ - type: string - type: array - port: - description: |- - Port is the port at which the APIServer is exposed inside a node. Other - pods using host networking cannot listen on this port. If not specified, - 6443 is used. - format: int32 - type: integer - type: object - clusterNetwork: - default: - - cidr: 10.132.0.0/14 - description: |- - ClusterNetwork is the list of IP address pools for pods. - TODO: make this required in the next version of the API - items: - description: |- - ClusterNetworkEntry is a single IP address block for pod IP blocks. IP blocks - are allocated with size 2^HostSubnetLength. - properties: - cidr: - description: CIDR is the IP block address pool. - type: string - hostPrefix: - description: |- - HostPrefix is the prefix size to allocate to each node from the CIDR. - For example, 24 would allocate 2^8=256 adresses to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - type: integer - required: - - cidr - type: object - type: array - machineCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use MachineNetwork instead - format: cidr - type: string - machineNetwork: - description: |- - MachineNetwork is the list of IP address pools for machines. - TODO: make this required in the next version of the API - items: - description: MachineNetworkEntry is a single IP address block - for node IP blocks. - properties: - cidr: - description: CIDR is the IP block address pool for machines - within the cluster. - type: string - required: - - cidr - type: object - type: array - networkType: - default: OVNKubernetes - description: NetworkType specifies the SDN provider used for cluster - networking. - enum: - - OpenShiftSDN - - Calico - - OVNKubernetes - - Other - type: string - podCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use ClusterNetwork instead - format: cidr - type: string - serviceCIDR: - description: |- - Deprecated - This field will be removed in the next API release. - Use ServiceNetwork instead - format: cidr - type: string - serviceNetwork: - default: - - cidr: 172.31.0.0/16 - description: |- - ServiceNetwork is the list of IP address pools for services. - NOTE: currently only one entry is supported. - TODO: make this required in the next version of the API - items: - description: ServiceNetworkEntry is a single IP address block - for the service network. - properties: - cidr: - description: CIDR is the IP block address pool for services - within the cluster. - type: string - required: - - cidr - type: object - type: array - required: - - networkType - type: object - nodeSelector: - additionalProperties: - type: string - description: NodeSelector when specified, must be true for the pods - managed by the HostedCluster to be scheduled. - type: object - olmCatalogPlacement: - default: management - description: |- - OLMCatalogPlacement specifies the placement of OLM catalog components. By default, - this is set to management and OLM catalog components are deployed onto the management - cluster. If set to guest, the OLM catalog components will be deployed onto the guest - cluster. - enum: - - management - - guest - type: string - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - PlatformSpec specifies the underlying infrastructure provider for the cluster - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies configuration for agent-based installations. - properties: - agentNamespace: - description: AgentNamespace is the namespace where to search - for Agents for this cluster - type: string - required: - - agentNamespace - type: object - aws: - description: AWS specifies configuration for clusters running - on Amazon Web Services. - properties: - additionalAllowedPrincipals: - description: |- - AdditionalAllowedPrincipals specifies a list of additional allowed principal ARNs - to be added to the hosted control plane's VPC Endpoint Service to enable additional - VPC Endpoint connection requests to be automatically accepted. - See https://docs.aws.amazon.com/vpc/latest/privatelink/configure-endpoint-service.html - for more details around VPC Endpoint Service allowed principals. - items: - type: string - type: array - cloudProviderConfig: - description: |- - CloudProviderConfig specifies AWS networking configuration for the control - plane. - This is mainly used for cloud provider controller config: - https://github.com/kubernetes/kubernetes/blob/f5be5052e3d0808abb904aebd3218fe4a5c2dd82/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L1347-L1364 - TODO(dan): should this be named AWSNetworkConfig? - properties: - subnet: - description: Subnet is the subnet to use for control plane - cloud resources. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify - an AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - vpc: - description: VPC is the VPC to use for control plane cloud - resources. - type: string - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - type: string - required: - - vpc - type: object - controlPlaneOperatorCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - endpointAccess: - default: Public - description: |- - EndpointAccess specifies the publishing scope of cluster endpoints. The - default is Public. - enum: - - Public - - PublicAndPrivate - - Private - type: string - kubeCloudControllerCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - multiArch: - default: false - description: |- - MultiArch specifies whether the Hosted Cluster will be expected to support NodePools with different - CPU architectures, i.e., supporting arm64 NodePools and supporting amd64 NodePools on the same Hosted Cluster. - type: boolean - nodePoolManagementCreds: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the AWS region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot AMI for a given release. - type: string - resourceTags: - description: |- - ResourceTags is a list of additional tags to apply to AWS resources created - for the cluster. See - https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - roles: - description: |- - Deprecated - This field will be removed in the next API release. - Use RolesRef instead. - items: - properties: - arn: - type: string - name: - type: string - namespace: - type: string - required: - - arn - - name - - namespace - type: object - type: array - rolesRef: - description: |- - RolesRef contains references to various AWS IAM roles required to enable - integrations such as OIDC. - properties: - controlPlaneOperatorARN: - description: "ControlPlaneOperatorARN is an ARN value - referencing a role appropriate for the Control Plane - Operator.\n\n\nThe following is an example of a valid - policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"ec2:CreateVpcEndpoint\",\n\t\t\t\t\"ec2:DescribeVpcEndpoints\",\n\t\t\t\t\"ec2:ModifyVpcEndpoint\",\n\t\t\t\t\"ec2:DeleteVpcEndpoints\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\",\n\t\t\t\t\"route53:ListResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - \"arn:aws:route53:::%s\"\n\t\t}\n\t]\n}" - type: string - imageRegistryARN: - description: "ImageRegistryARN is an ARN value referencing - a role appropriate for the Image Registry Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"s3:CreateBucket\",\n\t\t\t\t\"s3:DeleteBucket\",\n\t\t\t\t\"s3:PutBucketTagging\",\n\t\t\t\t\"s3:GetBucketTagging\",\n\t\t\t\t\"s3:PutBucketPublicAccessBlock\",\n\t\t\t\t\"s3:GetBucketPublicAccessBlock\",\n\t\t\t\t\"s3:PutEncryptionConfiguration\",\n\t\t\t\t\"s3:GetEncryptionConfiguration\",\n\t\t\t\t\"s3:PutLifecycleConfiguration\",\n\t\t\t\t\"s3:GetLifecycleConfiguration\",\n\t\t\t\t\"s3:GetBucketLocation\",\n\t\t\t\t\"s3:ListBucket\",\n\t\t\t\t\"s3:GetObject\",\n\t\t\t\t\"s3:PutObject\",\n\t\t\t\t\"s3:DeleteObject\",\n\t\t\t\t\"s3:ListBucketMultipartUploads\",\n\t\t\t\t\"s3:AbortMultipartUpload\",\n\t\t\t\t\"s3:ListMultipartUploadParts\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - ingressARN: - description: "The referenced role must have a trust relationship - that allows it to be assumed via web identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ .ProviderName - }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nIngressARN - is an ARN value referencing a role appropriate for the - Ingress Operator.\n\n\nThe following is an example of - a valid policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"elasticloadbalancing:DescribeLoadBalancers\",\n\t\t\t\t\"tag:GetResources\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - [\n\t\t\t\t\"arn:aws:route53:::PUBLIC_ZONE_ID\",\n\t\t\t\t\"arn:aws:route53:::PRIVATE_ZONE_ID\"\n\t\t\t]\n\t\t}\n\t]\n}" - type: string - kubeCloudControllerARN: - description: |- - KubeCloudControllerARN is an ARN value referencing a role appropriate for the KCM/KCC. - - - The following is an example of a valid policy document: - - - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "ec2:DescribeInstances", - "ec2:DescribeImages", - "ec2:DescribeRegions", - "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVolumes", - "ec2:CreateSecurityGroup", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:ModifyInstanceAttribute", - "ec2:ModifyVolume", - "ec2:AttachVolume", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateRoute", - "ec2:DeleteRoute", - "ec2:DeleteSecurityGroup", - "ec2:DeleteVolume", - "ec2:DetachVolume", - "ec2:RevokeSecurityGroupIngress", - "ec2:DescribeVpcs", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:AttachLoadBalancerToSubnets", - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", - "elasticloadbalancing:CreateLoadBalancer", - "elasticloadbalancing:CreateLoadBalancerPolicy", - "elasticloadbalancing:CreateLoadBalancerListeners", - "elasticloadbalancing:ConfigureHealthCheck", - "elasticloadbalancing:DeleteLoadBalancer", - "elasticloadbalancing:DeleteLoadBalancerListeners", - "elasticloadbalancing:DescribeLoadBalancers", - "elasticloadbalancing:DescribeLoadBalancerAttributes", - "elasticloadbalancing:DetachLoadBalancerFromSubnets", - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:ModifyLoadBalancerAttributes", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:CreateListener", - "elasticloadbalancing:CreateTargetGroup", - "elasticloadbalancing:DeleteListener", - "elasticloadbalancing:DeleteTargetGroup", - "elasticloadbalancing:DescribeListeners", - "elasticloadbalancing:DescribeLoadBalancerPolicies", - "elasticloadbalancing:DescribeTargetGroups", - "elasticloadbalancing:DescribeTargetHealth", - "elasticloadbalancing:ModifyListener", - "elasticloadbalancing:ModifyTargetGroup", - "elasticloadbalancing:RegisterTargets", - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener", - "iam:CreateServiceLinkedRole", - "kms:DescribeKey" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ] - } - type: string - networkARN: - description: "NetworkARN is an ARN value referencing a - role appropriate for the Network Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInstanceStatus\",\n \"ec2:DescribeInstanceTypes\",\n - \ \"ec2:UnassignPrivateIpAddresses\",\n \"ec2:AssignPrivateIpAddresses\",\n - \ \"ec2:UnassignIpv6Addresses\",\n \"ec2:AssignIpv6Addresses\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeNetworkInterfaces\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - nodePoolManagementARN: - description: "NodePoolManagementARN is an ARN value referencing - a role appropriate for the CAPI Controller.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n - \ \"Version\": \"2012-10-17\",\n \"Statement\": [\n - \ {\n \"Action\": [\n \"ec2:AllocateAddress\",\n - \ \"ec2:AssociateRouteTable\",\n \"ec2:AttachInternetGateway\",\n - \ \"ec2:AuthorizeSecurityGroupIngress\",\n \"ec2:CreateInternetGateway\",\n - \ \"ec2:CreateNatGateway\",\n \"ec2:CreateRoute\",\n - \ \"ec2:CreateRouteTable\",\n \"ec2:CreateSecurityGroup\",\n - \ \"ec2:CreateSubnet\",\n \"ec2:CreateTags\",\n - \ \"ec2:DeleteInternetGateway\",\n \"ec2:DeleteNatGateway\",\n - \ \"ec2:DeleteRouteTable\",\n \"ec2:DeleteSecurityGroup\",\n - \ \"ec2:DeleteSubnet\",\n \"ec2:DeleteTags\",\n - \ \"ec2:DescribeAccountAttributes\",\n \"ec2:DescribeAddresses\",\n - \ \"ec2:DescribeAvailabilityZones\",\n \"ec2:DescribeImages\",\n - \ \"ec2:DescribeInstances\",\n \"ec2:DescribeInternetGateways\",\n - \ \"ec2:DescribeNatGateways\",\n \"ec2:DescribeNetworkInterfaces\",\n - \ \"ec2:DescribeNetworkInterfaceAttribute\",\n - \ \"ec2:DescribeRouteTables\",\n \"ec2:DescribeSecurityGroups\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeVpcs\",\n - \ \"ec2:DescribeVpcAttribute\",\n \"ec2:DescribeVolumes\",\n - \ \"ec2:DetachInternetGateway\",\n \"ec2:DisassociateRouteTable\",\n - \ \"ec2:DisassociateAddress\",\n \"ec2:ModifyInstanceAttribute\",\n - \ \"ec2:ModifyNetworkInterfaceAttribute\",\n \"ec2:ModifySubnetAttribute\",\n - \ \"ec2:ReleaseAddress\",\n \"ec2:RevokeSecurityGroupIngress\",\n - \ \"ec2:RunInstances\",\n \"ec2:TerminateInstances\",\n - \ \"tag:GetResources\",\n \"ec2:CreateLaunchTemplate\",\n - \ \"ec2:CreateLaunchTemplateVersion\",\n \"ec2:DescribeLaunchTemplates\",\n - \ \"ec2:DescribeLaunchTemplateVersions\",\n \"ec2:DeleteLaunchTemplate\",\n - \ \"ec2:DeleteLaunchTemplateVersions\"\n ],\n - \ \"Resource\": [\n \"*\"\n ],\n \"Effect\": - \"Allow\"\n },\n {\n \"Condition\": {\n \"StringLike\": - {\n \"iam:AWSServiceName\": \"elasticloadbalancing.amazonaws.com\"\n - \ }\n },\n \"Action\": [\n \"iam:CreateServiceLinkedRole\"\n - \ ],\n \"Resource\": [\n \"arn:*:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing\"\n - \ ],\n \"Effect\": \"Allow\"\n },\n {\n \"Action\": - [\n \"iam:PassRole\"\n ],\n \"Resource\": - [\n \"arn:*:iam::*:role/*-worker-role\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n\t {\n\t \t\"Effect\": - \"Allow\",\n\t \t\"Action\": [\n\t \t\t\"kms:Decrypt\",\n\t - \ \t\t\"kms:Encrypt\",\n\t \t\t\"kms:GenerateDataKey\",\n\t - \ \t\t\"kms:GenerateDataKeyWithoutPlainText\",\n\t \t\t\"kms:DescribeKey\"\n\t - \ \t],\n\t \t\"Resource\": \"*\"\n\t },\n\t {\n\t - \ \t\"Effect\": \"Allow\",\n\t \t\"Action\": [\n\t - \ \t\t\"kms:RevokeGrant\",\n\t \t\t\"kms:CreateGrant\",\n\t - \ \t\t\"kms:ListGrants\"\n\t \t],\n\t \t\"Resource\": - \"*\",\n\t \t\"Condition\": {\n\t \t\t\"Bool\": {\n\t - \ \t\t\t\"kms:GrantIsForAWSResource\": true\n\t \t\t}\n\t - \ \t}\n\t }\n ]\n}" - type: string - storageARN: - description: "StorageARN is an ARN value referencing a - role appropriate for the Storage Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:AttachVolume\",\n\t\t\t\t\"ec2:CreateSnapshot\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"ec2:CreateVolume\",\n\t\t\t\t\"ec2:DeleteSnapshot\",\n\t\t\t\t\"ec2:DeleteTags\",\n\t\t\t\t\"ec2:DeleteVolume\",\n\t\t\t\t\"ec2:DescribeInstances\",\n\t\t\t\t\"ec2:DescribeSnapshots\",\n\t\t\t\t\"ec2:DescribeTags\",\n\t\t\t\t\"ec2:DescribeVolumes\",\n\t\t\t\t\"ec2:DescribeVolumesModifications\",\n\t\t\t\t\"ec2:DetachVolume\",\n\t\t\t\t\"ec2:ModifyVolume\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - required: - - controlPlaneOperatorARN - - imageRegistryARN - - ingressARN - - kubeCloudControllerARN - - networkARN - - nodePoolManagementARN - - storageARN - type: object - serviceEndpoints: - description: |- - ServiceEndpoints specifies optional custom endpoints which will override - the default service endpoint of specific AWS Services. - - - There must be only one ServiceEndpoint for a given service name. - items: - description: |- - AWSServiceEndpoint stores the configuration for services to - override existing defaults of AWS Services. - properties: - name: - description: |- - Name is the name of the AWS service. - This must be provided and cannot be empty. - type: string - url: - description: |- - URL is fully qualified URI with scheme https, that overrides the default generated - endpoint for a client. - This must be provided and cannot be empty. - pattern: ^https:// - type: string - required: - - name - - url - type: object - type: array - required: - - controlPlaneOperatorCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - rolesRef - type: object - azure: - description: Azure defines azure specific settings - properties: - cloud: - default: AzurePublicCloud - description: 'The cloud environment identifier, valid values - could be found here: https://github.com/Azure/go-autorest/blob/4c0e21ca2bbb3251fe7853e6f9df6397f53dd419/autorest/azure/environments.go#L33' - enum: - - AzurePublicCloud - - AzureUSGovernmentCloud - - AzureChinaCloud - - AzureGermanCloud - type: string - credentials: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - location: - type: string - resourceGroup: - type: string - securityGroupID: - type: string - subnetID: - type: string - subscriptionID: - type: string - vnetID: - type: string - required: - - credentials - - location - - resourceGroup - - securityGroupID - - subnetID - - subscriptionID - - vnetID - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: KubeVirt defines KubeVirt specific settings for cluster - components. - properties: - baseDomainPassthrough: - description: |- - BaseDomainPassthrough toggles whether or not an automatically - generated base domain for the guest cluster should be used that - is a subdomain of the management cluster's *.apps DNS. - - - For the KubeVirt platform, the basedomain can be autogenerated using - the *.apps domain of the management/infra hosting cluster - This makes the guest cluster's base domain a subdomain of the - hypershift infra/mgmt cluster's base domain. - - - Example: - Infra/Mgmt cluster's DNS - Base: example.com - Cluster: mgmt-cluster.example.com - Apps: *.apps.mgmt-cluster.example.com - KubeVirt Guest cluster's DNS - Base: apps.mgmt-cluster.example.com - Cluster: guest.apps.mgmt-cluster.example.com - Apps: *.apps.guest.apps.mgmt-cluster.example.com - - - This is possible using OCP wildcard routes - type: boolean - x-kubernetes-validations: - - message: baseDomainPassthrough is immutable - rule: self == oldSelf - credentials: - description: |- - Credentials defines the client credentials used when creating KubeVirt virtual machines. - Defining credentials is only necessary when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - generateID: - description: |- - GenerateID is used to uniquely apply a name suffix to resources associated with - kubevirt infrastructure resources - maxLength: 11 - type: string - x-kubernetes-validations: - - message: Kubevirt GenerateID is immutable once set - rule: self == oldSelf - storageDriver: - description: |- - StorageDriver defines how the KubeVirt CSI driver exposes StorageClasses on - the infra cluster (hosting the VMs) to the guest cluster. - properties: - manual: - description: |- - Manual is used to explicilty define how the infra storageclasses are - mapped to guest storageclasses - properties: - storageClassMapping: - description: |- - StorageClassMapping maps StorageClasses on the infra cluster hosting - the KubeVirt VMs to StorageClasses that are made available within the - Guest Cluster. - - - NOTE: It is possible that not all capablities of an infra cluster's - storageclass will be present for the corresponding guest clusters storageclass. - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestStorageClassName: - description: |- - GuestStorageClassName is the name that the corresponding storageclass will - be called within the guest cluster - type: string - infraStorageClassName: - description: |- - InfraStorageClassName is the name of the infra cluster storage class that - will be exposed to the guest. - type: string - required: - - guestStorageClassName - - infraStorageClassName - type: object - type: array - x-kubernetes-validations: - - message: storageClassMapping is immutable - rule: self == oldSelf - volumeSnapshotClassMapping: - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestVolumeSnapshotClassName: - description: |- - GuestVolumeSnapshotClassName is the name that the corresponding volumeSnapshotClass will - be called within the guest cluster - type: string - infraVolumeSnapshotClassName: - description: |- - InfraStorageClassName is the name of the infra cluster volume snapshot class that - will be exposed to the guest. - type: string - required: - - guestVolumeSnapshotClassName - - infraVolumeSnapshotClassName - type: object - type: array - x-kubernetes-validations: - - message: volumeSnapshotClassMapping is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver.Manual is immutable - rule: self == oldSelf - type: - default: Default - description: Type represents the type of kubevirt csi - driver configuration to use - enum: - - None - - Default - - Manual - type: string - x-kubernetes-validations: - - message: storageDriver.Type is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: Kubevirt GenerateID is required once set - rule: '!has(oldSelf.generateID) || has(self.generateID)' - powervs: - description: |- - PowerVS specifies configuration for clusters running on IBMCloud Power VS Service. - This field is immutable. Once set, It can't be changed. - properties: - accountID: - description: |- - AccountID is the IBMCloud account id. - This field is immutable. Once set, It can't be changed. - type: string - cisInstanceCRN: - description: |- - CISInstanceCRN is the IBMCloud CIS Service Instance's Cloud Resource Name - This field is immutable. Once set, It can't be changed. - pattern: '^crn:' - type: string - imageRegistryOperatorCloudCreds: - description: |- - ImageRegistryOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for image registry operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - ingressOperatorCloudCreds: - description: |- - IngressOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for ingress operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeCloudControllerCreds: - description: |- - KubeCloudControllerCreds is a reference to a secret containing cloud - credentials with permissions matching the cloud controller policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "cloud controller policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - nodePoolManagementCreds: - description: |- - NodePoolManagementCreds is a reference to a secret containing cloud - credentials with permissions matching the node pool management policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "node pool management policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the IBMCloud region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot image for a given release. - This field is immutable. Once set, It can't be changed. - type: string - resourceGroup: - description: |- - ResourceGroup is the IBMCloud Resource Group in which the cluster resides. - This field is immutable. Once set, It can't be changed. - type: string - serviceInstanceID: - description: |- - ServiceInstance is the reference to the Power VS service on which the server instance(VM) will be created. - Power VS service is a container for all Power VS instances at a specific geographic region. - serviceInstance can be created via IBM Cloud catalog or CLI. - ServiceInstanceID is the unique identifier that can be obtained from IBM Cloud UI or IBM Cloud cli. - - - More detail about Power VS service instance. - https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server - - - This field is immutable. Once set, It can't be changed. - type: string - storageOperatorCloudCreds: - description: |- - StorageOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for storage operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - subnet: - description: |- - Subnet is the subnet to use for control plane cloud resources. - This field is immutable. Once set, It can't be changed. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - vpc: - description: |- - VPC specifies IBM Cloud PowerVS Load Balancing configuration for the control - plane. - This field is immutable. Once set, It can't be changed. - properties: - name: - description: |- - Name for VPC to used for all the service load balancer. - This field is immutable. Once set, It can't be changed. - type: string - region: - description: |- - Region is the IBMCloud region in which VPC gets created, this VPC used for all the ingress traffic - into the OCP cluster. - This field is immutable. Once set, It can't be changed. - type: string - subnet: - description: |- - Subnet is the subnet to use for load balancer. - This field is immutable. Once set, It can't be changed. - type: string - zone: - description: |- - Zone is the availability zone where load balancer cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - name - - region - type: object - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - accountID - - cisInstanceCRN - - imageRegistryOperatorCloudCreds - - ingressOperatorCloudCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - resourceGroup - - serviceInstanceID - - storageOperatorCloudCreds - - subnet - - vpc - - zone - type: object - type: - description: Type is the type of infrastructure provider for the - cluster. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - type: string - required: - - type - type: object - podCIDR: - description: |- - deprecated - use networking.ClusterNetwork - type: string - pullSecret: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - releaseImage: - description: ReleaseImage is the release image applied to the hosted - control plane. - type: string - secretEncryption: - description: |- - SecretEncryption contains metadata about the kubernetes secret encryption strategy being used for the - cluster when applicable. - properties: - aescbc: - description: AESCBC defines metadata about the AESCBC secret encryption - strategy - properties: - activeKey: - description: ActiveKey defines the active key used to encrypt - new secrets - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - activeKey - type: object - kms: - description: KMS defines metadata about the kms secret encryption - strategy - properties: - aws: - description: AWS defines metadata about the configuration - of the AWS KMS Secret Encryption provider - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - auth: - description: Auth defines metadata about the management - of credentials used to interact with AWS KMS - properties: - awsKms: - description: "The referenced role must have a trust - relationship that allows it to be assumed via web - identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ - .ProviderName }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nAWSKMSARN - is an ARN value referencing a role appropriate for - managing the auth via the AWS KMS key.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n \t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"kms:Encrypt\",\n\t\t\t\t\"kms:Decrypt\",\n\t\t\t\t\"kms:ReEncrypt*\",\n\t\t\t\t\"kms:GenerateDataKey*\",\n\t\t\t\t\"kms:DescribeKey\"\n\t\t\t],\n\t\t\t\"Resource\": - %q\n\t\t}\n\t]\n}" - type: string - credentials: - description: |- - Deprecated - This field is deprecated and will be removed in a future release. Use AWSKMSRoleARN instead. - Credentials contains the name of the secret that holds the aws credentials that can be used - to make the necessary KMS calls. It should at key AWSCredentialsFileSecretKey contain the - aws credentials file that can be used to configure AWS SDKs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - awsKms - - credentials - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - region: - description: Region contains the AWS region - type: string - required: - - activeKey - - auth - - region - type: object - azure: - description: Azure defines metadata about the configuration - of the Azure KMS Secret Encryption provider using Azure - key vault - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - required: - - activeKey - type: object - ibmcloud: - description: IBMCloud defines metadata for the IBM Cloud KMS - encryption strategy - properties: - auth: - description: Auth defines metadata for how authentication - is done with IBM Cloud KMS - properties: - managed: - description: |- - Managed defines metadata around the service to service authentication strategy for the IBM Cloud - KMS system (all provider managed). - type: object - type: - description: Type defines the IBM Cloud KMS authentication - strategy - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: Unmanaged defines the auth metadata the - customer provides to interact with IBM Cloud KMS - properties: - credentials: - description: |- - Credentials should reference a secret with a key field of IBMCloudIAMAPIKeySecretKey that contains a apikey to - call IBM Cloud KMS APIs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - credentials - type: object - required: - - type - type: object - keyList: - description: KeyList defines the list of keys used for - data encryption - items: - description: IBMCloudKMSKeyEntry defines metadata for - an IBM Cloud KMS encryption key - properties: - correlationID: - description: CorrelationID is an identifier used - to track all api call usage from hypershift - type: string - crkID: - description: CRKID is the customer rook key id - type: string - instanceID: - description: InstanceID is the id for the key protect - instance - type: string - keyVersion: - description: |- - KeyVersion is a unique number associated with the key. The number increments whenever a new - key is enabled for data encryption. - type: integer - url: - description: URL is the url to call key protect - apis over - pattern: ^https:// - type: string - required: - - correlationID - - crkID - - instanceID - - keyVersion - - url - type: object - type: array - region: - description: Region is the IBM Cloud region - type: string - required: - - auth - - keyList - - region - type: object - provider: - description: Provider defines the KMS provider - enum: - - IBMCloud - - AWS - - Azure - type: string - required: - - provider - type: object - type: - description: Type defines the type of kube secret encryption being - used - enum: - - kms - - aescbc - type: string - required: - - type - type: object - serviceAccountSigningKey: - description: |- - ServiceAccountSigningKey is a reference to a secret containing the private key - used by the service account token issuer. The secret is expected to contain - a single key named "key". If not specified, a service account signing key will - be generated automatically for the cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - serviceCIDR: - description: |- - deprecated - use networking.ServiceNetwork - type: string - services: - description: |- - Services defines metadata about how control plane services are published - in the management cluster. - items: - description: |- - ServicePublishingStrategyMapping specifies how individual control plane - services are published from the hosting cluster of a control plane. - properties: - service: - description: Service identifies the type of service being published. - enum: - - APIServer - - OAuthServer - - OIDC - - Konnectivity - - Ignition - - OVNSbDb - type: string - servicePublishingStrategy: - description: ServicePublishingStrategy specifies how to publish - Service. - properties: - loadBalancer: - description: LoadBalancer configures exposing a service - using a LoadBalancer. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the LoadBalancer. - type: string - type: object - nodePort: - description: NodePort configures exposing a service using - a NodePort. - properties: - address: - description: Address is the host/ip that the NodePort - service is exposed over. - type: string - port: - description: |- - Port is the port of the NodePort service. If <=0, the port is dynamically - assigned when the service is created. - format: int32 - type: integer - required: - - address - type: object - route: - description: Route configures exposing a service using a - Route. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the Route. - type: string - type: object - type: - description: Type is the publishing strategy used for the - service. - enum: - - LoadBalancer - - NodePort - - Route - - None - - S3 - type: string - required: - - type - type: object - required: - - service - - servicePublishingStrategy - type: object - type: array - sshKey: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - tolerations: - description: Tolerations when specified, define what custome tolerations - are added to the hcp pods. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - updateService: - description: |- - updateService may be used to specify the preferred upstream update service. - By default it will use the appropriate update service for the cluster and region. - type: string - required: - - dns - - etcd - - infraID - - issuerURL - - platform - - pullSecret - - releaseImage - - services - - sshKey - type: object - status: - description: HostedControlPlaneStatus defines the observed state of HostedControlPlane - properties: - conditions: - description: |- - Condition contains details for one aspect of the current state of the HostedControlPlane. - Current condition types are: "Available" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint contains the endpoint information by which - external clients can access the control plane. This is populated - after the infrastructure is ready. - properties: - host: - description: Host is the hostname on which the API server is serving. - type: string - port: - description: Port is the port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - externalManagedControlPlane: - default: true - description: |- - ExternalManagedControlPlane indicates to cluster-api that the control plane - is managed by an external service. - https://github.com/kubernetes-sigs/cluster-api/blob/65e5385bffd71bf4aad3cf34a537f11b217c7fab/controllers/machine_controller.go#L468 - type: boolean - initialized: - default: false - description: |- - Initialized denotes whether or not the control plane has - provided a kubeadm-config. - Once this condition is marked true, its value is never changed. See the Ready condition for an indication of - the current readiness of the cluster's control plane. - This satisfies CAPI contract https://github.com/kubernetes-sigs/cluster-api/blob/cd3a694deac89d5ebeb888307deaa61487207aa0/controllers/cluster_controller_phases.go#L238-L252 - type: boolean - kubeConfig: - description: |- - KubeConfig is a reference to the secret containing the default kubeconfig - for this control plane. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - kubeadminPassword: - description: |- - KubeadminPassword is a reference to the secret containing the initial kubeadmin password - for the guest cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - lastReleaseImageTransitionTime: - description: |- - lastReleaseImageTransitionTime is the time of the last update to the current - releaseImage property. - - - Deprecated: Use versionStatus.history[0].startedTime instead. - format: date-time - type: string - nodeCount: - description: NodeCount tracks the number of nodes in the HostedControlPlane. - type: integer - oauthCallbackURLTemplate: - description: |- - OAuthCallbackURLTemplate contains a template for the URL to use as a callback - for identity providers. The [identity-provider-name] placeholder must be replaced - with the name of an identity provider defined on the HostedCluster. - This is populated after the infrastructure is ready. - type: string - platform: - description: Platform contains platform-specific status of the HostedCluster - properties: - aws: - description: AWSPlatformStatus contains status specific to the - AWS platform - properties: - defaultWorkerSecurityGroupID: - description: |- - DefaultWorkerSecurityGroupID is the ID of a security group created by - the control plane operator. It is always added to worker machines in - addition to any security groups specified in the NodePool. - type: string - type: object - type: object - ready: - default: false - description: |- - Ready denotes that the HostedControlPlane API Server is ready to - receive requests - This satisfies CAPI contract https://github.com/kubernetes-sigs/cluster-api/blob/cd3a694deac89d5ebeb888307deaa61487207aa0/controllers/cluster_controller_phases.go#L226-L230 - type: boolean - releaseImage: - description: |- - ReleaseImage is the release image applied to the hosted control plane. - - - Deprecated: Use versionStatus.desired.image instead. - type: string - version: - description: |- - Version is the semantic version of the release applied by - the hosted control plane operator - - - Deprecated: Use versionStatus.desired.version instead. - type: string - versionStatus: - description: |- - versionStatus is the status of the release version applied by the - hosted control plane operator. - properties: - availableUpdates: - description: |- - availableUpdates contains updates recommended for this - cluster. Updates which appear in conditionalUpdates but not in - availableUpdates may expose this cluster to known issues. This list - may be empty if no updates are recommended, if the update service - is unavailable, or if an invalid channel has been specified. - items: - description: Release represents an OpenShift release image and - associated metadata. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - nullable: true - type: array - conditionalUpdates: - description: |- - conditionalUpdates contains the list of updates that may be - recommended for this cluster if it meets specific required - conditions. Consumers interested in the set of updates that are - actually recommended for this cluster should use - availableUpdates. This list may be empty if no updates are - recommended, if the update service is unavailable, or if an empty - or invalid channel has been specified. - items: - description: |- - ConditionalUpdate represents an update which is recommended to some - clusters on the version the current cluster is reconciling, but which - may not be recommended for the current cluster. - properties: - conditions: - description: |- - conditions represents the observations of the conditional update's - current status. Known types are: - * Recommended, for whether the update is recommended for the current cluster. - items: - description: "Condition contains details for one aspect - of the current state of this API Resource.\n---\nThis - struct is intended for direct use as an array at the - field path .status.conditions. For example,\n\n\n\ttype - FooStatus struct{\n\t // Represents the observations - of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t - \ // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t - \ // +listType=map\n\t // +listMapKey=type\n\t - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, - False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - release: - description: release is the target of the update. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - risks: - description: |- - risks represents the range of issues associated with - updating to the target release. The cluster-version - operator will evaluate all entries, and only recommend the - update if there is at least one entry and all entries - recommend the update. - items: - description: |- - ConditionalUpdateRisk represents a reason and cluster-state - for not recommending a conditional update. - properties: - matchingRules: - description: |- - matchingRules is a slice of conditions for deciding which - clusters match the risk and which do not. The slice is - ordered by decreasing precedence. The cluster-version - operator will walk the slice in order, and stop after the - first it can successfully evaluate. If no condition can be - successfully evaluated, the update will not be recommended. - items: - description: |- - ClusterCondition is a union of typed cluster conditions. The 'type' - property determines which of the type-specific properties are relevant. - When evaluated on a cluster, the condition may match, not match, or - fail to evaluate. - properties: - promql: - description: promQL represents a cluster condition - based on PromQL. - properties: - promql: - description: |- - PromQL is a PromQL query classifying clusters. This query - query should return a 1 in the match case and a 0 in the - does-not-match case. Queries which return no time - series, or which return values besides 0 or 1, are - evaluation failures. - type: string - required: - - promql - type: object - type: - description: |- - type represents the cluster-condition type. This defines - the members and semantics of any additional properties. - enum: - - Always - - PromQL - type: string - required: - - type - type: object - minItems: 1 - type: array - x-kubernetes-list-type: atomic - message: - description: |- - message provides additional information about the risk of - updating, in the event that matchingRules match the cluster - state. This is only to be consumed by humans. It may - contain Line Feed characters (U+000A), which should be - rendered as new lines. - minLength: 1 - type: string - name: - description: |- - name is the CamelCase reason for not recommending a - conditional update, in the event that matchingRules match the - cluster state. - minLength: 1 - type: string - url: - description: url contains information about this risk. - format: uri - minLength: 1 - type: string - required: - - matchingRules - - message - - name - - url - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - release - - risks - type: object - type: array - x-kubernetes-list-type: atomic - desired: - description: |- - desired is the version that the cluster is reconciling towards. - If the cluster is not yet fully initialized desired will be set - with the information available, which may be an image or a tag. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - history: - description: |- - history contains a list of the most recent versions applied to the cluster. - This value may be empty during cluster startup, and then will be updated - when a new update is being applied. The newest update is first in the - list and it is ordered by recency. Updates in the history have state - Completed if the rollout completed - if an update was failing or halfway - applied the state will be Partial. Only a limited amount of update history - is preserved. - items: - description: UpdateHistory is a single attempted update to the - cluster. - properties: - acceptedRisks: - description: |- - acceptedRisks records risks which were accepted to initiate the update. - For example, it may menition an Upgradeable=False or missing signature - that was overriden via desiredUpdate.force, or an update that was - initiated despite not being in the availableUpdates set of recommended - update targets. - type: string - completionTime: - description: |- - completionTime, if set, is when the update was fully applied. The update - that is currently being applied will have a null completion time. - Completion time will always be set for entries that are not the current - update (usually to the started time of the next update). - format: date-time - nullable: true - type: string - image: - description: |- - image is a container image location that contains the update. This value - is always populated. - type: string - startedTime: - description: startedTime is the time at which the update - was started. - format: date-time - type: string - state: - description: |- - state reflects whether the update was fully applied. The Partial state - indicates the update is not fully applied, while the Completed state - indicates the update was successfully rolled out at least once (all - parts of the update successfully applied). - type: string - verified: - description: |- - verified indicates whether the provided update was properly verified - before it was installed. If this is false the cluster may not be trusted. - Verified does not cover upgradeable checks that depend on the cluster - state at the time when the update target was accepted. - type: boolean - version: - description: |- - version is a semantic version identifying the update version. If the - requested image does not define a version, or if a failure occurs - retrieving the image, this value may be empty. - type: string - required: - - completionTime - - image - - startedTime - - state - - verified - type: object - type: array - observedGeneration: - description: |- - observedGeneration reports which version of the spec is being synced. - If this value is not equal to metadata.generation, then the desired - and conditions fields may represent a previous version. - format: int64 - type: integer - required: - - availableUpdates - - desired - - observedGeneration - type: object - required: - - initialized - - ready - type: object - type: object - served: true - storage: false - subresources: - status: {} - - name: v1beta1 - schema: - openAPIV3Schema: - description: HostedControlPlane defines the desired state of HostedControlPlane - 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: HostedControlPlaneSpec defines the desired state of HostedControlPlane - properties: - additionalTrustBundle: - description: AdditionalTrustBundle references a ConfigMap containing - a PEM-encoded X.509 certificate bundle - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - auditWebhook: - description: |- - AuditWebhook contains metadata for configuring an audit webhook - endpoint for a cluster to process cluster audit events. It references - a secret that contains the webhook information for the audit webhook endpoint. - It is a secret because if the endpoint has MTLS the kubeconfig will contain client - keys. This is currently only supported in IBM Cloud. The kubeconfig needs to be stored - in the secret with a secret key name that corresponds to the constant AuditWebhookKubeconfigKey. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - autoscaling: - description: |- - Autoscaling specifies auto-scaling behavior that applies to all NodePools - associated with the control plane. - properties: - maxNodeProvisionTime: - description: |- - MaxNodeProvisionTime is the maximum time to wait for node provisioning - before considering the provisioning to be unsuccessful, expressed as a Go - duration string. The default is 15 minutes. - pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ - type: string - maxNodesTotal: - description: |- - MaxNodesTotal is the maximum allowable number of nodes across all NodePools - for a HostedCluster. The autoscaler will not grow the cluster beyond this - number. - format: int32 - minimum: 0 - type: integer - maxPodGracePeriod: - description: |- - MaxPodGracePeriod is the maximum seconds to wait for graceful pod - termination before scaling down a NodePool. The default is 600 seconds. - format: int32 - minimum: 0 - type: integer - podPriorityThreshold: - description: |- - PodPriorityThreshold enables users to schedule "best-effort" pods, which - shouldn't trigger autoscaler actions, but only run when there are spare - resources available. The default is -10. - - - See the following for more details: - https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-cluster-autoscaler-work-with-pod-priority-and-preemption - format: int32 - type: integer - type: object - channel: - description: |- - channel is an identifier for explicitly requesting that a non-default - set of updates be applied to this cluster. The default channel will be - contain stable updates that are appropriate for production clusters. - type: string - clusterID: - description: |- - ClusterID is the unique id that identifies the cluster externally. - Making it optional here allows us to keep compatibility with previous - versions of the control-plane-operator that have no knowledge of this - field. - type: string - configuration: - description: |- - Configuration embeds resources that correspond to the openshift configuration API: - https://docs.openshift.com/container-platform/4.7/rest_api/config_apis/config-apis-index.html - properties: - apiServer: - description: |- - APIServer holds configuration (like serving certificates, client CA and CORS domains) - shared by all API servers in the system, among them especially kube-apiserver - and openshift-apiserver. - properties: - additionalCORSAllowedOrigins: - description: |- - additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the - API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth - server from JavaScript applications. - The values are regular expressions that correspond to the Golang regular expression language. - items: - type: string - type: array - audit: - default: - profile: Default - description: |- - audit specifies the settings for audit configuration to be applied to all OpenShift-provided - API servers in the cluster. - properties: - customRules: - description: |- - customRules specify profiles per group. These profile take precedence over the - top-level profile field if they apply. They are evaluation from top to bottom and - the first one that matches, applies. - items: - description: |- - AuditCustomRule describes a custom rule for an audit profile that takes precedence over - the top-level profile. - properties: - group: - description: group is a name of group a request - user must be member of in order to this profile - to apply. - minLength: 1 - type: string - profile: - description: |- - profile specifies the name of the desired audit policy configuration to be deployed to - all OpenShift-provided API servers in the cluster. - - - The following profiles are provided: - - Default: the existing default policy. - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - required: - - group - - profile - type: object - type: array - x-kubernetes-list-map-keys: - - group - x-kubernetes-list-type: map - profile: - default: Default - description: |- - profile specifies the name of the desired top-level audit profile to be applied to all requests - sent to any of the OpenShift-provided API servers in the cluster (kube-apiserver, - openshift-apiserver and oauth-apiserver), with the exception of those requests that match - one or more of the customRules. - - - The following profiles are provided: - - Default: default policy which means MetaData level logging with the exception of events - (not logged at all), oauthaccesstokens and oauthauthorizetokens (both logged at RequestBody - level). - - WriteRequestBodies: like 'Default', but logs request and response HTTP payloads for - write requests (create, update, patch). - - AllRequestBodies: like 'WriteRequestBodies', but also logs request and response - HTTP payloads for read requests (get, list). - - None: no requests are logged at all, not even oauthaccesstokens and oauthauthorizetokens. - - - Warning: It is not recommended to disable audit logging by using the `None` profile unless you - are fully aware of the risks of not logging data that can be beneficial when troubleshooting issues. - If you disable audit logging and a support situation arises, you might need to enable audit logging - and reproduce the issue in order to troubleshoot properly. - - - If unset, the 'Default' profile is used as the default. - enum: - - Default - - WriteRequestBodies - - AllRequestBodies - - None - type: string - type: object - clientCA: - description: |- - clientCA references a ConfigMap containing a certificate bundle for the signers that will be recognized for - incoming client certificates in addition to the operator managed signers. If this is empty, then only operator managed signers are valid. - You usually only have to set this if you have your own PKI you wish to honor client certificates from. - The ConfigMap must exist in the openshift-config namespace and contain the following required fields: - - ConfigMap.Data["ca-bundle.crt"] - CA bundle. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - encryption: - description: encryption allows the configuration of encryption - of resources at the datastore layer. - properties: - type: - description: |- - type defines what encryption type should be used to encrypt resources at the datastore layer. - When this field is unset (i.e. when it is set to the empty string), identity is implied. - The behavior of unset can and will change over time. Even if encryption is enabled by default, - the meaning of unset may change to a different encryption type based on changes in best practices. - - - When encryption is enabled, all sensitive resources shipped with the platform are encrypted. - This list of sensitive resources can and will change over time. The current authoritative list is: - - - 1. secrets - 2. configmaps - 3. routes.route.openshift.io - 4. oauthaccesstokens.oauth.openshift.io - 5. oauthauthorizetokens.oauth.openshift.io - enum: - - "" - - identity - - aescbc - - aesgcm - type: string - type: object - servingCerts: - description: |- - servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates - will be used for serving secure traffic. - properties: - namedCertificates: - description: |- - namedCertificates references secrets containing the TLS cert info for serving secure traffic to specific hostnames. - If no named certificates are provided, or no named certificates match the server name as understood by a client, - the defaultServingCertificate will be used. - items: - description: APIServerNamedServingCert maps a server - DNS name, as understood by a client, to a certificate. - properties: - names: - description: |- - names is a optional list of explicit DNS names (leading wildcards allowed) that should use this certificate to - serve secure traffic. If no names are provided, the implicit names will be extracted from the certificates. - Exact names trump over wildcard names. Explicit names defined here trump over extracted implicit names. - items: - type: string - type: array - servingCertificate: - description: |- - servingCertificate references a kubernetes.io/tls type secret containing the TLS cert info for serving secure traffic. - The secret must exist in the openshift-config namespace and contain the following required fields: - - Secret.Data["tls.key"] - TLS private key. - - Secret.Data["tls.crt"] - TLS certificate. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - type: array - type: object - tlsSecurityProfile: - description: |- - tlsSecurityProfile specifies settings for TLS connections for externally exposed servers. - - - If unset, a default (which may change between releases) is chosen. Note that only Old, - Intermediate and Custom profiles are currently supported, and the maximum available - minTLSVersion is VersionTLS12. - properties: - custom: - description: |- - custom is a user-defined TLS security profile. Be extremely careful using a custom - profile as invalid configurations can be catastrophic. An example custom profile - looks like this: - - - ciphers: - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - minTLSVersion: VersionTLS11 - nullable: true - properties: - ciphers: - description: |- - ciphers is used to specify the cipher algorithms that are negotiated - during the TLS handshake. Operators may remove entries their operands - do not support. For example, to use DES-CBC3-SHA (yaml): - - - ciphers: - - DES-CBC3-SHA - items: - type: string - type: array - minTLSVersion: - description: |- - minTLSVersion is used to specify the minimal version of the TLS protocol - that is negotiated during the TLS handshake. For example, to use TLS - versions 1.1, 1.2 and 1.3 (yaml): - - - minTLSVersion: VersionTLS11 - - - NOTE: currently the highest minTLSVersion allowed is VersionTLS12 - enum: - - VersionTLS10 - - VersionTLS11 - - VersionTLS12 - - VersionTLS13 - type: string - type: object - intermediate: - description: |- - intermediate is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - minTLSVersion: VersionTLS12 - nullable: true - type: object - modern: - description: |- - modern is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - minTLSVersion: VersionTLS13 - nullable: true - type: object - old: - description: |- - old is a TLS security profile based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility - - - and looks like this (yaml): - - - ciphers: - - - - TLS_AES_128_GCM_SHA256 - - - - TLS_AES_256_GCM_SHA384 - - - - TLS_CHACHA20_POLY1305_SHA256 - - - - ECDHE-ECDSA-AES128-GCM-SHA256 - - - - ECDHE-RSA-AES128-GCM-SHA256 - - - - ECDHE-ECDSA-AES256-GCM-SHA384 - - - - ECDHE-RSA-AES256-GCM-SHA384 - - - - ECDHE-ECDSA-CHACHA20-POLY1305 - - - - ECDHE-RSA-CHACHA20-POLY1305 - - - - DHE-RSA-AES128-GCM-SHA256 - - - - DHE-RSA-AES256-GCM-SHA384 - - - - DHE-RSA-CHACHA20-POLY1305 - - - - ECDHE-ECDSA-AES128-SHA256 - - - - ECDHE-RSA-AES128-SHA256 - - - - ECDHE-ECDSA-AES128-SHA - - - - ECDHE-RSA-AES128-SHA - - - - ECDHE-ECDSA-AES256-SHA384 - - - - ECDHE-RSA-AES256-SHA384 - - - - ECDHE-ECDSA-AES256-SHA - - - - ECDHE-RSA-AES256-SHA - - - - DHE-RSA-AES128-SHA256 - - - - DHE-RSA-AES256-SHA256 - - - - AES128-GCM-SHA256 - - - - AES256-GCM-SHA384 - - - - AES128-SHA256 - - - - AES256-SHA256 - - - - AES128-SHA - - - - AES256-SHA - - - - DES-CBC3-SHA - - - minTLSVersion: VersionTLS10 - nullable: true - type: object - type: - description: |- - type is one of Old, Intermediate, Modern or Custom. Custom provides - the ability to specify individual TLS security profile parameters. - Old, Intermediate and Modern are TLS security profiles based on: - - - https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations - - - The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers - are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be - reduced. - - - Note that the Modern profile is currently not supported because it is not - yet well adopted by common software libraries. - enum: - - Old - - Intermediate - - Modern - - Custom - type: string - type: object - type: object - authentication: - description: |- - Authentication specifies cluster-wide settings for authentication (like OAuth and - webhook token authenticators). - properties: - oauthMetadata: - description: |- - oauthMetadata contains the discovery endpoint data for OAuth 2.0 - Authorization Server Metadata for an external OAuth server. - This discovery document can be viewed from its served location: - oc get --raw '/.well-known/oauth-authorization-server' - For further details, see the IETF Draft: - https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 - If oauthMetadata.name is non-empty, this value has precedence - over any metadata reference stored in status. - The key "oauthMetadata" is used to locate the data. - If specified and the config map or expected key is not found, no metadata is served. - If the specified metadata is not valid, no metadata is served. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - oidcProviders: - description: |- - OIDCProviders are OIDC identity providers that can issue tokens - for this cluster - Can only be set if "Type" is set to "OIDC". - - - At most one provider can be configured. - items: - properties: - claimMappings: - description: |- - ClaimMappings describes rules on how to transform information from an - ID token into a cluster identity - properties: - groups: - description: |- - Groups is a name of the claim that should be used to construct - groups for the cluster identity. - The referenced claim must use array of strings values. - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - description: |- - Prefix is a string to prefix the value from the token in the result of the - claim mapping. - - - By default, no prefixing occurs. - - - Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains - an array of strings "a", "b" and "c", the mapping will result in an - array of string "myoidc:a", "myoidc:b" and "myoidc:c". - type: string - required: - - claim - type: object - username: - description: |- - Username is a name of the claim that should be used to construct - usernames for the cluster identity. - - - Default value: "sub" - properties: - claim: - description: Claim is a JWT token claim to be - used in the mapping - type: string - prefix: - properties: - prefixString: - minLength: 1 - type: string - required: - - prefixString - type: object - prefixPolicy: - description: |- - PrefixPolicy specifies how a prefix should apply. - - - By default, claims other than `email` will be prefixed with the issuer URL to - prevent naming clashes with other plugins. - - - Set to "NoPrefix" to disable prefixing. - - - Example: - (1) `prefix` is set to "myoidc:" and `claim` is set to "username". - If the JWT claim `username` contains value `userA`, the resulting - mapped value will be "myoidc:userA". - (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the - JWT `email` claim contains value "userA@myoidc.tld", the resulting - mapped value will be "myoidc:userA@myoidc.tld". - (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`, - the JWT claims include "username":"userA" and "email":"userA@myoidc.tld", - and `claim` is set to: - (a) "username": the mapped value will be "https://myoidc.tld#userA" - (b) "email": the mapped value will be "userA@myoidc.tld" - enum: - - "" - - NoPrefix - - Prefix - type: string - required: - - claim - type: object - x-kubernetes-validations: - - message: prefix must be set if prefixPolicy is - 'Prefix', but must remain unset otherwise - rule: 'has(self.prefixPolicy) && self.prefixPolicy - == ''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString) - > 0) : !has(self.prefix)' - type: object - claimValidationRules: - description: ClaimValidationRules are rules that are - applied to validate token claims to authenticate users. - items: - properties: - requiredClaim: - description: |- - RequiredClaim allows configuring a required claim name and its expected - value - properties: - claim: - description: |- - Claim is a name of a required claim. Only claims with string values are - supported. - minLength: 1 - type: string - requiredValue: - description: RequiredValue is the required - value for the claim. - minLength: 1 - type: string - required: - - claim - - requiredValue - type: object - type: - default: RequiredClaim - description: Type sets the type of the validation - rule - enum: - - RequiredClaim - type: string - type: object - type: array - x-kubernetes-list-type: atomic - issuer: - description: Issuer describes atributes of the OIDC - token issuer - properties: - audiences: - description: |- - Audiences is an array of audiences that the token was issued for. - Valid tokens must include at least one of these values in their - "aud" claim. - Must be set to exactly one value. - items: - minLength: 1 - type: string - maxItems: 10 - minItems: 1 - type: array - x-kubernetes-list-type: set - issuerCertificateAuthority: - description: |- - CertificateAuthority is a reference to a config map in the - configuration namespace. The .data of the configMap must contain - the "ca-bundle.crt" key. - If unset, system trust is used instead. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - issuerURL: - description: |- - URL is the serving URL of the token issuer. - Must use the https:// scheme. - pattern: ^https:\/\/[^\s] - type: string - required: - - audiences - - issuerURL - type: object - name: - description: Name of the OIDC provider - minLength: 1 - type: string - oidcClients: - description: |- - OIDCClients contains configuration for the platform's clients that - need to request tokens from the issuer - items: - properties: - clientID: - description: ClientID is the identifier of the - OIDC client from the OIDC provider - minLength: 1 - type: string - clientSecret: - description: |- - ClientSecret refers to a secret in the `openshift-config` namespace that - contains the client secret in the `clientSecret` key of the `.data` field - properties: - name: - description: name is the metadata.name of - the referenced secret - type: string - required: - - name - type: object - componentName: - description: |- - ComponentName is the name of the component that is supposed to consume this - client configuration - maxLength: 256 - minLength: 1 - type: string - componentNamespace: - description: |- - ComponentNamespace is the namespace of the component that is supposed to consume this - client configuration - maxLength: 63 - minLength: 1 - type: string - extraScopes: - description: ExtraScopes is an optional set of - scopes to request tokens with. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - clientID - - componentName - - componentNamespace - type: object - maxItems: 20 - type: array - x-kubernetes-list-map-keys: - - componentNamespace - - componentName - x-kubernetes-list-type: map - required: - - issuer - - name - type: object - maxItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - serviceAccountIssuer: - description: |- - serviceAccountIssuer is the identifier of the bound service account token - issuer. - The default is https://kubernetes.default.svc - WARNING: Updating this field will not result in immediate invalidation of all bound tokens with the - previous issuer value. Instead, the tokens issued by previous service account issuer will continue to - be trusted for a time period chosen by the platform (currently set to 24h). - This time period is subject to change over time. - This allows internal components to transition to use new service account issuer without service distruption. - type: string - type: - description: |- - type identifies the cluster managed, user facing authentication mode in use. - Specifically, it manages the component that responds to login attempts. - The default is IntegratedOAuth. - type: string - webhookTokenAuthenticator: - description: |- - webhookTokenAuthenticator configures a remote token reviewer. - These remote authentication webhooks can be used to verify bearer tokens - via the tokenreviews.authentication.k8s.io REST API. This is required to - honor bearer tokens that are provisioned by an external authentication service. - - - Can only be set if "Type" is set to "None". - properties: - kubeConfig: - description: |- - kubeConfig references a secret that contains kube config file data which - describes how to access the remote webhook service. - The namespace for the referenced secret is openshift-config. - - - For further details, see: - - - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - - - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - kubeConfig - type: object - webhookTokenAuthenticators: - description: webhookTokenAuthenticators is DEPRECATED, setting - it has no effect. - items: - description: |- - deprecatedWebhookTokenAuthenticator holds the necessary configuration options for a remote token authenticator. - It's the same as WebhookTokenAuthenticator but it's missing the 'required' validation on KubeConfig field. - properties: - kubeConfig: - description: |- - kubeConfig contains kube config file data which describes how to access the remote webhook service. - For further details, see: - https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication - The key "kubeConfig" is used to locate the data. - If the secret or expected key is not found, the webhook is not honored. - If the specified kube config data is not valid, the webhook is not honored. - The namespace for this secret is determined by the point of use. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - featureGate: - description: FeatureGate holds cluster-wide information about - feature gates. - properties: - customNoUpgrade: - description: |- - customNoUpgrade allows the enabling or disabling of any feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, and PREVENTS UPGRADES. - Because of its nature, this setting cannot be validated. If you have any typos or accidentally apply invalid combinations - your cluster may fail in an unrecoverable way. featureSet must equal "CustomNoUpgrade" must be set to use this field. - nullable: true - properties: - disabled: - description: disabled is a list of all feature gates that - you want to force off - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - enabled: - description: enabled is a list of all feature gates that - you want to force on - items: - description: FeatureGateName is a string to enforce - patterns on the name of a FeatureGate - pattern: ^([A-Za-z0-9-]+\.)*[A-Za-z0-9-]+\.?$ - type: string - type: array - type: object - featureSet: - description: |- - featureSet changes the list of features in the cluster. The default is empty. Be very careful adjusting this setting. - Turning on or off features may cause irreversible changes in your cluster which cannot be undone. - type: string - x-kubernetes-validations: - - message: CustomNoUpgrade may not be changed - rule: 'oldSelf == ''CustomNoUpgrade'' ? self == ''CustomNoUpgrade'' - : true' - - message: TechPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''TechPreviewNoUpgrade'' ? self == ''TechPreviewNoUpgrade'' - : true' - - message: DevPreviewNoUpgrade may not be changed - rule: 'oldSelf == ''DevPreviewNoUpgrade'' ? self == ''DevPreviewNoUpgrade'' - : true' - type: object - image: - description: |- - Image governs policies related to imagestream imports and runtime configuration - for external registries. It allows cluster admins to configure which registries - OpenShift is allowed to import images from, extra CA trust bundles for external - registries, and policies to block or allow registry hostnames. - When exposing OpenShift's image registry to the public, this also lets cluster - admins specify the external hostname. - properties: - additionalTrustedCA: - description: |- - additionalTrustedCA is a reference to a ConfigMap containing additional CAs that - should be trusted during imagestream import, pod image pull, build image pull, and - imageregistry pullthrough. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - allowedRegistriesForImport: - description: |- - allowedRegistriesForImport limits the container image registries that normal users may import - images from. Set this list to the registries that you trust to contain valid Docker - images and that you want applications to be able to import from. Users with - permission to create Images or ImageStreamMappings via the API are not affected by - this policy - typically only administrators or system integrations will have those - permissions. - items: - description: |- - RegistryLocation contains a location of the registry specified by the registry domain - name. The domain name might include wildcards, like '*' or '??'. - properties: - domainName: - description: |- - domainName specifies a domain name for the registry - In case the registry use non-standard (80 or 443) port, the port should be included - in the domain name as well. - type: string - insecure: - description: |- - insecure indicates whether the registry is secure (https) or insecure (http) - By default (if not specified) the registry is assumed as secure. - type: boolean - type: object - type: array - externalRegistryHostnames: - description: |- - externalRegistryHostnames provides the hostnames for the default external image - registry. The external hostname should be set only when the image registry - is exposed externally. The first value is used in 'publicDockerImageRepository' - field in ImageStreams. The value must be in "hostname[:port]" format. - items: - type: string - type: array - registrySources: - description: |- - registrySources contains configuration that determines how the container runtime - should treat individual registries when accessing images for builds+pods. (e.g. - whether or not to allow insecure access). It does not contain configuration for the - internal cluster registry. - properties: - allowedRegistries: - description: |- - allowedRegistries are the only registries permitted for image pull and push actions. All other registries are denied. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - blockedRegistries: - description: |- - blockedRegistries cannot be used for image pull and push actions. All other registries are permitted. - - - Only one of BlockedRegistries or AllowedRegistries may be set. - items: - type: string - type: array - containerRuntimeSearchRegistries: - description: |- - containerRuntimeSearchRegistries are registries that will be searched when pulling images that do not have fully qualified - domains in their pull specs. Registries will be searched in the order provided in the list. - Note: this search list only works with the container runtime, i.e CRI-O. Will NOT work with builds or imagestream imports. - format: hostname - items: - type: string - minItems: 1 - type: array - x-kubernetes-list-type: set - insecureRegistries: - description: insecureRegistries are registries which do - not have a valid TLS certificates or only support HTTP - connections. - items: - type: string - type: array - type: object - type: object - ingress: - description: |- - Ingress holds cluster-wide information about ingress, including the default ingress domain - used for routes. - properties: - appsDomain: - description: |- - appsDomain is an optional domain to use instead of the one specified - in the domain field when a Route is created without specifying an explicit - host. If appsDomain is nonempty, this value is used to generate default - host values for Route. Unlike domain, appsDomain may be modified after - installation. - This assumes a new ingresscontroller has been setup with a wildcard - certificate. - type: string - componentRoutes: - description: |- - componentRoutes is an optional list of routes that are managed by OpenShift components - that a cluster-admin is able to configure the hostname and serving certificate for. - The namespace and name of each route in this list should match an existing entry in the - status.componentRoutes list. - - - To determine the set of configurable Routes, look at namespace and name of entries in the - .status.componentRoutes list, where participating operators write the status of - configurable routes. - items: - description: ComponentRouteSpec allows for configuration - of a route's hostname and serving certificate. - properties: - hostname: - description: hostname is the hostname that should be - used by the route. - pattern: ^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$|^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$ - type: string - name: - description: |- - name is the logical name of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 256 - minLength: 1 - type: string - namespace: - description: |- - namespace is the namespace of the route to customize. - - - The namespace and name of this componentRoute must match a corresponding - entry in the list of status.componentRoutes if the route is to be customized. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - servingCertKeyPairSecret: - description: |- - servingCertKeyPairSecret is a reference to a secret of type `kubernetes.io/tls` in the openshift-config namespace. - The serving cert/key pair must match and will be used by the operator to fulfill the intent of serving with this name. - If the custom hostname uses the default routing suffix of the cluster, - the Secret specification for a serving certificate will not be needed. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - required: - - hostname - - name - - namespace - type: object - type: array - x-kubernetes-list-map-keys: - - namespace - - name - x-kubernetes-list-type: map - domain: - description: |- - domain is used to generate a default host name for a route when the - route's host name is empty. The generated host name will follow this - pattern: "..". - - - It is also used as the default wildcard domain suffix for ingress. The - default ingresscontroller domain will follow this pattern: "*.". - - - Once set, changing domain is not currently supported. - type: string - loadBalancer: - description: |- - loadBalancer contains the load balancer details in general which are not only specific to the underlying infrastructure - provider of the current cluster and are required for Ingress Controller to work on OpenShift. - properties: - platform: - description: |- - platform holds configuration specific to the underlying - infrastructure provider for the ingress load balancers. - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - properties: - aws: - description: aws contains settings specific to the - Amazon Web Services infrastructure provider. - properties: - type: - description: |- - type allows user to set a load balancer type. - When this field is set the default ingresscontroller will get created using the specified LBType. - If this field is not set then the default ingress controller of LBType Classic will be created. - Valid values are: - - - * "Classic": A Classic Load Balancer that makes routing decisions at either - the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See - the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb - - - * "NLB": A Network Load Balancer that makes routing decisions at the - transport layer (TCP/SSL). See the following for additional details: - - - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb - enum: - - NLB - - Classic - type: string - required: - - type - type: object - type: - description: |- - type is the underlying infrastructure provider for the cluster. - Allowed values are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", - "OpenStack", "VSphere", "oVirt", "KubeVirt", "EquinixMetal", "PowerVS", - "AlibabaCloud", "Nutanix" and "None". Individual components may not support all platforms, - and must handle unrecognized platforms as None if they do not support that platform. - enum: - - "" - - AWS - - Azure - - BareMetal - - GCP - - Libvirt - - OpenStack - - None - - VSphere - - oVirt - - IBMCloud - - KubeVirt - - EquinixMetal - - PowerVS - - AlibabaCloud - - Nutanix - - External - type: string - type: object - type: object - requiredHSTSPolicies: - description: |- - requiredHSTSPolicies specifies HSTS policies that are required to be set on newly created or updated routes - matching the domainPattern/s and namespaceSelector/s that are specified in the policy. - Each requiredHSTSPolicy must have at least a domainPattern and a maxAge to validate a route HSTS Policy route - annotation, and affect route admission. - - - A candidate route is checked for HSTS Policies if it has the HSTS Policy route annotation: - "haproxy.router.openshift.io/hsts_header" - E.g. haproxy.router.openshift.io/hsts_header: max-age=31536000;preload;includeSubDomains - - - - For each candidate route, if it matches a requiredHSTSPolicy domainPattern and optional namespaceSelector, - then the maxAge, preloadPolicy, and includeSubdomainsPolicy must be valid to be admitted. Otherwise, the route - is rejected. - - The first match, by domainPattern and optional namespaceSelector, in the ordering of the RequiredHSTSPolicies - determines the route's admission status. - - If the candidate route doesn't match any requiredHSTSPolicy domainPattern and optional namespaceSelector, - then it may use any HSTS Policy annotation. - - - The HSTS policy configuration may be changed after routes have already been created. An update to a previously - admitted route may then fail if the updated route does not conform to the updated HSTS policy configuration. - However, changing the HSTS policy configuration will not cause a route that is already admitted to stop working. - - - Note that if there are no RequiredHSTSPolicies, any HSTS Policy annotation on the route is valid. - items: - properties: - domainPatterns: - description: |- - domainPatterns is a list of domains for which the desired HSTS annotations are required. - If domainPatterns is specified and a route is created with a spec.host matching one of the domains, - the route must specify the HSTS Policy components described in the matching RequiredHSTSPolicy. - - - The use of wildcards is allowed like this: *.foo.com matches everything under foo.com. - foo.com only matches foo.com, so to cover foo.com and everything under it, you must specify *both*. - items: - type: string - minItems: 1 - type: array - includeSubDomainsPolicy: - description: |- - includeSubDomainsPolicy means the HSTS Policy should apply to any subdomains of the host's - domain name. Thus, for the host bar.foo.com, if includeSubDomainsPolicy was set to RequireIncludeSubDomains: - - the host app.bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host bar.foo.com would inherit the HSTS Policy of bar.foo.com - - the host foo.com would NOT inherit the HSTS Policy of bar.foo.com - - the host def.foo.com would NOT inherit the HSTS Policy of bar.foo.com - enum: - - RequireIncludeSubDomains - - RequireNoIncludeSubDomains - - NoOpinion - type: string - maxAge: - description: |- - maxAge is the delta time range in seconds during which hosts are regarded as HSTS hosts. - If set to 0, it negates the effect, and hosts are removed as HSTS hosts. - If set to 0 and includeSubdomains is specified, all subdomains of the host are also removed as HSTS hosts. - maxAge is a time-to-live value, and if this policy is not refreshed on a client, the HSTS - policy will eventually expire on that client. - properties: - largestMaxAge: - description: |- - The largest allowed value (in seconds) of the RequiredHSTSPolicy max-age - This value can be left unspecified, in which case no upper limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - smallestMaxAge: - description: |- - The smallest allowed value (in seconds) of the RequiredHSTSPolicy max-age - Setting max-age=0 allows the deletion of an existing HSTS header from a host. This is a necessary - tool for administrators to quickly correct mistakes. - This value can be left unspecified, in which case no lower limit is enforced. - format: int32 - maximum: 2147483647 - minimum: 0 - type: integer - type: object - namespaceSelector: - description: |- - namespaceSelector specifies a label selector such that the policy applies only to those routes that - are in namespaces with labels that match the selector, and are in one of the DomainPatterns. - Defaults to the empty LabelSelector, which matches everything. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - preloadPolicy: - description: |- - preloadPolicy directs the client to include hosts in its host preload list so that - it never needs to do an initial load to get the HSTS header (note that this is not defined - in RFC 6797 and is therefore client implementation-dependent). - enum: - - RequirePreload - - RequireNoPreload - - NoOpinion - type: string - required: - - domainPatterns - type: object - type: array - type: object - network: - description: |- - Network holds cluster-wide information about the network. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. - Please view network.spec for an explanation on what applies when configuring this resource. - TODO (csrwng): Add validation here to exclude changes that conflict with networking settings in the HostedCluster.Spec.Networking field. - properties: - clusterNetwork: - description: |- - IP address pool to use for pod IPs. - This field is immutable after installation. - items: - description: |- - ClusterNetworkEntry is a contiguous block of IP addresses from which pod IPs - are allocated. - properties: - cidr: - description: The complete block for pod IPs. - type: string - hostPrefix: - description: |- - The size (prefix) of block to allocate to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - minimum: 0 - type: integer - type: object - type: array - x-kubernetes-list-type: atomic - externalIP: - description: |- - externalIP defines configuration for controllers that - affect Service.ExternalIP. If nil, then ExternalIP is - not allowed to be set. - properties: - autoAssignCIDRs: - description: |- - autoAssignCIDRs is a list of CIDRs from which to automatically assign - Service.ExternalIP. These are assigned when the service is of type - LoadBalancer. In general, this is only useful for bare-metal clusters. - In Openshift 3.x, this was misleadingly called "IngressIPs". - Automatically assigned External IPs are not affected by any - ExternalIPPolicy rules. - Currently, only one entry may be provided. - items: - type: string - type: array - x-kubernetes-list-type: atomic - policy: - description: |- - policy is a set of restrictions applied to the ExternalIP field. - If nil or empty, then ExternalIP is not allowed to be set. - properties: - allowedCIDRs: - description: allowedCIDRs is the list of allowed CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - rejectedCIDRs: - description: |- - rejectedCIDRs is the list of disallowed CIDRs. These take precedence - over allowedCIDRs. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkDiagnostics: - description: |- - networkDiagnostics defines network diagnostics configuration. - - - Takes precedence over spec.disableNetworkDiagnostics in network.operator.openshift.io. - If networkDiagnostics is not specified or is empty, - and the spec.disableNetworkDiagnostics flag in network.operator.openshift.io is set to true, - the network diagnostics feature will be disabled. - properties: - mode: - description: |- - mode controls the network diagnostics mode - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is All. - enum: - - "" - - All - - Disabled - type: string - sourcePlacement: - description: |- - sourcePlacement controls the scheduling of network diagnostics source deployment - - - See NetworkDiagnosticsSourcePlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is an empty list. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - targetPlacement: - description: |- - targetPlacement controls the scheduling of network diagnostics target daemonset - - - See NetworkDiagnosticsTargetPlacement for more details about default values. - properties: - nodeSelector: - additionalProperties: - type: string - description: |- - nodeSelector is the node selector applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `kubernetes.io/os: linux`. - type: object - tolerations: - description: |- - tolerations is a list of tolerations applied to network diagnostics components - - - When omitted, this means the user has no opinion and the platform is left - to choose reasonable defaults. These defaults are subject to change over time. - The current default is `- operator: "Exists"` which means that all taints are tolerated. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - networkType: - description: |- - NetworkType is the plugin that is to be deployed (e.g. OpenShiftSDN). - This should match a value that the cluster-network-operator understands, - or else no networking will be installed. - Currently supported values are: - - OpenShiftSDN - This field is immutable after installation. - type: string - serviceNetwork: - description: |- - IP address pool for services. - Currently, we only support a single entry here. - This field is immutable after installation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - serviceNodePortRange: - description: |- - The port range allowed for Services of type NodePort. - If not specified, the default of 30000-32767 will be used. - Such Services without a NodePort specified will have one - automatically allocated from this range. - This parameter can be updated after the cluster is - installed. - pattern: ^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])-([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$ - type: string - type: object - oauth: - description: |- - OAuth holds cluster-wide information about OAuth. - It is used to configure the integrated OAuth server. - This configuration is only honored when the top level Authentication config has type set to IntegratedOAuth. - properties: - identityProviders: - description: |- - identityProviders is an ordered list of ways for a user to identify themselves. - When this list is empty, no identities are provisioned for users. - items: - description: IdentityProvider provides identities for users - authenticating using credentials - properties: - basicAuth: - description: basicAuth contains configuration options - for the BasicAuth IdP - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - github: - description: github enables user authentication using - GitHub credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - This can only be configured when hostname is set to a non-empty value. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostname: - description: |- - hostname is the optional domain (e.g. "mycompany.com") for use with a hosted instance of - GitHub Enterprise. - It must match the GitHub Enterprise settings value configured at /setup/settings#hostname. - type: string - organizations: - description: organizations optionally restricts - which organizations are allowed to log in - items: - type: string - type: array - teams: - description: teams optionally restricts which teams - are allowed to log in. Format is /. - items: - type: string - type: array - type: object - gitlab: - description: gitlab enables user authentication using - GitLab credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the oauth server base URL - type: string - type: object - google: - description: google enables user authentication using - Google credentials - properties: - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - hostedDomain: - description: hostedDomain is the optional Google - App domain (e.g. "mycompany.com") to restrict - logins to - type: string - type: object - htpasswd: - description: htpasswd enables user authentication using - an HTPasswd file to validate credentials - properties: - fileData: - description: |- - fileData is a required reference to a secret by name containing the data to use as the htpasswd file. - The key "htpasswd" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - If the specified htpasswd data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - type: object - keystone: - description: keystone enables user authentication using - keystone password credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - domainName: - description: domainName is required for keystone - v3 - type: string - tlsClientCert: - description: |- - tlsClientCert is an optional reference to a secret by name that contains the - PEM-encoded TLS client certificate to present when connecting to the server. - The key "tls.crt" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - tlsClientKey: - description: |- - tlsClientKey is an optional reference to a secret by name that contains the - PEM-encoded TLS private key for the client certificate referenced in tlsClientCert. - The key "tls.key" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - If the specified certificate data is not valid, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - url: - description: url is the remote URL to connect to - type: string - type: object - ldap: - description: ldap enables user authentication using - LDAP credentials - properties: - attributes: - description: attributes maps LDAP attributes to - identities - properties: - email: - description: |- - email is the list of attributes whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - id: - description: |- - id is the list of attributes whose values should be used as the user ID. Required. - First non-empty attribute is used. At least one attribute is required. If none of the listed - attribute have a value, authentication fails. - LDAP standard identity attribute is "dn" - items: - type: string - type: array - name: - description: |- - name is the list of attributes whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - LDAP standard display name attribute is "cn" - items: - type: string - type: array - preferredUsername: - description: |- - preferredUsername is the list of attributes whose values should be used as the preferred username. - LDAP standard login attribute is "uid" - items: - type: string - type: array - type: object - bindDN: - description: bindDN is an optional DN to bind with - during the search phase. - type: string - bindPassword: - description: |- - bindPassword is an optional reference to a secret by name - containing a password to bind with during the search phase. - The key "bindPassword" is used to locate the data. - If specified and the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - insecure: - description: |- - insecure, if true, indicates the connection should not use TLS - WARNING: Should not be set to `true` with the URL scheme "ldaps://" as "ldaps://" URLs always - attempt to connect using TLS, even when `insecure` is set to `true` - When `true`, "ldap://" URLS connect insecurely. When `false`, "ldap://" URLs are upgraded to - a TLS connection using StartTLS as specified in https://tools.ietf.org/html/rfc2830. - type: boolean - url: - description: |- - url is an RFC 2255 URL which specifies the LDAP search parameters to use. - The syntax of the URL is: - ldap://host:port/basedn?attribute?scope?filter - type: string - type: object - mappingMethod: - description: |- - mappingMethod determines how identities from this provider are mapped to users - Defaults to "claim" - type: string - name: - description: |- - name is used to qualify the identities returned by this provider. - - It MUST be unique and not shared by any other identity provider used - - It MUST be a valid path segment: name cannot equal "." or ".." or contain "/" or "%" or ":" - Ref: https://godoc.org/github.com/openshift/origin/pkg/user/apis/user/validation#ValidateIdentityProviderName - type: string - openID: - description: openID enables user authentication using - OpenID credentials - properties: - ca: - description: |- - ca is an optional reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - The key "ca.crt" is used to locate the data. - If specified and the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - If empty, the default system roots are used. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - claims: - description: claims mappings - properties: - email: - description: |- - email is the list of claims whose values should be used as the email address. Optional. - If unspecified, no email is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - groups: - description: |- - groups is the list of claims value of which should be used to synchronize groups - from the OIDC provider to OpenShift for the user. - If multiple claims are specified, the first one with a non-empty value is used. - items: - description: |- - OpenIDClaim represents a claim retrieved from an OpenID provider's tokens or userInfo - responses - minLength: 1 - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: |- - name is the list of claims whose values should be used as the display name. Optional. - If unspecified, no display name is set for the identity - items: - type: string - type: array - x-kubernetes-list-type: atomic - preferredUsername: - description: |- - preferredUsername is the list of claims whose values should be used as the preferred username. - If unspecified, the preferred username is determined from the value of the sub claim - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - clientID: - description: clientID is the oauth client ID - type: string - clientSecret: - description: |- - clientSecret is a required reference to the secret by name containing the oauth client secret. - The key "clientSecret" is used to locate the data. - If the secret or expected key is not found, the identity provider is not honored. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced secret - type: string - required: - - name - type: object - extraAuthorizeParameters: - additionalProperties: - type: string - description: extraAuthorizeParameters are any custom - parameters to add to the authorize request. - type: object - extraScopes: - description: extraScopes are any scopes to request - in addition to the standard "openid" scope. - items: - type: string - type: array - issuer: - description: |- - issuer is the URL that the OpenID Provider asserts as its Issuer Identifier. - It must use the https scheme with no query or fragment component. - type: string - type: object - requestHeader: - description: requestHeader enables user authentication - using request header credentials - properties: - ca: - description: |- - ca is a required reference to a config map by name containing the PEM-encoded CA bundle. - It is used as a trust anchor to validate the TLS certificate presented by the remote server. - Specifically, it allows verification of incoming requests to prevent header spoofing. - The key "ca.crt" is used to locate the data. - If the config map or expected key is not found, the identity provider is not honored. - If the specified ca data is not valid, the identity provider is not honored. - The namespace for this config map is openshift-config. - properties: - name: - description: name is the metadata.name of the - referenced config map - type: string - required: - - name - type: object - challengeURL: - description: |- - challengeURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect WWW-Authenticate challenges will be - redirected here. - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when challenge is set to true. - type: string - clientCommonNames: - description: |- - clientCommonNames is an optional list of common names to require a match from. If empty, any - client certificate validated against the clientCA bundle is considered authoritative. - items: - type: string - type: array - emailHeaders: - description: emailHeaders is the set of headers - to check for the email address - items: - type: string - type: array - headers: - description: headers is the set of headers to check - for identity information - items: - type: string - type: array - loginURL: - description: |- - loginURL is a URL to redirect unauthenticated /authorize requests to - Unauthenticated requests from OAuth clients which expect interactive logins will be redirected here - ${url} is replaced with the current URL, escaped to be safe in a query parameter - https://www.example.com/sso-login?then=${url} - ${query} is replaced with the current query string - https://www.example.com/auth-proxy/oauth/authorize?${query} - Required when login is set to true. - type: string - nameHeaders: - description: nameHeaders is the set of headers to - check for the display name - items: - type: string - type: array - preferredUsernameHeaders: - description: preferredUsernameHeaders is the set - of headers to check for the preferred username - items: - type: string - type: array - type: object - type: - description: type identifies the identity provider type - for this entry. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - templates: - description: templates allow you to customize pages like the - login page. - properties: - error: - description: |- - error is the name of a secret that specifies a go template to use to render error pages - during the authentication or grant flow. - The key "errors.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default error page is used. - If the specified template is not valid, the default error page is used. - If unspecified, the default error page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - login: - description: |- - login is the name of a secret that specifies a go template to use to render the login page. - The key "login.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default login page is used. - If the specified template is not valid, the default login page is used. - If unspecified, the default login page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - providerSelection: - description: |- - providerSelection is the name of a secret that specifies a go template to use to render - the provider selection page. - The key "providers.html" is used to locate the template data. - If specified and the secret or expected key is not found, the default provider selection page is used. - If the specified template is not valid, the default provider selection page is used. - If unspecified, the default provider selection page is used. - The namespace for this secret is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - secret - type: string - required: - - name - type: object - type: object - tokenConfig: - description: tokenConfig contains options for authorization - and access tokens - properties: - accessTokenInactivityTimeout: - description: |- - accessTokenInactivityTimeout defines the token inactivity timeout - for tokens granted by any client. - The value represents the maximum amount of time that can occur between - consecutive uses of the token. Tokens become invalid if they are not - used within this temporal window. The user will need to acquire a new - token to regain access once a token times out. Takes valid time - duration string such as "5m", "1.5h" or "2h45m". The minimum allowed - value for duration is 300s (5 minutes). If the timeout is configured - per client, then that value takes precedence. If the timeout value is - not specified and the client does not override the value, then tokens - are valid until their lifetime. - - - WARNING: existing tokens' timeout will not be affected (lowered) by changing this value - type: string - accessTokenInactivityTimeoutSeconds: - description: 'accessTokenInactivityTimeoutSeconds - DEPRECATED: - setting this field has no effect.' - format: int32 - type: integer - accessTokenMaxAgeSeconds: - description: accessTokenMaxAgeSeconds defines the maximum - age of access tokens - format: int32 - type: integer - type: object - type: object - x-kubernetes-validations: - - message: spec.configuration.oauth.tokenConfig.accessTokenInactivityTimeout - minimum acceptable token timeout value is 300 seconds - rule: '!has(self.tokenConfig) || !has(self.tokenConfig.accessTokenInactivityTimeout) - || duration(self.tokenConfig.accessTokenInactivityTimeout).getSeconds() - >= 300' - operatorhub: - description: |- - OperatorHub specifies the configuration for the Operator Lifecycle Manager in the HostedCluster. This is only configured at deployment time but the controller are not reconcilling over it. - The OperatorHub configuration will be constantly reconciled if catalog placement is management, but only on cluster creation otherwise. - properties: - disableAllDefaultSources: - description: |- - disableAllDefaultSources allows you to disable all the default hub - sources. If this is true, a specific entry in sources can be used to - enable a default source. If this is false, a specific entry in - sources can be used to disable or enable a default source. - type: boolean - sources: - description: |- - sources is the list of default hub sources and their configuration. - If the list is empty, it implies that the default hub sources are - enabled on the cluster unless disableAllDefaultSources is true. - If disableAllDefaultSources is true and sources is not empty, - the configuration present in sources will take precedence. The list of - default hub sources and their current state will always be reflected in - the status block. - items: - description: HubSource is used to specify the hub source - and its configuration - properties: - disabled: - description: disabled is used to disable a default hub - source on cluster - type: boolean - name: - description: name is the name of one of the default - hub sources - maxLength: 253 - minLength: 1 - type: string - type: object - type: array - type: object - proxy: - description: Proxy holds cluster-wide information on how to configure - default proxies for the cluster. - properties: - httpProxy: - description: httpProxy is the URL of the proxy for HTTP requests. Empty - means unset and will not result in an env var. - type: string - httpsProxy: - description: httpsProxy is the URL of the proxy for HTTPS - requests. Empty means unset and will not result in an env - var. - type: string - noProxy: - description: |- - noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. - Empty means unset and will not result in an env var. - type: string - readinessEndpoints: - description: readinessEndpoints is a list of endpoints used - to verify readiness of the proxy. - items: - type: string - type: array - trustedCA: - description: |- - trustedCA is a reference to a ConfigMap containing a CA certificate bundle. - The trustedCA field should only be consumed by a proxy validator. The - validator is responsible for reading the certificate bundle from the required - key "ca-bundle.crt", merging it with the system default trust bundle, - and writing the merged trust bundle to a ConfigMap named "trusted-ca-bundle" - in the "openshift-config-managed" namespace. Clients that expect to make - proxy connections must use the trusted-ca-bundle for all HTTPS requests to - the proxy, and may use the trusted-ca-bundle for non-proxy HTTPS requests as - well. - - - The namespace for the ConfigMap referenced by trustedCA is - "openshift-config". Here is an example ConfigMap (in yaml): - - - apiVersion: v1 - kind: ConfigMap - metadata: - name: user-ca-bundle - namespace: openshift-config - data: - ca-bundle.crt: | - -----BEGIN CERTIFICATE----- - Custom CA certificate bundle. - -----END CERTIFICATE----- - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - type: object - scheduler: - description: |- - Scheduler holds cluster-wide config information to run the Kubernetes Scheduler - and influence its placement decisions. The canonical name for this config is `cluster`. - properties: - defaultNodeSelector: - description: |- - defaultNodeSelector helps set the cluster-wide default node selector to - restrict pod placement to specific nodes. This is applied to the pods - created in all namespaces and creates an intersection with any existing - nodeSelectors already set on a pod, additionally constraining that pod's selector. - For example, - defaultNodeSelector: "type=user-node,region=east" would set nodeSelector - field in pod spec to "type=user-node,region=east" to all pods created - in all namespaces. Namespaces having project-wide node selectors won't be - impacted even if this field is set. This adds an annotation section to - the namespace. - For example, if a new namespace is created with - node-selector='type=user-node,region=east', - the annotation openshift.io/node-selector: type=user-node,region=east - gets added to the project. When the openshift.io/node-selector annotation - is set on the project the value is used in preference to the value we are setting - for defaultNodeSelector field. - For instance, - openshift.io/node-selector: "type=user-node,region=west" means - that the default of "type=user-node,region=east" set in defaultNodeSelector - would not be applied. - type: string - mastersSchedulable: - description: |- - MastersSchedulable allows masters nodes to be schedulable. When this flag is - turned on, all the master nodes in the cluster will be made schedulable, - so that workload pods can run on them. The default value for this field is false, - meaning none of the master nodes are schedulable. - Important Note: Once the workload pods start running on the master nodes, - extreme care must be taken to ensure that cluster-critical control plane components - are not impacted. - Please turn on this field after doing due diligence. - type: boolean - policy: - description: |- - DEPRECATED: the scheduler Policy API has been deprecated and will be removed in a future release. - policy is a reference to a ConfigMap containing scheduler policy which has - user specified predicates and priorities. If this ConfigMap is not available - scheduler will default to use DefaultAlgorithmProvider. - The namespace for this configmap is openshift-config. - properties: - name: - description: name is the metadata.name of the referenced - config map - type: string - required: - - name - type: object - profile: - description: |- - profile sets which scheduling profile should be set in order to configure scheduling - decisions for new pods. - - - Valid values are "LowNodeUtilization", "HighNodeUtilization", "NoScoring" - Defaults to "LowNodeUtilization" - enum: - - "" - - LowNodeUtilization - - HighNodeUtilization - - NoScoring - type: string - profileCustomizations: - description: profileCustomizations contains configuration - for modifying the default behavior of existing scheduler - profiles. - properties: - dynamicResourceAllocation: - description: |- - dynamicResourceAllocation allows to enable or disable dynamic resource allocation within the scheduler. - Dynamic resource allocation is an API for requesting and sharing resources between pods and containers inside a pod. - Third-party resource drivers are responsible for tracking and allocating resources. - Different kinds of resources support arbitrary parameters for defining requirements and initialization. - Valid values are Enabled, Disabled and omitted. - When omitted, this means no opinion and the platform is left to choose a reasonable default, - which is subject to change over time. - The current default is Disabled. - enum: - - "" - - Enabled - - Disabled - type: string - type: object - type: object - type: object - controlPlaneReleaseImage: - description: |- - ControlPlaneReleaseImage specifies the desired OCP release payload for - control plane components running on the management cluster. - If not defined, ReleaseImage is used - type: string - controllerAvailabilityPolicy: - default: SingleReplica - description: |- - ControllerAvailabilityPolicy specifies the availability policy applied to - critical control plane components. The default value is SingleReplica. - type: string - x-kubernetes-validations: - - message: ControllerAvailabilityPolicy is immutable - rule: self == oldSelf - dns: - description: DNSSpec specifies the DNS configuration in the cluster. - properties: - baseDomain: - description: BaseDomain is the base domain of the cluster. - type: string - baseDomainPrefix: - description: |- - BaseDomainPrefix is the base domain prefix of the cluster. - defaults to clusterName if not set. Set it to "" if you don't want a prefix to be prepended to BaseDomain. - type: string - privateZoneID: - description: |- - PrivateZoneID is the Hosted Zone ID where all the DNS records that are only - available internally to the cluster exist. - type: string - publicZoneID: - description: |- - PublicZoneID is the Hosted Zone ID where all the DNS records that are - publicly accessible to the internet exist. - type: string - required: - - baseDomain - type: object - etcd: - description: |- - Etcd contains metadata about the etcd cluster the hypershift managed Openshift control plane components - use to store data. - properties: - managed: - description: Managed specifies the behavior of an etcd cluster - managed by HyperShift. - properties: - storage: - description: Storage specifies how etcd data is persisted. - properties: - persistentVolume: - description: |- - PersistentVolume is the configuration for PersistentVolume etcd storage. - With this implementation, a PersistentVolume will be allocated for every - etcd member (either 1 or 3 depending on the HostedCluster control plane - availability configuration). - properties: - size: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Size is the minimum size of the data - volume for each etcd member. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: Etcd PV storage size is immutable - rule: self == oldSelf - storageClassName: - description: |- - StorageClassName is the StorageClass of the data volume for each etcd member. - - - See https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1. - type: string - type: object - restoreSnapshotURL: - description: |- - RestoreSnapshotURL allows an optional URL to be provided where - an etcd snapshot can be downloaded, for example a pre-signed URL - referencing a storage service. - This snapshot will be restored on initial startup, only when the etcd PV - is empty. - items: - type: string - type: array - x-kubernetes-validations: - - message: RestoreSnapshotURL shouldn't contain more than - 1 entry - rule: self.size() <= 1 - type: - description: Type is the kind of persistent storage implementation - to use for etcd. - enum: - - PersistentVolume - type: string - required: - - type - type: object - required: - - storage - type: object - managementType: - description: ManagementType defines how the etcd cluster is managed. - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: |- - Unmanaged specifies configuration which enables the control plane to - integrate with an eternally managed etcd cluster. - properties: - endpoint: - description: |- - Endpoint is the full etcd cluster client endpoint URL. For example: - - - https://etcd-client:2379 - - - If the URL uses an HTTPS scheme, the TLS field is required. - pattern: ^https:// - type: string - tls: - description: TLS specifies TLS configuration for HTTPS etcd - client endpoints. - properties: - clientSecret: - description: |- - ClientSecret refers to a secret for client mTLS authentication with the etcd cluster. It - may have the following key/value pairs: - - - etcd-client-ca.crt: Certificate Authority value - etcd-client.crt: Client certificate value - etcd-client.key: Client certificate key value - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - clientSecret - type: object - required: - - endpoint - - tls - type: object - required: - - managementType - type: object - fips: - description: FIPS specifies if the nodes for the cluster will be running - in FIPS mode - type: boolean - imageContentSources: - description: ImageContentSources lists sources/repositories for the - release-image content. - items: - description: |- - ImageContentSource specifies image mirrors that can be used by cluster nodes - to pull content. For cluster workloads, if a container image registry host of - the pullspec matches Source then one of the Mirrors are substituted as hosts - in the pullspec and tried in order to fetch the image. - properties: - mirrors: - description: Mirrors are one or more repositories that may also - contain the same images. - items: - type: string - type: array - source: - description: |- - Source is the repository that users refer to, e.g. in image pull - specifications. - type: string - required: - - source - type: object - type: array - infraID: - type: string - infrastructureAvailabilityPolicy: - default: SingleReplica - description: |- - InfrastructureAvailabilityPolicy specifies the availability policy applied - to infrastructure services which run on cluster nodes. The default value is - SingleReplica. - type: string - issuerURL: - description: |- - IssuerURL is an OIDC issuer URL which is used as the issuer in all - ServiceAccount tokens generated by the control plane API server. The - default value is kubernetes.default.svc, which only works for in-cluster - validation. - type: string - kubeconfig: - description: KubeConfig specifies the name and key for the kubeconfig - secret - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - networking: - description: |- - Networking specifies network configuration for the cluster. - Temporarily optional for backward compatibility, required in future releases. - properties: - apiServer: - description: |- - APIServer contains advanced network settings for the API server that affect - how the APIServer is exposed inside a cluster node. - properties: - advertiseAddress: - description: |- - AdvertiseAddress is the address that nodes will use to talk to the API - server. This is an address associated with the loopback adapter of each - node. If not specified, the controller will take default values. - The default values will be set as 172.20.0.1 or fd00::1. - type: string - allowedCIDRBlocks: - description: |- - AllowedCIDRBlocks is an allow list of CIDR blocks that can access the APIServer - If not specified, traffic is allowed from all addresses. - This depends on underlying support by the cloud provider for Service LoadBalancerSourceRanges - items: - pattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$ - type: string - type: array - port: - description: |- - Port is the port at which the APIServer is exposed inside a node. Other - pods using host networking cannot listen on this port. - If unset 6443 is used. - This is useful to choose a port other than the default one which might interfere with customer environments e.g. https://github.com/openshift/hypershift/pull/356. - Setting this to 443 is possible only for backward compatibility reasons and it's discouraged. - Doing so, it would result in the controller overriding the KAS endpoint in the guest cluster having a discrepancy with the KAS Pod and potentially causing temporarily network failures. - format: int32 - type: integer - type: object - clusterNetwork: - default: - - cidr: 10.132.0.0/14 - description: ClusterNetwork is the list of IP address pools for - pods. - items: - description: |- - ClusterNetworkEntry is a single IP address block for pod IP blocks. IP blocks - are allocated with size 2^HostSubnetLength. - properties: - cidr: - description: CIDR is the IP block address pool. - type: string - hostPrefix: - description: |- - HostPrefix is the prefix size to allocate to each node from the CIDR. - For example, 24 would allocate 2^8=256 adresses to each node. If this - field is not used by the plugin, it can be left unset. - format: int32 - type: integer - required: - - cidr - type: object - type: array - machineNetwork: - description: MachineNetwork is the list of IP address pools for - machines. - items: - description: MachineNetworkEntry is a single IP address block - for node IP blocks. - properties: - cidr: - description: CIDR is the IP block address pool for machines - within the cluster. - type: string - required: - - cidr - type: object - type: array - networkType: - default: OVNKubernetes - description: NetworkType specifies the SDN provider used for cluster - networking. - enum: - - OpenShiftSDN - - Calico - - OVNKubernetes - - Other - type: string - serviceNetwork: - default: - - cidr: 172.31.0.0/16 - description: |- - ServiceNetwork is the list of IP address pools for services. - NOTE: currently only one entry is supported. - items: - description: ServiceNetworkEntry is a single IP address block - for the service network. - properties: - cidr: - description: CIDR is the IP block address pool for services - within the cluster. - type: string - required: - - cidr - type: object - type: array - required: - - clusterNetwork - - networkType - type: object - nodeSelector: - additionalProperties: - type: string - description: NodeSelector when specified, must be true for the pods - managed by the HostedCluster to be scheduled. - type: object - olmCatalogPlacement: - default: management - description: |- - OLMCatalogPlacement specifies the placement of OLM catalog components. By default, - this is set to management and OLM catalog components are deployed onto the management - cluster. If set to guest, the OLM catalog components will be deployed onto the guest - cluster. - enum: - - management - - guest - type: string - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - PlatformSpec specifies the underlying infrastructure provider for the cluster - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies configuration for agent-based installations. - properties: - agentNamespace: - description: AgentNamespace is the namespace where to search - for Agents for this cluster - type: string - required: - - agentNamespace - type: object - aws: - description: AWS specifies configuration for clusters running - on Amazon Web Services. - properties: - additionalAllowedPrincipals: - description: |- - AdditionalAllowedPrincipals specifies a list of additional allowed principal ARNs - to be added to the hosted control plane's VPC Endpoint Service to enable additional - VPC Endpoint connection requests to be automatically accepted. - See https://docs.aws.amazon.com/vpc/latest/privatelink/configure-endpoint-service.html - for more details around VPC Endpoint Service allowed principals. - items: - type: string - type: array - cloudProviderConfig: - description: |- - CloudProviderConfig specifies AWS networking configuration for the control - plane. - This is mainly used for cloud provider controller config: - https://github.com/kubernetes/kubernetes/blob/f5be5052e3d0808abb904aebd3218fe4a5c2dd82/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L1347-L1364 - TODO(dan): should this be named AWSNetworkConfig? - properties: - subnet: - description: Subnet is the subnet to use for control plane - cloud resources. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify - an AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - vpc: - description: VPC is the VPC to use for control plane cloud - resources. - type: string - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - type: string - required: - - vpc - type: object - endpointAccess: - default: Public - description: |- - EndpointAccess specifies the publishing scope of cluster endpoints. The - default is Public. - enum: - - Public - - PublicAndPrivate - - Private - type: string - multiArch: - default: false - description: |- - MultiArch specifies whether the Hosted Cluster will be expected to support NodePools with different - CPU architectures, i.e., supporting arm64 NodePools and supporting amd64 NodePools on the same Hosted Cluster. - type: boolean - region: - description: |- - Region is the AWS region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot AMI for a given release. - type: string - resourceTags: - description: |- - ResourceTags is a list of additional tags to apply to AWS resources created - for the cluster. See - https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - rolesRef: - description: |- - RolesRef contains references to various AWS IAM roles required to enable - integrations such as OIDC. - properties: - controlPlaneOperatorARN: - description: "ControlPlaneOperatorARN is an ARN value - referencing a role appropriate for the Control Plane - Operator.\n\n\nThe following is an example of a valid - policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"ec2:CreateVpcEndpoint\",\n\t\t\t\t\"ec2:DescribeVpcEndpoints\",\n\t\t\t\t\"ec2:ModifyVpcEndpoint\",\n\t\t\t\t\"ec2:DeleteVpcEndpoints\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"route53:ListHostedZones\",\n\t\t\t\t\"ec2:CreateSecurityGroup\",\n\t\t\t\t\"ec2:AuthorizeSecurityGroupIngress\",\n\t\t\t\t\"ec2:AuthorizeSecurityGroupEgress\",\n\t\t\t\t\"ec2:DeleteSecurityGroup\",\n\t\t\t\t\"ec2:RevokeSecurityGroupIngress\",\n\t\t\t\t\"ec2:RevokeSecurityGroupEgress\",\n\t\t\t\t\"ec2:DescribeSecurityGroups\",\n\t\t\t\t\"ec2:DescribeVpcs\",\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\",\n\t\t\t\t\"route53:ListResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - \"arn:aws:route53:::%s\"\n\t\t}\n\t]\n}" - type: string - imageRegistryARN: - description: "ImageRegistryARN is an ARN value referencing - a role appropriate for the Image Registry Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"s3:CreateBucket\",\n\t\t\t\t\"s3:DeleteBucket\",\n\t\t\t\t\"s3:PutBucketTagging\",\n\t\t\t\t\"s3:GetBucketTagging\",\n\t\t\t\t\"s3:PutBucketPublicAccessBlock\",\n\t\t\t\t\"s3:GetBucketPublicAccessBlock\",\n\t\t\t\t\"s3:PutEncryptionConfiguration\",\n\t\t\t\t\"s3:GetEncryptionConfiguration\",\n\t\t\t\t\"s3:PutLifecycleConfiguration\",\n\t\t\t\t\"s3:GetLifecycleConfiguration\",\n\t\t\t\t\"s3:GetBucketLocation\",\n\t\t\t\t\"s3:ListBucket\",\n\t\t\t\t\"s3:GetObject\",\n\t\t\t\t\"s3:PutObject\",\n\t\t\t\t\"s3:DeleteObject\",\n\t\t\t\t\"s3:ListBucketMultipartUploads\",\n\t\t\t\t\"s3:AbortMultipartUpload\",\n\t\t\t\t\"s3:ListMultipartUploadParts\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - ingressARN: - description: "The referenced role must have a trust relationship - that allows it to be assumed via web identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ .ProviderName - }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nIngressARN - is an ARN value referencing a role appropriate for the - Ingress Operator.\n\n\nThe following is an example of - a valid policy document:\n\n\n{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": - [\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"elasticloadbalancing:DescribeLoadBalancers\",\n\t\t\t\t\"tag:GetResources\",\n\t\t\t\t\"route53:ListHostedZones\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t},\n\t\t{\n\t\t\t\"Effect\": \"Allow\",\n\t\t\t\"Action\": - [\n\t\t\t\t\"route53:ChangeResourceRecordSets\"\n\t\t\t],\n\t\t\t\"Resource\": - [\n\t\t\t\t\"arn:aws:route53:::PUBLIC_ZONE_ID\",\n\t\t\t\t\"arn:aws:route53:::PRIVATE_ZONE_ID\"\n\t\t\t]\n\t\t}\n\t]\n}" - type: string - kubeCloudControllerARN: - description: |- - KubeCloudControllerARN is an ARN value referencing a role appropriate for the KCM/KCC. - Source: https://cloud-provider-aws.sigs.k8s.io/prerequisites/#iam-policies - - - The following is an example of a valid policy document: - - - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingGroups", - "autoscaling:DescribeLaunchConfigurations", - "autoscaling:DescribeTags", - "ec2:DescribeAvailabilityZones", - "ec2:DescribeInstances", - "ec2:DescribeImages", - "ec2:DescribeRegions", - "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVolumes", - "ec2:CreateSecurityGroup", - "ec2:CreateTags", - "ec2:CreateVolume", - "ec2:ModifyInstanceAttribute", - "ec2:ModifyVolume", - "ec2:AttachVolume", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateRoute", - "ec2:DeleteRoute", - "ec2:DeleteSecurityGroup", - "ec2:DeleteVolume", - "ec2:DetachVolume", - "ec2:RevokeSecurityGroupIngress", - "ec2:DescribeVpcs", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:AttachLoadBalancerToSubnets", - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", - "elasticloadbalancing:CreateLoadBalancer", - "elasticloadbalancing:CreateLoadBalancerPolicy", - "elasticloadbalancing:CreateLoadBalancerListeners", - "elasticloadbalancing:ConfigureHealthCheck", - "elasticloadbalancing:DeleteLoadBalancer", - "elasticloadbalancing:DeleteLoadBalancerListeners", - "elasticloadbalancing:DescribeLoadBalancers", - "elasticloadbalancing:DescribeLoadBalancerAttributes", - "elasticloadbalancing:DetachLoadBalancerFromSubnets", - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:ModifyLoadBalancerAttributes", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer", - "elasticloadbalancing:AddTags", - "elasticloadbalancing:CreateListener", - "elasticloadbalancing:CreateTargetGroup", - "elasticloadbalancing:DeleteListener", - "elasticloadbalancing:DeleteTargetGroup", - "elasticloadbalancing:DeregisterTargets", - "elasticloadbalancing:DescribeListeners", - "elasticloadbalancing:DescribeLoadBalancerPolicies", - "elasticloadbalancing:DescribeTargetGroups", - "elasticloadbalancing:DescribeTargetHealth", - "elasticloadbalancing:ModifyListener", - "elasticloadbalancing:ModifyTargetGroup", - "elasticloadbalancing:RegisterTargets", - "elasticloadbalancing:SetLoadBalancerPoliciesOfListener", - "iam:CreateServiceLinkedRole", - "kms:DescribeKey" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ] - } - type: string - networkARN: - description: "NetworkARN is an ARN value referencing a - role appropriate for the Network Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInstanceStatus\",\n \"ec2:DescribeInstanceTypes\",\n - \ \"ec2:UnassignPrivateIpAddresses\",\n \"ec2:AssignPrivateIpAddresses\",\n - \ \"ec2:UnassignIpv6Addresses\",\n \"ec2:AssignIpv6Addresses\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeNetworkInterfaces\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - nodePoolManagementARN: - description: "NodePoolManagementARN is an ARN value referencing - a role appropriate for the CAPI Controller.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n - \ \"Version\": \"2012-10-17\",\n \"Statement\": [\n - \ {\n \"Action\": [\n \"ec2:AssociateRouteTable\",\n - \ \"ec2:AttachInternetGateway\",\n \"ec2:AuthorizeSecurityGroupIngress\",\n - \ \"ec2:CreateInternetGateway\",\n \"ec2:CreateNatGateway\",\n - \ \"ec2:CreateRoute\",\n \"ec2:CreateRouteTable\",\n - \ \"ec2:CreateSecurityGroup\",\n \"ec2:CreateSubnet\",\n - \ \"ec2:CreateTags\",\n \"ec2:DeleteInternetGateway\",\n - \ \"ec2:DeleteNatGateway\",\n \"ec2:DeleteRouteTable\",\n - \ \"ec2:DeleteSecurityGroup\",\n \"ec2:DeleteSubnet\",\n - \ \"ec2:DeleteTags\",\n \"ec2:DescribeAccountAttributes\",\n - \ \"ec2:DescribeAddresses\",\n \"ec2:DescribeAvailabilityZones\",\n - \ \"ec2:DescribeImages\",\n \"ec2:DescribeInstances\",\n - \ \"ec2:DescribeInternetGateways\",\n \"ec2:DescribeNatGateways\",\n - \ \"ec2:DescribeNetworkInterfaces\",\n \"ec2:DescribeNetworkInterfaceAttribute\",\n - \ \"ec2:DescribeRouteTables\",\n \"ec2:DescribeSecurityGroups\",\n - \ \"ec2:DescribeSubnets\",\n \"ec2:DescribeVpcs\",\n - \ \"ec2:DescribeVpcAttribute\",\n \"ec2:DescribeVolumes\",\n - \ \"ec2:DetachInternetGateway\",\n \"ec2:DisassociateRouteTable\",\n - \ \"ec2:DisassociateAddress\",\n \"ec2:ModifyInstanceAttribute\",\n - \ \"ec2:ModifyNetworkInterfaceAttribute\",\n \"ec2:ModifySubnetAttribute\",\n - \ \"ec2:RevokeSecurityGroupIngress\",\n \"ec2:RunInstances\",\n - \ \"ec2:TerminateInstances\",\n \"tag:GetResources\",\n - \ \"ec2:CreateLaunchTemplate\",\n \"ec2:CreateLaunchTemplateVersion\",\n - \ \"ec2:DescribeLaunchTemplates\",\n \"ec2:DescribeLaunchTemplateVersions\",\n - \ \"ec2:DeleteLaunchTemplate\",\n \"ec2:DeleteLaunchTemplateVersions\"\n - \ ],\n \"Resource\": [\n \"*\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n {\n \"Condition\": - {\n \"StringLike\": {\n \"iam:AWSServiceName\": - \"elasticloadbalancing.amazonaws.com\"\n }\n },\n - \ \"Action\": [\n \"iam:CreateServiceLinkedRole\"\n - \ ],\n \"Resource\": [\n \"arn:*:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing\"\n - \ ],\n \"Effect\": \"Allow\"\n },\n {\n \"Action\": - [\n \"iam:PassRole\"\n ],\n \"Resource\": - [\n \"arn:*:iam::*:role/*-worker-role\"\n ],\n - \ \"Effect\": \"Allow\"\n },\n\t {\n\t \t\"Effect\": - \"Allow\",\n\t \t\"Action\": [\n\t \t\t\"kms:Decrypt\",\n\t - \ \t\t\"kms:ReEncrypt\",\n\t \t\t\"kms:GenerateDataKeyWithoutPlainText\",\n\t - \ \t\t\"kms:DescribeKey\"\n\t \t],\n\t \t\"Resource\": - \"*\"\n\t },\n\t {\n\t \t\"Effect\": \"Allow\",\n\t - \ \t\"Action\": [\n\t \t\t\"kms:CreateGrant\"\n\t \t],\n\t - \ \t\"Resource\": \"*\",\n\t \t\"Condition\": {\n\t - \ \t\t\"Bool\": {\n\t \t\t\t\"kms:GrantIsForAWSResource\": - true\n\t \t\t}\n\t \t}\n\t }\n ]\n}" - type: string - storageARN: - description: "StorageARN is an ARN value referencing a - role appropriate for the Storage Operator.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"ec2:AttachVolume\",\n\t\t\t\t\"ec2:CreateSnapshot\",\n\t\t\t\t\"ec2:CreateTags\",\n\t\t\t\t\"ec2:CreateVolume\",\n\t\t\t\t\"ec2:DeleteSnapshot\",\n\t\t\t\t\"ec2:DeleteTags\",\n\t\t\t\t\"ec2:DeleteVolume\",\n\t\t\t\t\"ec2:DescribeInstances\",\n\t\t\t\t\"ec2:DescribeSnapshots\",\n\t\t\t\t\"ec2:DescribeTags\",\n\t\t\t\t\"ec2:DescribeVolumes\",\n\t\t\t\t\"ec2:DescribeVolumesModifications\",\n\t\t\t\t\"ec2:DetachVolume\",\n\t\t\t\t\"ec2:ModifyVolume\"\n\t\t\t],\n\t\t\t\"Resource\": - \"*\"\n\t\t}\n\t]\n}" - type: string - required: - - controlPlaneOperatorARN - - imageRegistryARN - - ingressARN - - kubeCloudControllerARN - - networkARN - - nodePoolManagementARN - - storageARN - type: object - serviceEndpoints: - description: |- - ServiceEndpoints specifies optional custom endpoints which will override - the default service endpoint of specific AWS Services. - - - There must be only one ServiceEndpoint for a given service name. - items: - description: |- - AWSServiceEndpoint stores the configuration for services to - override existing defaults of AWS Services. - properties: - name: - description: |- - Name is the name of the AWS service. - This must be provided and cannot be empty. - type: string - url: - description: |- - URL is fully qualified URI with scheme https, that overrides the default generated - endpoint for a client. - This must be provided and cannot be empty. - pattern: ^https:// - type: string - required: - - name - - url - type: object - type: array - required: - - region - - rolesRef - type: object - azure: - description: Azure defines azure specific settings - properties: - cloud: - default: AzurePublicCloud - description: 'Cloud is the cloud environment identifier, valid - values could be found here: https://github.com/Azure/go-autorest/blob/4c0e21ca2bbb3251fe7853e6f9df6397f53dd419/autorest/azure/environments.go#L33' - enum: - - AzurePublicCloud - - AzureUSGovernmentCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureStackCloud - type: string - credentials: - description: |- - Credentials is the object containing existing Azure credentials needed for creating and managing cloud - infrastructure resources. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - location: - description: |- - Location is the Azure region in where all the cloud infrastructure resources will be created. - - - Example: eastus - type: string - x-kubernetes-validations: - - message: Location is immutable - rule: self == oldSelf - resourceGroup: - default: default - description: |- - ResourceGroupName is the name of an existing resource group where all cloud resources created by the Hosted - Cluster are to be placed. The resource group is expected to exist under the same subscription as SubscriptionID. - - - In ARO HCP, this will be the managed resource group where customer cloud resources will be created. - - - Resource group naming requirements can be found here: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ResourceGroup.Name/. - - - Example: if your resource group ID is /subscriptions//resourceGroups/, your - ResourceGroupName is . - pattern: ^[a-zA-Z0-9_()\-\.]{1,89}[a-zA-Z0-9_()\-]$ - type: string - x-kubernetes-validations: - - message: ResourceGroupName is immutable - rule: self == oldSelf - securityGroupID: - description: |- - SecurityGroupID is the ID of an existing security group on the SubnetID. This field is provided as part of the - configuration for the Azure cloud provider, aka Azure cloud controller manager (CCM). This security group is - expected to exist under the same subscription as SubscriptionID. - type: string - x-kubernetes-validations: - - message: SecurityGroupID is immutable - rule: self == oldSelf - subnetID: - description: |- - SubnetID is the subnet ID of an existing subnet where the load balancer for node egress will be created. This - subnet is expected to be a subnet within the VNET specified in VnetID. This subnet is expected to exist under the - same subscription as SubscriptionID. - - - In ARO HCP, managed services will create the aforementioned load balancer in ResourceGroupName. - type: string - x-kubernetes-validations: - - message: SubnetID is immutable - rule: self == oldSelf - subscriptionID: - description: SubscriptionID is a unique identifier for an - Azure subscription used to manage resources. - type: string - x-kubernetes-validations: - - message: SubscriptionID is immutable - rule: self == oldSelf - vnetID: - description: |- - VnetID is the ID of an existing VNET to use in creating VMs. The VNET can exist in a different resource group - other than the one specified in ResourceGroupName, but it must exist under the same subscription as - SubscriptionID. - - - In ARO HCP, this will be the ID of the customer provided VNET. - - - Example: /subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/ - type: string - x-kubernetes-validations: - - message: VnetID is immutable - rule: self == oldSelf - required: - - credentials - - location - - resourceGroup - - subnetID - - subscriptionID - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: KubeVirt defines KubeVirt specific settings for cluster - components. - properties: - baseDomainPassthrough: - description: |- - BaseDomainPassthrough toggles whether or not an automatically - generated base domain for the guest cluster should be used that - is a subdomain of the management cluster's *.apps DNS. - - - For the KubeVirt platform, the basedomain can be autogenerated using - the *.apps domain of the management/infra hosting cluster - This makes the guest cluster's base domain a subdomain of the - hypershift infra/mgmt cluster's base domain. - - - Example: - Infra/Mgmt cluster's DNS - Base: example.com - Cluster: mgmt-cluster.example.com - Apps: *.apps.mgmt-cluster.example.com - KubeVirt Guest cluster's DNS - Base: apps.mgmt-cluster.example.com - Cluster: guest.apps.mgmt-cluster.example.com - Apps: *.apps.guest.apps.mgmt-cluster.example.com - - - This is possible using OCP wildcard routes - type: boolean - x-kubernetes-validations: - - message: baseDomainPassthrough is immutable - rule: self == oldSelf - credentials: - description: |- - Credentials defines the client credentials used when creating KubeVirt virtual machines. - Defining credentials is only necessary when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - generateID: - description: |- - GenerateID is used to uniquely apply a name suffix to resources associated with - kubevirt infrastructure resources - maxLength: 11 - type: string - x-kubernetes-validations: - - message: Kubevirt GenerateID is immutable once set - rule: self == oldSelf - storageDriver: - description: |- - StorageDriver defines how the KubeVirt CSI driver exposes StorageClasses on - the infra cluster (hosting the VMs) to the guest cluster. - properties: - manual: - description: |- - Manual is used to explicilty define how the infra storageclasses are - mapped to guest storageclasses - properties: - storageClassMapping: - description: |- - StorageClassMapping maps StorageClasses on the infra cluster hosting - the KubeVirt VMs to StorageClasses that are made available within the - Guest Cluster. - - - NOTE: It is possible that not all capablities of an infra cluster's - storageclass will be present for the corresponding guest clusters storageclass. - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestStorageClassName: - description: |- - GuestStorageClassName is the name that the corresponding storageclass will - be called within the guest cluster - type: string - infraStorageClassName: - description: |- - InfraStorageClassName is the name of the infra cluster storage class that - will be exposed to the guest. - type: string - required: - - guestStorageClassName - - infraStorageClassName - type: object - type: array - x-kubernetes-validations: - - message: storageClassMapping is immutable - rule: self == oldSelf - volumeSnapshotClassMapping: - items: - properties: - group: - description: Group contains which group this - mapping belongs to. - type: string - guestVolumeSnapshotClassName: - description: |- - GuestVolumeSnapshotClassName is the name that the corresponding volumeSnapshotClass will - be called within the guest cluster - type: string - infraVolumeSnapshotClassName: - description: |- - InfraStorageClassName is the name of the infra cluster volume snapshot class that - will be exposed to the guest. - type: string - required: - - guestVolumeSnapshotClassName - - infraVolumeSnapshotClassName - type: object - type: array - x-kubernetes-validations: - - message: volumeSnapshotClassMapping is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver.Manual is immutable - rule: self == oldSelf - type: - default: Default - description: Type represents the type of kubevirt csi - driver configuration to use - enum: - - None - - Default - - Manual - type: string - x-kubernetes-validations: - - message: storageDriver.Type is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: storageDriver is immutable - rule: self == oldSelf - type: object - x-kubernetes-validations: - - message: Kubevirt GenerateID is required once set - rule: '!has(oldSelf.generateID) || has(self.generateID)' - openstack: - description: OpenStack specifies configuration for clusters running - on OpenStack. - properties: - disableExternalNetwork: - description: |- - DisableExternalNetwork specifies whether or not to attempt to connect the cluster - to an external network. This allows for the creation of clusters when connecting - to an external network is not possible or desirable, e.g. if using a provider network. - type: boolean - externalNetwork: - description: |- - ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. - This option is ignored if DisableExternalNetwork is set to true. - - - If ExternalNetwork is defined it must refer to exactly one external network. - - - If ExternalNetwork is not defined or is empty the controller will use any - existing external network as long as there is only one. It is an - error if ExternalNetwork is not defined and there are multiple - external networks unless DisableExternalNetwork is also set. - - - If ExternalNetwork is not defined and there are no external networks - the controller will proceed as though DisableExternalNetwork was set. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - network to filter by. - type: string - name: - description: Name is the name of the network to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the network - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling the hosted cluster. - properties: - cloudName: - description: CloudName specifies the name of the entry - in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - ingressFloatingIP: - description: |- - IngressFloatingIP is an available floating IP in your OpenStack cluster that will - be associated with the OpenShift ingress port. - type: string - managedSubnets: - description: |- - ManagedSubnets describe the OpenStack Subnet to be created. Cluster actuator will create a network, - and a subnet with the defined DNSNameservers, AllocationPools and the CIDR defined in the HostedCluster - MachineNetwork, and a router connected to the subnet. Currently only one IPv4 - subnet is supported. - items: - properties: - allocationPools: - description: |- - AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. - If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from - outside of these ranges manually. - items: - properties: - end: - description: End represents the end of the AlloctionPool, - that is the highest IP of the pool. - type: string - start: - description: Start represents the start of the - AllocationPool, that is the lowest IP of the - pool. - type: string - required: - - end - - start - type: object - type: array - dnsNameservers: - description: |- - DNSNameservers holds a list of DNS server addresses that will be provided when creating - the subnet. These addresses need to have the same IP version as CIDR. - items: - type: string - type: array - type: object - maxItems: 1 - type: array - x-kubernetes-list-type: atomic - network: - description: |- - Network specifies an existing network to use if no ManagedSubnets - are specified. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - network to filter by. - type: string - name: - description: Name is the name of the network to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the network - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - networkMTU: - description: |- - NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. - This value will be used only if the Cluster actuator creates the network. - If left empty, the network will have the default MTU defined in Openstack network service. - To use this field, the Openstack installation requires the net-mtu neutron API extension. - type: integer - router: - description: |- - Router specifies an existing router to be used if ManagedSubnets are - specified. If specified, no new router will be created. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - router. If provided, cannot be empty. - minProperties: 1 - properties: - description: - description: Description is the description of the - router to filter by. - type: string - name: - description: Name is the name of the router to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the router - to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the router to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - subnets: - description: |- - Subnets specifies existing subnets to use if not ManagedSubnets are - specified. All subnets must be in the network specified by Network. - There can be zero, one, or two subnets. If no subnets are specified, - all subnets in Network will be used. If 2 subnets are specified, one - must be IPv4 and the other IPv6. - items: - description: SubnetParam specifies an OpenStack subnet to - use. It may be specified by either ID or filter, but not - both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the - subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - description: CIDR is the CIDR of the subnet to filter - by. - type: string - description: - description: Description is the description of the - subnet to filter by. - type: string - gatewayIP: - description: GatewayIP is the gateway IP of the - subnet to filter by. - type: string - ipVersion: - description: IPVersion is the IP version of the - subnet to filter by. - type: integer - ipv6AddressMode: - description: IPv6AddressMode is the IPv6 address - mode of the subnet to filter by. - type: string - ipv6RAMode: - description: IPv6RAMode is the IPv6 RA mode of the - subnet to filter by. - type: string - name: - description: Name is the name of the subnet to filter - by. - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - description: ProjectID is the project ID of the - subnet to filter by. - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not - be validated. - format: uuid - type: string - type: object - maxItems: 2 - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags to set on all resources in cluster which - support tags - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - identityRef - type: object - powervs: - description: |- - PowerVS specifies configuration for clusters running on IBMCloud Power VS Service. - This field is immutable. Once set, It can't be changed. - properties: - accountID: - description: |- - AccountID is the IBMCloud account id. - This field is immutable. Once set, It can't be changed. - type: string - cisInstanceCRN: - description: |- - CISInstanceCRN is the IBMCloud CIS Service Instance's Cloud Resource Name - This field is immutable. Once set, It can't be changed. - pattern: '^crn:' - type: string - imageRegistryOperatorCloudCreds: - description: |- - ImageRegistryOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for image registry operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - ingressOperatorCloudCreds: - description: |- - IngressOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for ingress operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - kubeCloudControllerCreds: - description: |- - KubeCloudControllerCreds is a reference to a secret containing cloud - credentials with permissions matching the cloud controller policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "cloud controller policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - nodePoolManagementCreds: - description: |- - NodePoolManagementCreds is a reference to a secret containing cloud - credentials with permissions matching the node pool management policy. - This field is immutable. Once set, It can't be changed. - - - TODO(dan): document the "node pool management policy" - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - region: - description: |- - Region is the IBMCloud region in which the cluster resides. This configures the - OCP control plane cloud integrations, and is used by NodePool to resolve - the correct boot image for a given release. - This field is immutable. Once set, It can't be changed. - type: string - resourceGroup: - description: |- - ResourceGroup is the IBMCloud Resource Group in which the cluster resides. - This field is immutable. Once set, It can't be changed. - type: string - serviceInstanceID: - description: |- - ServiceInstance is the reference to the Power VS service on which the server instance(VM) will be created. - Power VS service is a container for all Power VS instances at a specific geographic region. - serviceInstance can be created via IBM Cloud catalog or CLI. - ServiceInstanceID is the unique identifier that can be obtained from IBM Cloud UI or IBM Cloud cli. - - - More detail about Power VS service instance. - https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server - - - This field is immutable. Once set, It can't be changed. - type: string - storageOperatorCloudCreds: - description: |- - StorageOperatorCloudCreds is a reference to a secret containing ibm cloud - credentials for storage operator to get authenticated with ibm cloud. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - subnet: - description: |- - Subnet is the subnet to use for control plane cloud resources. - This field is immutable. Once set, It can't be changed. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - vpc: - description: |- - VPC specifies IBM Cloud PowerVS Load Balancing configuration for the control - plane. - This field is immutable. Once set, It can't be changed. - properties: - name: - description: |- - Name for VPC to used for all the service load balancer. - This field is immutable. Once set, It can't be changed. - type: string - region: - description: |- - Region is the IBMCloud region in which VPC gets created, this VPC used for all the ingress traffic - into the OCP cluster. - This field is immutable. Once set, It can't be changed. - type: string - subnet: - description: |- - Subnet is the subnet to use for load balancer. - This field is immutable. Once set, It can't be changed. - type: string - zone: - description: |- - Zone is the availability zone where load balancer cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - name - - region - type: object - zone: - description: |- - Zone is the availability zone where control plane cloud resources are - created. - This field is immutable. Once set, It can't be changed. - type: string - required: - - accountID - - cisInstanceCRN - - imageRegistryOperatorCloudCreds - - ingressOperatorCloudCreds - - kubeCloudControllerCreds - - nodePoolManagementCreds - - region - - resourceGroup - - serviceInstanceID - - storageOperatorCloudCreds - - subnet - - vpc - - zone - type: object - type: - description: Type is the type of infrastructure provider for the - cluster. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - - OpenStack - type: string - required: - - type - type: object - pullSecret: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - releaseImage: - description: ReleaseImage is the release image applied to the hosted - control plane. - type: string - secretEncryption: - description: |- - SecretEncryption contains metadata about the kubernetes secret encryption strategy being used for the - cluster when applicable. - properties: - aescbc: - description: AESCBC defines metadata about the AESCBC secret encryption - strategy - properties: - activeKey: - description: ActiveKey defines the active key used to encrypt - new secrets - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - activeKey - type: object - kms: - description: KMS defines metadata about the kms secret encryption - strategy - properties: - aws: - description: AWS defines metadata about the configuration - of the AWS KMS Secret Encryption provider - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - auth: - description: Auth defines metadata about the management - of credentials used to interact with AWS KMS - properties: - awsKms: - description: "The referenced role must have a trust - relationship that allows it to be assumed via web - identity.\nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html.\nExample:\n{\n\t\t\"Version\": - \"2012-10-17\",\n\t\t\"Statement\": [\n\t\t\t{\n\t\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\t\"Principal\": {\n\t\t\t\t\t\"Federated\": - \"{{ .ProviderARN }}\"\n\t\t\t\t},\n\t\t\t\t\t\"Action\": - \"sts:AssumeRoleWithWebIdentity\",\n\t\t\t\t\"Condition\": - {\n\t\t\t\t\t\"StringEquals\": {\n\t\t\t\t\t\t\"{{ - .ProviderName }}:sub\": {{ .ServiceAccounts }}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\nAWSKMSARN - is an ARN value referencing a role appropriate for - managing the auth via the AWS KMS key.\n\n\nThe - following is an example of a valid policy document:\n\n\n{\n\t\"Version\": - \"2012-10-17\",\n\t\"Statement\": [\n \t{\n\t\t\t\"Effect\": - \"Allow\",\n\t\t\t\"Action\": [\n\t\t\t\t\"kms:Encrypt\",\n\t\t\t\t\"kms:Decrypt\",\n\t\t\t\t\"kms:ReEncrypt*\",\n\t\t\t\t\"kms:GenerateDataKey*\",\n\t\t\t\t\"kms:DescribeKey\"\n\t\t\t],\n\t\t\t\"Resource\": - %q\n\t\t}\n\t]\n}" - type: string - required: - - awsKms - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - arn: - description: ARN is the Amazon Resource Name for the - encryption key - pattern: '^arn:' - type: string - required: - - arn - type: object - region: - description: Region contains the AWS region - type: string - required: - - activeKey - - auth - - region - type: object - azure: - description: Azure defines metadata about the configuration - of the Azure KMS Secret Encryption provider using Azure - key vault - properties: - activeKey: - description: ActiveKey defines the active key used to - encrypt new secrets - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - backupKey: - description: |- - BackupKey defines the old key during the rotation process so previously created - secrets can continue to be decrypted until they are all re-encrypted with the active key. - properties: - keyName: - description: KeyName is the name of the keyvault key - used for encrypt/decrypt - type: string - keyVaultName: - description: |- - KeyVaultName is the name of the keyvault. Must match criteria specified at https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name - Your Microsoft Entra application used to create the cluster must be authorized to access this keyvault, e.g using the AzureCLI: - `az keyvault set-policy -n $KEYVAULT_NAME --key-permissions decrypt encrypt --spn ` - type: string - keyVersion: - description: KeyVersion contains the version of the - key to use - type: string - required: - - keyName - - keyVaultName - - keyVersion - type: object - required: - - activeKey - type: object - ibmcloud: - description: IBMCloud defines metadata for the IBM Cloud KMS - encryption strategy - properties: - auth: - description: Auth defines metadata for how authentication - is done with IBM Cloud KMS - properties: - managed: - description: |- - Managed defines metadata around the service to service authentication strategy for the IBM Cloud - KMS system (all provider managed). - type: object - type: - description: Type defines the IBM Cloud KMS authentication - strategy - enum: - - Managed - - Unmanaged - type: string - unmanaged: - description: Unmanaged defines the auth metadata the - customer provides to interact with IBM Cloud KMS - properties: - credentials: - description: |- - Credentials should reference a secret with a key field of IBMCloudIAMAPIKeySecretKey that contains a apikey to - call IBM Cloud KMS APIs - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - credentials - type: object - required: - - type - type: object - keyList: - description: KeyList defines the list of keys used for - data encryption - items: - description: IBMCloudKMSKeyEntry defines metadata for - an IBM Cloud KMS encryption key - properties: - correlationID: - description: CorrelationID is an identifier used - to track all api call usage from hypershift - type: string - crkID: - description: CRKID is the customer rook key id - type: string - instanceID: - description: InstanceID is the id for the key protect - instance - type: string - keyVersion: - description: |- - KeyVersion is a unique number associated with the key. The number increments whenever a new - key is enabled for data encryption. - type: integer - url: - description: URL is the url to call key protect - apis over - pattern: ^https:// - type: string - required: - - correlationID - - crkID - - instanceID - - keyVersion - - url - type: object - type: array - region: - description: Region is the IBM Cloud region - type: string - required: - - auth - - keyList - - region - type: object - provider: - description: Provider defines the KMS provider - enum: - - IBMCloud - - AWS - - Azure - type: string - required: - - provider - type: object - type: - description: Type defines the type of kube secret encryption being - used - enum: - - kms - - aescbc - type: string - required: - - type - type: object - serviceAccountSigningKey: - description: |- - ServiceAccountSigningKey is a reference to a secret containing the private key - used by the service account token issuer. The secret is expected to contain - a single key named "key". If not specified, a service account signing key will - be generated automatically for the cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - services: - description: |- - Services defines metadata about how control plane services are published - in the management cluster. - items: - description: |- - ServicePublishingStrategyMapping specifies how individual control plane - services are published from the hosting cluster of a control plane. - properties: - service: - description: Service identifies the type of service being published. - enum: - - APIServer - - OAuthServer - - OIDC - - Konnectivity - - Ignition - - OVNSbDb - type: string - servicePublishingStrategy: - description: ServicePublishingStrategy specifies how to publish - Service. - properties: - loadBalancer: - description: LoadBalancer configures exposing a service - using a LoadBalancer. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the LoadBalancer. - type: string - type: object - nodePort: - description: NodePort configures exposing a service using - a NodePort. - properties: - address: - description: Address is the host/ip that the NodePort - service is exposed over. - type: string - port: - description: |- - Port is the port of the NodePort service. If <=0, the port is dynamically - assigned when the service is created. - format: int32 - type: integer - required: - - address - type: object - route: - description: Route configures exposing a service using a - Route. - properties: - hostname: - description: Hostname is the name of the DNS record - that will be created pointing to the Route. - type: string - type: object - type: - description: Type is the publishing strategy used for the - service. - enum: - - LoadBalancer - - NodePort - - Route - - None - - S3 - type: string - required: - - type - type: object - required: - - service - - servicePublishingStrategy - type: object - type: array - sshKey: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - tolerations: - description: Tolerations when specified, define what custome tolerations - are added to the hcp pods. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - updateService: - description: |- - updateService may be used to specify the preferred upstream update service. - By default it will use the appropriate update service for the cluster and region. - type: string - required: - - dns - - etcd - - infraID - - issuerURL - - platform - - pullSecret - - releaseImage - - services - - sshKey - type: object - status: - description: HostedControlPlaneStatus defines the observed state of HostedControlPlane - properties: - conditions: - description: |- - Condition contains details for one aspect of the current state of the HostedControlPlane. - Current condition types are: "Available" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint contains the endpoint information by which - external clients can access the control plane. This is populated - after the infrastructure is ready. - properties: - host: - description: Host is the hostname on which the API server is serving. - type: string - port: - description: Port is the port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - externalManagedControlPlane: - default: true - description: |- - ExternalManagedControlPlane indicates to cluster-api that the control plane - is managed by an external service. - https://github.com/kubernetes-sigs/cluster-api/blob/65e5385bffd71bf4aad3cf34a537f11b217c7fab/controllers/machine_controller.go#L468 - type: boolean - initialized: - default: false - description: |- - Initialized denotes whether or not the control plane has - provided a kubeadm-config. - Once this condition is marked true, its value is never changed. See the Ready condition for an indication of - the current readiness of the cluster's control plane. - This satisfies CAPI contract https://github.com/kubernetes-sigs/cluster-api/blob/cd3a694deac89d5ebeb888307deaa61487207aa0/controllers/cluster_controller_phases.go#L238-L252 - type: boolean - kubeConfig: - description: |- - KubeConfig is a reference to the secret containing the default kubeconfig - for this control plane. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - kubeadminPassword: - description: |- - KubeadminPassword is a reference to the secret containing the initial kubeadmin password - for the guest cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - lastReleaseImageTransitionTime: - description: |- - lastReleaseImageTransitionTime is the time of the last update to the current - releaseImage property. - - - Deprecated: Use versionStatus.history[0].startedTime instead. - format: date-time - type: string - nodeCount: - description: NodeCount tracks the number of nodes in the HostedControlPlane. - type: integer - oauthCallbackURLTemplate: - description: |- - OAuthCallbackURLTemplate contains a template for the URL to use as a callback - for identity providers. The [identity-provider-name] placeholder must be replaced - with the name of an identity provider defined on the HostedCluster. - This is populated after the infrastructure is ready. - type: string - platform: - description: Platform contains platform-specific status of the HostedCluster - properties: - aws: - description: AWSPlatformStatus contains status specific to the - AWS platform - properties: - defaultWorkerSecurityGroupID: - description: |- - DefaultWorkerSecurityGroupID is the ID of a security group created by - the control plane operator. It is always added to worker machines in - addition to any security groups specified in the NodePool. - type: string - type: object - type: object - ready: - default: false - description: |- - Ready denotes that the HostedControlPlane API Server is ready to - receive requests - This satisfies CAPI contract https://github.com/kubernetes-sigs/cluster-api/blob/cd3a694deac89d5ebeb888307deaa61487207aa0/controllers/cluster_controller_phases.go#L226-L230 - type: boolean - releaseImage: - description: |- - ReleaseImage is the release image applied to the hosted control plane. - - - Deprecated: Use versionStatus.desired.image instead. - type: string - version: - description: |- - Version is the semantic version of the release applied by - the hosted control plane operator - - - Deprecated: Use versionStatus.desired.version instead. - type: string - versionStatus: - description: |- - versionStatus is the status of the release version applied by the - hosted control plane operator. - properties: - availableUpdates: - description: |- - availableUpdates contains updates recommended for this - cluster. Updates which appear in conditionalUpdates but not in - availableUpdates may expose this cluster to known issues. This list - may be empty if no updates are recommended, if the update service - is unavailable, or if an invalid channel has been specified. - items: - description: Release represents an OpenShift release image and - associated metadata. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - nullable: true - type: array - conditionalUpdates: - description: |- - conditionalUpdates contains the list of updates that may be - recommended for this cluster if it meets specific required - conditions. Consumers interested in the set of updates that are - actually recommended for this cluster should use - availableUpdates. This list may be empty if no updates are - recommended, if the update service is unavailable, or if an empty - or invalid channel has been specified. - items: - description: |- - ConditionalUpdate represents an update which is recommended to some - clusters on the version the current cluster is reconciling, but which - may not be recommended for the current cluster. - properties: - conditions: - description: |- - conditions represents the observations of the conditional update's - current status. Known types are: - * Recommended, for whether the update is recommended for the current cluster. - items: - description: "Condition contains details for one aspect - of the current state of this API Resource.\n---\nThis - struct is intended for direct use as an array at the - field path .status.conditions. For example,\n\n\n\ttype - FooStatus struct{\n\t // Represents the observations - of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t - \ // +patchMergeKey=type\n\t // +patchStrategy=merge\n\t - \ // +listType=map\n\t // +listMapKey=type\n\t - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, - False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - release: - description: release is the target of the update. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - risks: - description: |- - risks represents the range of issues associated with - updating to the target release. The cluster-version - operator will evaluate all entries, and only recommend the - update if there is at least one entry and all entries - recommend the update. - items: - description: |- - ConditionalUpdateRisk represents a reason and cluster-state - for not recommending a conditional update. - properties: - matchingRules: - description: |- - matchingRules is a slice of conditions for deciding which - clusters match the risk and which do not. The slice is - ordered by decreasing precedence. The cluster-version - operator will walk the slice in order, and stop after the - first it can successfully evaluate. If no condition can be - successfully evaluated, the update will not be recommended. - items: - description: |- - ClusterCondition is a union of typed cluster conditions. The 'type' - property determines which of the type-specific properties are relevant. - When evaluated on a cluster, the condition may match, not match, or - fail to evaluate. - properties: - promql: - description: promQL represents a cluster condition - based on PromQL. - properties: - promql: - description: |- - PromQL is a PromQL query classifying clusters. This query - query should return a 1 in the match case and a 0 in the - does-not-match case. Queries which return no time - series, or which return values besides 0 or 1, are - evaluation failures. - type: string - required: - - promql - type: object - type: - description: |- - type represents the cluster-condition type. This defines - the members and semantics of any additional properties. - enum: - - Always - - PromQL - type: string - required: - - type - type: object - minItems: 1 - type: array - x-kubernetes-list-type: atomic - message: - description: |- - message provides additional information about the risk of - updating, in the event that matchingRules match the cluster - state. This is only to be consumed by humans. It may - contain Line Feed characters (U+000A), which should be - rendered as new lines. - minLength: 1 - type: string - name: - description: |- - name is the CamelCase reason for not recommending a - conditional update, in the event that matchingRules match the - cluster state. - minLength: 1 - type: string - url: - description: url contains information about this risk. - format: uri - minLength: 1 - type: string - required: - - matchingRules - - message - - name - - url - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - release - - risks - type: object - type: array - x-kubernetes-list-type: atomic - desired: - description: |- - desired is the version that the cluster is reconciling towards. - If the cluster is not yet fully initialized desired will be set - with the information available, which may be an image or a tag. - properties: - channels: - description: |- - channels is the set of Cincinnati channels to which the release - currently belongs. - items: - type: string - type: array - x-kubernetes-list-type: set - image: - description: |- - image is a container image location that contains the update. When this - field is part of spec, image is optional if version is specified and the - availableUpdates field contains a matching version. - type: string - url: - description: |- - url contains information about this release. This URL is set by - the 'url' metadata property on a release or the metadata returned by - the update API and should be displayed as a link in user - interfaces. The URL field may not be set for test or nightly - releases. - type: string - version: - description: |- - version is a semantic version identifying the update version. When this - field is part of spec, version is optional if image is specified. - type: string - type: object - history: - description: |- - history contains a list of the most recent versions applied to the cluster. - This value may be empty during cluster startup, and then will be updated - when a new update is being applied. The newest update is first in the - list and it is ordered by recency. Updates in the history have state - Completed if the rollout completed - if an update was failing or halfway - applied the state will be Partial. Only a limited amount of update history - is preserved. - items: - description: UpdateHistory is a single attempted update to the - cluster. - properties: - acceptedRisks: - description: |- - acceptedRisks records risks which were accepted to initiate the update. - For example, it may menition an Upgradeable=False or missing signature - that was overriden via desiredUpdate.force, or an update that was - initiated despite not being in the availableUpdates set of recommended - update targets. - type: string - completionTime: - description: |- - completionTime, if set, is when the update was fully applied. The update - that is currently being applied will have a null completion time. - Completion time will always be set for entries that are not the current - update (usually to the started time of the next update). - format: date-time - nullable: true - type: string - image: - description: |- - image is a container image location that contains the update. This value - is always populated. - type: string - startedTime: - description: startedTime is the time at which the update - was started. - format: date-time - type: string - state: - description: |- - state reflects whether the update was fully applied. The Partial state - indicates the update is not fully applied, while the Completed state - indicates the update was successfully rolled out at least once (all - parts of the update successfully applied). - type: string - verified: - description: |- - verified indicates whether the provided update was properly verified - before it was installed. If this is false the cluster may not be trusted. - Verified does not cover upgradeable checks that depend on the cluster - state at the time when the update target was accepted. - type: boolean - version: - description: |- - version is a semantic version identifying the update version. If the - requested image does not define a version, or if a failure occurs - retrieving the image, this value may be empty. - type: string - required: - - completionTime - - image - - startedTime - - state - - verified - type: object - type: array - observedGeneration: - description: |- - observedGeneration reports which version of the spec is being synced. - If this value is not equal to metadata.generation, then the desired - and conditions fields may represent a previous version. - format: int64 - type: integer - required: - - availableUpdates - - desired - - observedGeneration - type: object - required: - - initialized - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 19bdf9a03..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,238 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: ibmpowervsclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: IBMPowerVSCluster - listKind: IBMPowerVSClusterList - plural: ibmpowervsclusters - singular: ibmpowervscluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this IBMPowerVSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Time duration since creation of IBMPowerVSCluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .spec.serviceInstanceID - name: PowerVS Cloud Instance ID - priority: 1 - type: string - - description: Control Plane Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint - priority: 1 - type: string - - description: Control Plane Port - jsonPath: .spec.controlPlaneEndpoint.port - name: Port - priority: 1 - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMPowerVSCluster is the Schema for the ibmpowervsclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSClusterSpec defines the desired state of IBMPowerVSCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - network: - description: Network is the reference to the Network to use for this - cluster. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the vsi instance will get deployed. - minLength: 1 - type: string - required: - - network - - serviceInstanceID - type: object - status: - description: IBMPowerVSClusterStatus defines the observed state of IBMPowerVSCluster. - properties: - ready: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file - type: boolean - required: - - ready - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster to which this IBMPowerVSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Time duration since creation of IBMPowerVSCluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .spec.serviceInstanceID - name: PowerVS Cloud Instance ID - priority: 1 - type: string - - description: Control Plane Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint - priority: 1 - type: string - - description: Control Plane Port - jsonPath: .spec.controlPlaneEndpoint.port - name: Port - priority: 1 - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMPowerVSCluster is the Schema for the ibmpowervsclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSClusterSpec defines the desired state of IBMPowerVSCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - network: - description: Network is the reference to the Network to use for this - cluster. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the vsi instance will get deployed. - minLength: 1 - type: string - required: - - network - - serviceInstanceID - type: object - status: - description: IBMPowerVSClusterStatus defines the observed state of IBMPowerVSCluster. - properties: - ready: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file - type: boolean - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 430ee87ea..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,260 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IBMPowerVSClusterTemplate - listKind: IBMPowerVSClusterTemplateList - plural: ibmpowervsclustertemplates - shortNames: - - ibmpowervsct - singular: ibmpowervsclustertemplate - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of IBMPowerVSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMPowerVSClusterTemplate is the schema for IBM Power VS Kubernetes - Cluster Templates. - 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: IBMPowerVSClusterTemplateSpec defines the desired state of - IBMPowerVSClusterTemplate. - properties: - template: - description: IBMPowerVSClusterTemplateResource describes the data - needed to create an IBMPowerVSCluster from a template. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: IBMPowerVSClusterSpec defines the desired state of - IBMPowerVSCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - network: - description: Network is the reference to the Network to use - for this cluster. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud - instance where the vsi instance will get deployed. - minLength: 1 - type: string - required: - - network - - serviceInstanceID - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: false - subresources: {} - - additionalPrinterColumns: - - description: Time duration since creation of IBMPowerVSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMPowerVSClusterTemplate is the schema for IBM Power VS Kubernetes - Cluster Templates. - 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: IBMPowerVSClusterTemplateSpec defines the desired state of - IBMPowerVSClusterTemplate. - properties: - template: - description: IBMPowerVSClusterTemplateResource describes the data - needed to create an IBMPowerVSCluster from a template. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: IBMPowerVSClusterSpec defines the desired state of - IBMPowerVSCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - network: - description: Network is the reference to the Network to use - for this cluster. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud - instance where the vsi instance will get deployed. - minLength: 1 - type: string - required: - - network - - serviceInstanceID - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsimages.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsimages.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 5c7e16fe3..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsimages.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,306 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: ibmpowervsimages.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: IBMPowerVSImage - listKind: IBMPowerVSImageList - plural: ibmpowervsimages - singular: ibmpowervsimage - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: PowerVS image state - jsonPath: .status.imageState - name: State - type: string - - description: Image is ready for IBM PowerVS instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMPowerVSImage is the Schema for the ibmpowervsimages API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSImageSpec defines the desired state of IBMPowerVSImage. - properties: - bucket: - description: Cloud Object Storage bucket name; bucket-name[/optional/folder] - type: string - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - deletePolicy: - default: delete - description: DeletePolicy defines the policy used to identify images - to be preserved beyond the lifecycle of associated cluster. - enum: - - delete - - retain - type: string - object: - description: Cloud Object Storage image filename. - type: string - region: - description: Cloud Object Storage region. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the image will get imported. - type: string - storageType: - default: tier1 - description: Type of storage, storage pool with the most available - space will be selected. - enum: - - tier1 - - tier3 - type: string - required: - - bucket - - clusterName - - object - - region - - serviceInstanceID - type: object - status: - description: IBMPowerVSImageStatus defines the observed state of IBMPowerVSImage. - properties: - conditions: - description: Conditions defines current service state of the IBMPowerVSImage. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - imageID: - description: ImageID is the id of the imported image. - type: string - imageState: - description: ImageState is the status of the imported image. - type: string - jobID: - description: JobID is the job ID of an import operation. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: PowerVS image state - jsonPath: .status.imageState - name: State - type: string - - description: Image is ready for IBM PowerVS instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMPowerVSImage is the Schema for the ibmpowervsimages API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSImageSpec defines the desired state of IBMPowerVSImage. - properties: - bucket: - description: Cloud Object Storage bucket name; bucket-name[/optional/folder] - type: string - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - deletePolicy: - default: delete - description: DeletePolicy defines the policy used to identify images - to be preserved beyond the lifecycle of associated cluster. - enum: - - delete - - retain - type: string - object: - description: Cloud Object Storage image filename. - type: string - region: - description: Cloud Object Storage region. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the image will get imported. - type: string - storageType: - default: tier1 - description: Type of storage, storage pool with the most available - space will be selected. - enum: - - tier1 - - tier3 - type: string - required: - - bucket - - clusterName - - object - - region - - serviceInstanceID - type: object - status: - description: IBMPowerVSImageStatus defines the observed state of IBMPowerVSImage. - properties: - conditions: - description: Conditions defines current service state of the IBMPowerVSImage. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - imageID: - description: ImageID is the id of the imported image. - type: string - imageState: - description: ImageState is the status of the imported image. - type: string - jobID: - description: JobID is the job ID of an import operation. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 514f33b95..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,635 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: ibmpowervsmachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: IBMPowerVSMachine - listKind: IBMPowerVSMachineList - plural: ibmpowervsmachines - singular: ibmpowervsmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this IBMPowerVSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Machine object to which this IBMPowerVSMachine belongs - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - priority: 1 - type: string - - description: Time duration since creation of IBMPowerVSMachine - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Cluster infrastructure is ready for IBM PowerVS instances - jsonPath: .status.ready - name: Ready - type: string - - description: Instance Internal Addresses - jsonPath: .status.addresses[?(@.type=="InternalIP")].address - name: Internal-IP - priority: 1 - type: string - - description: Instance External Addresses - jsonPath: .status.addresses[?(@.type=="ExternalIP")].address - name: External-IP - priority: 1 - type: string - - description: PowerVS instance state - jsonPath: .status.instanceState - name: State - type: string - - description: PowerVS instance health - jsonPath: .status.health - name: Health - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMPowerVSMachine is the Schema for the ibmpowervsmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSMachineSpec defines the desired state of IBMPowerVSMachine. - properties: - image: - description: Image is the reference to the Image from which to create - the machine instance. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - imageRef: - description: |- - ImageRef is an optional reference to a provider-specific resource that holds - the details for provisioning the Image for a Cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - memory: - description: Memory is Amount of memory allocated (in GB) - type: string - network: - description: Network is the reference to the Network to use for this - instance. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - procType: - description: 'ProcType is the processor type, e.g: dedicated, shared, - capped' - type: string - processors: - description: Processors is Number of processors allocated. - pattern: ^\d+(\.)?(\d)?(\d)?$ - type: string - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the vsi instance will get deployed. - minLength: 1 - type: string - sshKey: - description: SSHKey is the name of the SSH key pair provided to the - vsi for authenticating users. - type: string - sysType: - description: SysType is the System type used to host the vsi. - type: string - required: - - network - - serviceInstanceID - type: object - status: - description: IBMPowerVSMachineStatus defines the observed state of IBMPowerVSMachine. - properties: - addresses: - description: Addresses contains the vsi associated addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the IBMPowerVSMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - fault: - description: Fault will report if any fault messages for the vsi. - type: string - health: - description: Health is the health of the vsi. - type: string - instanceID: - type: string - instanceState: - description: InstanceState is the status of the vsi. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - region: - description: Region specifies the Power VS Service instance region. - type: string - zone: - description: Zone specifies the Power VS Service instance zone. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster to which this IBMPowerVSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Machine object to which this IBMPowerVSMachine belongs - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - priority: 1 - type: string - - description: Time duration since creation of IBMPowerVSMachine - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Cluster infrastructure is ready for IBM PowerVS instances - jsonPath: .status.ready - name: Ready - type: string - - description: Instance Internal Addresses - jsonPath: .status.addresses[?(@.type=="InternalIP")].address - name: Internal-IP - priority: 1 - type: string - - description: Instance External Addresses - jsonPath: .status.addresses[?(@.type=="ExternalIP")].address - name: External-IP - priority: 1 - type: string - - description: PowerVS instance state - jsonPath: .status.instanceState - name: State - type: string - - description: PowerVS instance health - jsonPath: .status.health - name: Health - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMPowerVSMachine is the Schema for the ibmpowervsmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSMachineSpec defines the desired state of IBMPowerVSMachine. - properties: - image: - description: |- - Image the reference to the image which is used to create the instance. - supported image identifier in IBMPowerVSResourceReference are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - imageRef: - description: |- - ImageRef is an optional reference to a provider-specific resource that holds - the details for provisioning the Image for a Cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - memoryGiB: - description: |- - memoryGiB is the size of a virtual machine's memory, in GiB. - maximum value for the MemoryGiB depends on the selected SystemType. - when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. - when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. - when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. - The minimum memory is 2 GiB. - When omitted, this means the user has no opinion and the platform is left to choose a reasonable - default, which is subject to change over time. The current default is 2. - format: int32 - type: integer - network: - description: |- - Network is the reference to the Network to use for this instance. - supported network identifier in IBMPowerVSResourceReference are Name, ID and RegEx and that can be obtained from IBM Cloud UI or IBM Cloud cli. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - processorType: - description: |- - processorType is the VM instance processor type. - It must be set to one of the following values: Dedicated, Capped or Shared. - Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. - Shared: Shared among other clients. - Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. - if the processorType is selected as Dedicated, then processors value cannot be fractional. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The current default is Shared. - enum: - - Dedicated - - Shared - - Capped - - "" - type: string - processors: - anyOf: - - type: integer - - type: string - description: |- - processors is the number of virtual processors in a virtual machine. - when the processorType is selected as Dedicated the processors value cannot be fractional. - maximum value for the Processors depends on the selected SystemType. - when SystemType is set to e880 or e980 maximum Processors value is 143. - when SystemType is set to s922 maximum Processors value is 15. - minimum value for Processors depends on the selected ProcessorType. - when ProcessorType is set as Shared or Capped, The minimum processors is 0.25. - when ProcessorType is set as Dedicated, The minimum processors is 1. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The default is set based on the selected ProcessorType. - when ProcessorType selected as Dedicated, the default is set to 1. - when ProcessorType selected as Shared or Capped, the default is set to 0.25. - x-kubernetes-int-or-string: true - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud instance - where the vsi instance will get deployed. - minLength: 1 - type: string - sshKey: - description: SSHKey is the name of the SSH key pair provided to the - vsi for authenticating users. - type: string - systemType: - description: |- - systemType is the System type used to host the instance. - systemType determines the number of cores and memory that is available. - Few of the supported SystemTypes are s922,e880,e980. - e880 systemType available only in Dallas Datacenters. - e980 systemType available in Datacenters except Dallas and Washington. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The current default is s922 which is generally available. - enum: - - s922 - - e880 - - e980 - - "" - type: string - required: - - network - - serviceInstanceID - type: object - status: - description: IBMPowerVSMachineStatus defines the observed state of IBMPowerVSMachine. - properties: - addresses: - description: Addresses contains the vsi associated addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the IBMPowerVSMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - fault: - description: Fault will report if any fault messages for the vsi. - type: string - health: - description: Health is the health of the vsi. - type: string - instanceID: - type: string - instanceState: - description: InstanceState is the status of the vsi. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - region: - description: Region specifies the Power VS Service instance region. - type: string - zone: - description: Zone specifies the Power VS Service instance zone. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 38104ed47..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,373 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: IBMPowerVSMachineTemplate - listKind: IBMPowerVSMachineTemplateList - plural: ibmpowervsmachinetemplates - singular: ibmpowervsmachinetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMPowerVSMachineTemplate is the Schema for the ibmpowervsmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSMachineTemplateSpec defines the desired state of - IBMPowerVSMachineTemplate. - properties: - template: - description: IBMPowerVSMachineTemplateResource holds the IBMPowerVSMachine - spec. - properties: - spec: - description: IBMPowerVSMachineSpec defines the desired state of - IBMPowerVSMachine. - properties: - image: - description: Image is the reference to the Image from which - to create the machine instance. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - imageRef: - description: |- - ImageRef is an optional reference to a provider-specific resource that holds - the details for provisioning the Image for a Cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - memory: - description: Memory is Amount of memory allocated (in GB) - type: string - network: - description: Network is the reference to the Network to use - for this instance. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - procType: - description: 'ProcType is the processor type, e.g: dedicated, - shared, capped' - type: string - processors: - description: Processors is Number of processors allocated. - pattern: ^\d+(\.)?(\d)?(\d)?$ - type: string - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud - instance where the vsi instance will get deployed. - minLength: 1 - type: string - sshKey: - description: SSHKey is the name of the SSH key pair provided - to the vsi for authenticating users. - type: string - sysType: - description: SysType is the System type used to host the vsi. - type: string - required: - - network - - serviceInstanceID - type: object - required: - - spec - type: object - required: - - template - type: object - status: - description: IBMPowerVSMachineTemplateStatus defines the observed state - of IBMPowerVSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined in: - https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md - type: object - type: object - type: object - served: true - storage: false - subresources: - status: {} - - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMPowerVSMachineTemplate is the Schema for the ibmpowervsmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMPowerVSMachineTemplateSpec defines the desired state of - IBMPowerVSMachineTemplate. - properties: - template: - description: IBMPowerVSMachineTemplateResource holds the IBMPowerVSMachine - spec. - properties: - spec: - description: IBMPowerVSMachineSpec defines the desired state of - IBMPowerVSMachine. - properties: - image: - description: |- - Image the reference to the image which is used to create the instance. - supported image identifier in IBMPowerVSResourceReference are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - imageRef: - description: |- - ImageRef is an optional reference to a provider-specific resource that holds - the details for provisioning the Image for a Cluster. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - memoryGiB: - description: |- - memoryGiB is the size of a virtual machine's memory, in GiB. - maximum value for the MemoryGiB depends on the selected SystemType. - when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. - when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. - when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. - The minimum memory is 2 GiB. - When omitted, this means the user has no opinion and the platform is left to choose a reasonable - default, which is subject to change over time. The current default is 2. - format: int32 - type: integer - network: - description: |- - Network is the reference to the Network to use for this instance. - supported network identifier in IBMPowerVSResourceReference are Name, ID and RegEx and that can be obtained from IBM Cloud UI or IBM Cloud cli. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - regex: - description: |- - Regular expression to match resource, - In case of multiple resources matches the provided regular expression the first matched resource will be selected - minLength: 1 - type: string - type: object - processorType: - description: |- - processorType is the VM instance processor type. - It must be set to one of the following values: Dedicated, Capped or Shared. - Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. - Shared: Shared among other clients. - Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. - if the processorType is selected as Dedicated, then processors value cannot be fractional. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The current default is Shared. - enum: - - Dedicated - - Shared - - Capped - - "" - type: string - processors: - anyOf: - - type: integer - - type: string - description: |- - processors is the number of virtual processors in a virtual machine. - when the processorType is selected as Dedicated the processors value cannot be fractional. - maximum value for the Processors depends on the selected SystemType. - when SystemType is set to e880 or e980 maximum Processors value is 143. - when SystemType is set to s922 maximum Processors value is 15. - minimum value for Processors depends on the selected ProcessorType. - when ProcessorType is set as Shared or Capped, The minimum processors is 0.25. - when ProcessorType is set as Dedicated, The minimum processors is 1. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The default is set based on the selected ProcessorType. - when ProcessorType selected as Dedicated, the default is set to 1. - when ProcessorType selected as Shared or Capped, the default is set to 0.25. - x-kubernetes-int-or-string: true - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - serviceInstanceID: - description: ServiceInstanceID is the id of the power cloud - instance where the vsi instance will get deployed. - minLength: 1 - type: string - sshKey: - description: SSHKey is the name of the SSH key pair provided - to the vsi for authenticating users. - type: string - systemType: - description: |- - systemType is the System type used to host the instance. - systemType determines the number of cores and memory that is available. - Few of the supported SystemTypes are s922,e880,e980. - e880 systemType available only in Dallas Datacenters. - e980 systemType available in Datacenters except Dallas and Washington. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default, which is subject to change over time. The current default is s922 which is generally available. - enum: - - s922 - - e880 - - e980 - - "" - type: string - required: - - network - - serviceInstanceID - type: object - required: - - spec - type: object - required: - - template - type: object - status: - description: IBMPowerVSMachineTemplateStatus defines the observed state - of IBMPowerVSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined in: - https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 7f99dd7e8..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,390 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta2 - name: ibmvpcclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IBMVPCCluster - listKind: IBMVPCClusterList - plural: ibmvpcclusters - singular: ibmvpccluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this IBMVPCCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for IBM VPC instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMVPCCluster is the Schema for the ibmvpcclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCClusterSpec defines the desired state of IBMVPCCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. - properties: - name: - description: Name sets the name of the VPC load balancer. - maxLength: 63 - pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ - type: string - type: object - region: - description: The IBM Cloud Region the cluster lives in. - type: string - resourceGroup: - description: The VPC resources should be created under the resource - group. - type: string - vpc: - description: The Name of VPC. - type: string - zone: - description: The Name of availability zone. - type: string - required: - - region - - resourceGroup - type: object - status: - description: IBMVPCClusterStatus defines the observed state of IBMVPCCluster. - properties: - conditions: - description: Conditions defines current service state of the load - balancer. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - controlPlaneLoadBalancerState: - description: ControlPlaneLoadBalancerState is the status of the load - balancer. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - subnet: - description: Subnet describes a subnet. - properties: - cidr: - type: string - id: - type: string - name: - type: string - zone: - type: string - required: - - cidr - - id - - name - - zone - type: object - vpc: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file - properties: - id: - type: string - name: - type: string - required: - - id - - name - type: object - vpcEndpoint: - description: VPCEndpoint describes a VPCEndpoint. - properties: - address: - type: string - floatingIPID: - description: 'Deprecated: This field has no function and is going - to be removed in the next release.' - type: string - loadBalancerIPID: - type: string - required: - - address - type: object - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster to which this IBMVPCCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for IBM VPC instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMVPCCluster is the Schema for the ibmvpcclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCClusterSpec defines the desired state of IBMVPCCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. - properties: - name: - description: Name sets the name of the VPC load balancer. - maxLength: 63 - pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ - type: string - type: object - region: - description: The IBM Cloud Region the cluster lives in. - type: string - resourceGroup: - description: The VPC resources should be created under the resource - group. - type: string - vpc: - description: The Name of VPC. - type: string - zone: - description: The Name of availability zone. - type: string - required: - - region - - resourceGroup - type: object - status: - description: IBMVPCClusterStatus defines the observed state of IBMVPCCluster. - properties: - conditions: - description: Conditions defines current service state of the load - balancer. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - controlPlaneLoadBalancerState: - description: ControlPlaneLoadBalancerState is the status of the load - balancer. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - subnet: - description: Subnet describes a subnet. - properties: - cidr: - type: string - id: - type: string - name: - type: string - zone: - type: string - required: - - cidr - - id - - name - - zone - type: object - vpc: - description: |- - INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - Important: Run "make" to regenerate code after modifying this file - properties: - id: - type: string - name: - type: string - required: - - id - - name - type: object - vpcEndpoint: - description: VPCEndpoint describes a VPCEndpoint. - properties: - address: - type: string - floatingIPID: - description: 'Deprecated: This field has no function and is going - to be removed in the next release.' - type: string - loadBalancerIPID: - type: string - required: - - address - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 52983a408..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,138 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ibmvpcclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IBMVPCClusterTemplate - listKind: IBMVPCClusterTemplateList - plural: ibmvpcclustertemplates - shortNames: - - ibmvpcct - singular: ibmvpcclustertemplate - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Time duration since creation of IBMVPCClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMVPCClusterTemplate is the Schema for the ibmvpcclustertemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCClusterTemplateSpec defines the desired state of IBMVPCClusterTemplate. - properties: - template: - description: IBMVPCClusterTemplateResource describes the data needed - to create an IBMVPCCluster from a template. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: IBMVPCClusterSpec defines the desired state of IBMVPCCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. - properties: - name: - description: Name sets the name of the VPC load balancer. - maxLength: 63 - pattern: ^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$ - type: string - type: object - region: - description: The IBM Cloud Region the cluster lives in. - type: string - resourceGroup: - description: The VPC resources should be created under the - resource group. - type: string - vpc: - description: The Name of VPC. - type: string - zone: - description: The Name of availability zone. - type: string - required: - - region - - resourceGroup - type: object - required: - - spec - type: object - type: object - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 00736bf49..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,360 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ibmvpcmachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IBMVPCMachine - listKind: IBMVPCMachineList - plural: ibmvpcmachines - singular: ibmvpcmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster infrastructure is ready for IBM VPC instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMVPCMachine is the Schema for the ibmvpcmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCMachineSpec defines the desired state of IBMVPCMachine. - properties: - bootVolume: - description: BootVolume contains machines's boot volume configurations - like size, iops etc.. - properties: - deleteVolumeOnInstanceDelete: - default: true - description: |- - DeleteVolumeOnInstanceDelete If set to true, when deleting the instance the volume will also be deleted. - Default is set as true - type: boolean - encryptionKeyCRN: - description: |- - EncryptionKey is the root key to use to wrap the data encryption key for the volume and this points to the CRN - and possible values are as follows. - The CRN of the [Key Protect Root - Key](https://cloud.ibm.com/docs/key-protect?topic=key-protect-getting-started-tutorial) or [Hyper Protect Crypto - Service Root Key](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-get-started) for this resource. - If unspecified, the `encryption` type for the volume will be `provider_managed`. - type: string - iops: - description: |- - Iops is the maximum I/O operations per second (IOPS) to use for the volume. Applicable only to volumes using a profile - family of `custom`. - format: int64 - type: integer - name: - description: |- - Name is the unique user-defined name for this volume. - Default will be autogenerated - type: string - profile: - default: general-purpose - description: |- - Profile is the volume profile for the bootdisk, refer https://cloud.ibm.com/docs/vpc?topic=vpc-block-storage-profiles - for more information. - Default to general-purpose - enum: - - general-purpose - - 5iops-tier - - 10iops-tier - - custom - type: string - sizeGiB: - description: |- - SizeGiB is the size of the virtual server's boot disk in GiB. - Default to the size of the image's `minimum_provisioned_size`. - format: int64 - type: integer - type: object - image: - description: |- - Image is the id of OS image which would be install on the instance. - Example: r134-ed3f775f-ad7e-4e37-ae62-7199b4988b00 - type: string - imageName: - description: ImageName is the name of OS image which would be install - on the instance. - type: string - name: - description: Name of the instance. - type: string - primaryNetworkInterface: - description: PrimaryNetworkInterface is required to specify subnet. - properties: - subnet: - description: Subnet ID of the network interface. - type: string - type: object - profile: - description: "Profile indicates the flavor of instance. Example: bx2-8x32\tmeans - 8 vCPUs\t32 GB RAM\t16 Gbps\nTODO: add a reference link of profile" - type: string - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - sshKeyNames: - description: SSHKeysNames is the SSH pub key names that will be used - to access VM. - items: - type: string - type: array - sshKeys: - description: SSHKeys is the SSH pub keys that will be used to access - VM. - items: - type: string - type: array - zone: - description: |- - Zone is the place where the instance should be created. Example: us-south-3 - TODO: Actually zone is transparent to user. The field user can access is location. Example: Dallas 2 - type: string - required: - - zone - type: object - status: - description: IBMVPCMachineStatus defines the observed state of IBMVPCMachine. - properties: - addresses: - description: Addresses contains the GCP instance associated addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - instanceID: - type: string - instanceState: - description: InstanceStatus is the status of the GCP instance for - this machine. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Cluster infrastructure is ready for IBM VPC instances - jsonPath: .status.ready - name: Ready - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMVPCMachine is the Schema for the ibmvpcmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCMachineSpec defines the desired state of IBMVPCMachine. - properties: - bootVolume: - description: BootVolume contains machines's boot volume configurations - like size, iops etc.. - properties: - deleteVolumeOnInstanceDelete: - default: true - description: |- - DeleteVolumeOnInstanceDelete If set to true, when deleting the instance the volume will also be deleted. - Default is set as true - type: boolean - encryptionKeyCRN: - description: |- - EncryptionKey is the root key to use to wrap the data encryption key for the volume and this points to the CRN - and possible values are as follows. - The CRN of the [Key Protect Root - Key](https://cloud.ibm.com/docs/key-protect?topic=key-protect-getting-started-tutorial) or [Hyper Protect Crypto - Service Root Key](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-get-started) for this resource. - If unspecified, the `encryption` type for the volume will be `provider_managed`. - type: string - iops: - description: |- - Iops is the maximum I/O operations per second (IOPS) to use for the volume. Applicable only to volumes using a profile - family of `custom`. - format: int64 - type: integer - name: - description: |- - Name is the unique user-defined name for this volume. - Default will be autogenerated - type: string - profile: - default: general-purpose - description: |- - Profile is the volume profile for the bootdisk, refer https://cloud.ibm.com/docs/vpc?topic=vpc-block-storage-profiles - for more information. - Default to general-purpose - enum: - - general-purpose - - 5iops-tier - - 10iops-tier - - custom - type: string - sizeGiB: - description: |- - SizeGiB is the size of the virtual server's boot disk in GiB. - Default to the size of the image's `minimum_provisioned_size`. - format: int64 - type: integer - type: object - image: - description: |- - Image is the OS image which would be install on the instance. - ID will take higher precedence over Name if both specified. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - type: object - name: - description: Name of the instance. - type: string - primaryNetworkInterface: - description: PrimaryNetworkInterface is required to specify subnet. - properties: - subnet: - description: Subnet ID of the network interface. - type: string - type: object - profile: - description: "Profile indicates the flavor of instance. Example: bx2-8x32\tmeans - 8 vCPUs\t32 GB RAM\t16 Gbps\nTODO: add a reference link of profile" - type: string - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - sshKeys: - description: |- - SSHKeys is the SSH pub keys that will be used to access VM. - ID will take higher precedence over Name if both specified. - items: - description: |- - IBMVPCResourceReference is a reference to a specific VPC resource by ID or Name - Only one of ID or Name may be specified. Specifying more than one will result in - a validation error. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - type: object - type: array - zone: - description: |- - Zone is the place where the instance should be created. Example: us-south-3 - TODO: Actually zone is transparent to user. The field user can access is location. Example: Dallas 2 - type: string - required: - - image - - zone - type: object - status: - description: IBMVPCMachineStatus defines the observed state of IBMVPCMachine. - properties: - addresses: - description: Addresses contains the GCP instance associated addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - instanceID: - type: string - instanceState: - description: InstanceStatus is the status of the GCP instance for - this machine. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index bc451bc25..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ibmvpcmachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,320 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ibmvpcmachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IBMVPCMachineTemplate - listKind: IBMVPCMachineTemplateList - plural: ibmvpcmachinetemplates - singular: ibmvpcmachinetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: IBMVPCMachineTemplate is the Schema for the ibmvpcmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCMachineTemplateSpec defines the desired state of IBMVPCMachineTemplate. - properties: - template: - description: IBMVPCMachineTemplateResource describes the data needed - to create am IBMVPCMachine from a template. - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - bootVolume: - description: BootVolume contains machines's boot volume configurations - like size, iops etc.. - properties: - deleteVolumeOnInstanceDelete: - default: true - description: |- - DeleteVolumeOnInstanceDelete If set to true, when deleting the instance the volume will also be deleted. - Default is set as true - type: boolean - encryptionKeyCRN: - description: |- - EncryptionKey is the root key to use to wrap the data encryption key for the volume and this points to the CRN - and possible values are as follows. - The CRN of the [Key Protect Root - Key](https://cloud.ibm.com/docs/key-protect?topic=key-protect-getting-started-tutorial) or [Hyper Protect Crypto - Service Root Key](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-get-started) for this resource. - If unspecified, the `encryption` type for the volume will be `provider_managed`. - type: string - iops: - description: |- - Iops is the maximum I/O operations per second (IOPS) to use for the volume. Applicable only to volumes using a profile - family of `custom`. - format: int64 - type: integer - name: - description: |- - Name is the unique user-defined name for this volume. - Default will be autogenerated - type: string - profile: - default: general-purpose - description: |- - Profile is the volume profile for the bootdisk, refer https://cloud.ibm.com/docs/vpc?topic=vpc-block-storage-profiles - for more information. - Default to general-purpose - enum: - - general-purpose - - 5iops-tier - - 10iops-tier - - custom - type: string - sizeGiB: - description: |- - SizeGiB is the size of the virtual server's boot disk in GiB. - Default to the size of the image's `minimum_provisioned_size`. - format: int64 - type: integer - type: object - image: - description: |- - Image is the id of OS image which would be install on the instance. - Example: r134-ed3f775f-ad7e-4e37-ae62-7199b4988b00 - type: string - imageName: - description: ImageName is the name of OS image which would - be install on the instance. - type: string - name: - description: Name of the instance. - type: string - primaryNetworkInterface: - description: PrimaryNetworkInterface is required to specify - subnet. - properties: - subnet: - description: Subnet ID of the network interface. - type: string - type: object - profile: - description: "Profile indicates the flavor of instance. Example: - bx2-8x32\tmeans 8 vCPUs\t32 GB RAM\t16 Gbps\nTODO: add a - reference link of profile" - type: string - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - sshKeyNames: - description: SSHKeysNames is the SSH pub key names that will - be used to access VM. - items: - type: string - type: array - sshKeys: - description: SSHKeys is the SSH pub keys that will be used - to access VM. - items: - type: string - type: array - zone: - description: |- - Zone is the place where the instance should be created. Example: us-south-3 - TODO: Actually zone is transparent to user. The field user can access is location. Example: Dallas 2 - type: string - required: - - zone - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: IBMVPCMachineTemplate is the Schema for the ibmvpcmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IBMVPCMachineTemplateSpec defines the desired state of IBMVPCMachineTemplate. - properties: - template: - description: IBMVPCMachineTemplateResource describes the data needed - to create am IBMVPCMachine from a template. - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - bootVolume: - description: BootVolume contains machines's boot volume configurations - like size, iops etc.. - properties: - deleteVolumeOnInstanceDelete: - default: true - description: |- - DeleteVolumeOnInstanceDelete If set to true, when deleting the instance the volume will also be deleted. - Default is set as true - type: boolean - encryptionKeyCRN: - description: |- - EncryptionKey is the root key to use to wrap the data encryption key for the volume and this points to the CRN - and possible values are as follows. - The CRN of the [Key Protect Root - Key](https://cloud.ibm.com/docs/key-protect?topic=key-protect-getting-started-tutorial) or [Hyper Protect Crypto - Service Root Key](https://cloud.ibm.com/docs/hs-crypto?topic=hs-crypto-get-started) for this resource. - If unspecified, the `encryption` type for the volume will be `provider_managed`. - type: string - iops: - description: |- - Iops is the maximum I/O operations per second (IOPS) to use for the volume. Applicable only to volumes using a profile - family of `custom`. - format: int64 - type: integer - name: - description: |- - Name is the unique user-defined name for this volume. - Default will be autogenerated - type: string - profile: - default: general-purpose - description: |- - Profile is the volume profile for the bootdisk, refer https://cloud.ibm.com/docs/vpc?topic=vpc-block-storage-profiles - for more information. - Default to general-purpose - enum: - - general-purpose - - 5iops-tier - - 10iops-tier - - custom - type: string - sizeGiB: - description: |- - SizeGiB is the size of the virtual server's boot disk in GiB. - Default to the size of the image's `minimum_provisioned_size`. - format: int64 - type: integer - type: object - image: - description: |- - Image is the OS image which would be install on the instance. - ID will take higher precedence over Name if both specified. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - type: object - name: - description: Name of the instance. - type: string - primaryNetworkInterface: - description: PrimaryNetworkInterface is required to specify - subnet. - properties: - subnet: - description: Subnet ID of the network interface. - type: string - type: object - profile: - description: "Profile indicates the flavor of instance. Example: - bx2-8x32\tmeans 8 vCPUs\t32 GB RAM\t16 Gbps\nTODO: add a - reference link of profile" - type: string - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - sshKeys: - description: |- - SSHKeys is the SSH pub keys that will be used to access VM. - ID will take higher precedence over Name if both specified. - items: - description: |- - IBMVPCResourceReference is a reference to a specific VPC resource by ID or Name - Only one of ID or Name may be specified. Specifying more than one will result in - a validation error. - properties: - id: - description: ID of resource - minLength: 1 - type: string - name: - description: Name of resource - minLength: 1 - type: string - type: object - type: array - zone: - description: |- - Zone is the place where the instance should be created. Example: us-south-3 - TODO: Actually zone is transparent to user. The field user can access is location. Example: Dallas 2 - type: string - required: - - image - - zone - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddressclaims.ipam.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddressclaims.ipam.cluster.x-k8s.io.yaml deleted file mode 100644 index e7750f0f2..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddressclaims.ipam.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,157 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ipaddressclaims.ipam.cluster.x-k8s.io -spec: - group: ipam.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IPAddressClaim - listKind: IPAddressClaimList - plural: ipaddressclaims - singular: ipaddressclaim - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Name of the pool to allocate an address from - jsonPath: .spec.poolRef.name - name: Pool Name - type: string - - description: Kind of the pool to allocate an address from - jsonPath: .spec.poolRef.kind - name: Pool Kind - type: string - - description: Time duration since creation of IPAdressClaim - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: IPAddressClaim is the Schema for the ipaddressclaim API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IPAddressClaimSpec is the desired state of an IPAddressClaim. - properties: - poolRef: - description: PoolRef is a reference to the pool from which an IP address - should be created. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - required: - - poolRef - type: object - status: - description: IPAddressClaimStatus is the observed status of a IPAddressClaim. - properties: - addressRef: - description: AddressRef is a reference to the address that was created - for this claim. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - description: Conditions summarises the current state of the IPAddressClaim - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddresses.ipam.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddresses.ipam.cluster.x-k8s.io.yaml deleted file mode 100644 index bd8814452..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-ipaddresses.ipam.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,124 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: ipaddresses.ipam.cluster.x-k8s.io -spec: - group: ipam.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: IPAddress - listKind: IPAddressList - plural: ipaddresses - singular: ipaddress - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Address - jsonPath: .spec.address - name: Address - type: string - - description: Name of the pool the address is from - jsonPath: .spec.poolRef.name - name: Pool Name - type: string - - description: Kind of the pool the address is from - jsonPath: .spec.poolRef.kind - name: Pool Kind - type: string - - description: Time duration since creation of IPAdress - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: IPAddress is the Schema for the ipaddress API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IPAddressSpec is the desired state of an IPAddress. - properties: - address: - description: Address is the IP address. - type: string - claimRef: - description: ClaimRef is a reference to the claim this IPAddress was - created for. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - gateway: - description: Gateway is the network gateway of the network the address - is from. - type: string - poolRef: - description: PoolRef is a reference to the pool that this IPAddress - was created from. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - prefix: - description: Prefix is the prefix of the address. - type: integer - required: - - address - - claimRef - - poolRef - - prefix - type: object - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 3f990fef6..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,277 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1alpha1 - name: kubevirtclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: KubevirtCluster - listKind: KubevirtClusterList - plural: kubevirtclusters - singular: kubevirtcluster - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: KubevirtCluster is the Schema for the kubevirtclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: KubevirtClusterSpec defines the desired state of KubevirtCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - properties: - host: - description: Host is the hostname on which the API server is serving. - type: string - port: - description: Port is the port on which the API server is serving. - type: integer - required: - - host - - port - type: object - controlPlaneServiceTemplate: - description: |- - ControlPlaneServiceTemplate can be used to modify service that fronts the control plane nodes to handle the - api-server traffic (port 6443). This field is optional, by default control plane nodes will use a service - of type ClusterIP, which will make workload cluster only accessible within the same cluster. Note, this does - not aim to expose the entire Service spec to users, but only provides capability to modify the service metadata - and the service type. - properties: - metadata: - description: |- - Service metadata allows to set labels, annotations and namespace for the service. - When infraClusterSecretRef is used, ControlPlaneService take the kubeconfig namespace by default if metadata.namespace is not specified. - This field is optional. - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: |- - Service specification allows to override some fields in the service spec. - Note, it does not aim cover all fields of the service spec. - properties: - type: - description: |- - Type determines how the Service is exposed. Defaults to ClusterIP. Valid - options are ExternalName, ClusterIP, NodePort, and LoadBalancer. - More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types - type: string - type: object - type: object - infraClusterSecretRef: - description: InfraClusterSecretRef is a reference to a secret with - a kubeconfig for external cluster used for infra. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - sshKeys: - description: SSHKeys is a reference to a local struct for SSH keys - persistence. - properties: - configRef: - description: |- - ConfigRef is a reference to a resource containing the keys. - The reference is optional to allow users/operators to specify - Bootstrap.DataSecretName without the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: DataSecretName is the name of the secret that stores - ssh keys. - type: string - type: object - type: object - status: - description: KubevirtClusterStatus defines the observed state of KubevirtCluster. - properties: - conditions: - description: Conditions defines current service state of the KubevirtCluster. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: |- - FailureDomains don't mean much in CAPD since it's all local, but we can see how the rest of cluster API - will use this if we populate it. - type: object - ready: - default: false - description: Ready denotes that the infrastructure is ready. - type: boolean - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 03ad77841..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,267 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: kubevirtclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: KubevirtClusterTemplate - listKind: KubevirtClusterTemplateList - plural: kubevirtclustertemplates - shortNames: - - kct - singular: kubevirtclustertemplate - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: KubevirtClusterTemplate is the Schema for the kubevirtclustertemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: KubevirtClusterTemplateSpec defines the desired state of - KubevirtClusterTemplate. - properties: - template: - description: KubevirtClusterTemplateResource describes the data needed - to create a KubevirtCluster from a template. - properties: - metadata: - description: |- - ObjectMeta is metadata that all persisted resources must have, which includes all objects - users must create. This is a copy of customizable fields from metav1.ObjectMeta. - - - ObjectMeta is embedded in `Machine.Spec`, `MachineDeployment.Template` and `MachineSet.Template`, - which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases - and read-only fields which end up in the generated CRD validation, having it as a subset simplifies - the API and some issues that can impact user experience. - - - During the [upgrade to controller-tools@v2](https://github.com/kubernetes-sigs/cluster-api/pull/1054) - for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, - specifically `spec.metadata.creationTimestamp in body must be of type string: "null"`. - The investigation showed that `controller-tools@v2` behaves differently than its previous version - when handling types from [metav1](k8s.io/apimachinery/pkg/apis/meta/v1) package. - - - In more details, we found that embedded (non-top level) types that embedded `metav1.ObjectMeta` - had validation properties, including for `creationTimestamp` (metav1.Time). - The `metav1.Time` type specifies a custom json marshaller that, when IsZero() is true, returns `null` - which breaks validation because the field isn't marked as nullable. - - - In future versions, controller-tools@v2 might allow overriding the type and validation for embedded - types. When that happens, this hack should be revisited. - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: KubevirtClusterSpec defines the desired state of - KubevirtCluster. - properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - properties: - host: - description: Host is the hostname on which the API server - is serving. - type: string - port: - description: Port is the port on which the API server - is serving. - type: integer - required: - - host - - port - type: object - controlPlaneServiceTemplate: - description: |- - ControlPlaneServiceTemplate can be used to modify service that fronts the control plane nodes to handle the - api-server traffic (port 6443). This field is optional, by default control plane nodes will use a service - of type ClusterIP, which will make workload cluster only accessible within the same cluster. Note, this does - not aim to expose the entire Service spec to users, but only provides capability to modify the service metadata - and the service type. - properties: - metadata: - description: |- - Service metadata allows to set labels, annotations and namespace for the service. - When infraClusterSecretRef is used, ControlPlaneService take the kubeconfig namespace by default if metadata.namespace is not specified. - This field is optional. - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: |- - Service specification allows to override some fields in the service spec. - Note, it does not aim cover all fields of the service spec. - properties: - type: - description: |- - Type determines how the Service is exposed. Defaults to ClusterIP. Valid - options are ExternalName, ClusterIP, NodePort, and LoadBalancer. - More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types - type: string - type: object - type: object - infraClusterSecretRef: - description: InfraClusterSecretRef is a reference to a secret - with a kubeconfig for external cluster used for infra. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - sshKeys: - description: SSHKeys is a reference to a local struct for - SSH keys persistence. - properties: - configRef: - description: |- - ConfigRef is a reference to a resource containing the keys. - The reference is optional to allow users/operators to specify - Bootstrap.DataSecretName without the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: DataSecretName is the name of the secret - that stores ssh keys. - type: string - type: object - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - x-kubernetes-validations: - - message: KubevirtClusterTemplate is immutable - rule: self == oldSelf - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index fcfdb8984..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,4485 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1alpha1 - name: kubevirtmachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: KubevirtMachine - listKind: KubevirtMachineList - plural: kubevirtmachines - singular: kubevirtmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Is machine ready - jsonPath: .status.ready - name: Ready - type: boolean - name: v1alpha1 - schema: - openAPIV3Schema: - description: KubevirtMachine is the Schema for the kubevirtmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: KubevirtMachineSpec defines the desired state of KubevirtMachine. - properties: - infraClusterSecretRef: - description: |- - InfraClusterSecretRef is a reference to a secret with a kubeconfig for external cluster used for infra. - When nil, this defaults to the value present in the KubevirtCluster object's spec associated with this machine. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - providerID: - description: ProviderID TBD what to use for Kubevirt - type: string - virtualMachineBootstrapCheck: - description: BootstrapCheckSpec defines how the CAPK controller is - checking CAPI Sentinel file inside the VM. - properties: - checkStrategy: - default: ssh - description: |- - CheckStrategy describes how CAPK controller will validate a successful CAPI bootstrap. - Following specified method, CAPK will try to retrieve the state of the CAPI Sentinel file from the VM. - Possible values are: "none" or "ssh" (default is "ssh") and this value is validated by apiserver. - enum: - - none - - ssh - type: string - type: object - virtualMachineTemplate: - description: VirtualMachineTemplateSpec defines the desired state - of the kubevirt VM. - properties: - metadata: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: VirtualMachineSpec contains the VirtualMachine specification. - properties: - dataVolumeTemplates: - description: |- - dataVolumeTemplates is a list of dataVolumes that the VirtualMachineInstance template can reference. - DataVolumes in this list are dynamically created for the VirtualMachine and are tied to the VirtualMachine's life-cycle. - items: - nullable: true - 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: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: DataVolumeSpec contains the DataVolume - specification. - properties: - checkpoints: - description: Checkpoints is a list of DataVolumeCheckpoints, - representing stages in a multistage import. - items: - description: DataVolumeCheckpoint defines a stage - in a warm migration. - properties: - current: - description: Current is the identifier of - the snapshot created for this checkpoint. - type: string - previous: - description: Previous is the identifier of - the snapshot from the previous checkpoint. - type: string - required: - - current - - previous - type: object - type: array - contentType: - description: 'DataVolumeContentType options: "kubevirt", - "archive"' - enum: - - kubevirt - - archive - type: string - finalCheckpoint: - description: FinalCheckpoint indicates whether the - current DataVolumeCheckpoint is the final checkpoint. - type: boolean - preallocation: - description: Preallocation controls whether storage - for DataVolumes should be allocated in advance. - type: boolean - priorityClassName: - description: PriorityClassName for Importer, Cloner - and Uploader pod - type: string - pvc: - description: PVC is the PVC specification - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query over - volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - source: - description: Source is the src of the data for the - requested DataVolume - properties: - blank: - description: DataVolumeBlankImage provides the - parameters to create a new raw blank image - for the PVC - type: object - gcs: - description: DataVolumeSourceGCS provides the - parameters to create a Data Volume from an - GCS source - properties: - secretRef: - description: SecretRef provides the secret - reference needed to access the GCS source - type: string - url: - description: URL is the url of the GCS source - type: string - required: - - url - type: object - http: - description: DataVolumeSourceHTTP can be either - an http or https endpoint, with an optional - basic auth user name and password, and an - optional configmap containing additional CAs - properties: - certConfigMap: - description: CertConfigMap is a configmap - reference, containing a Certificate Authority(CA) - public key, and a base64 encoded pem certificate - type: string - extraHeaders: - description: ExtraHeaders is a list of strings - containing extra headers to include with - HTTP transfer requests - items: - type: string - type: array - secretExtraHeaders: - description: SecretExtraHeaders is a list - of Secret references, each containing - an extra HTTP header that may include - sensitive information - items: - type: string - type: array - secretRef: - description: SecretRef A Secret reference, - the secret should contain accessKeyId - (user name) base64 encoded, and secretKey - (password) also base64 encoded - type: string - url: - description: URL is the URL of the http(s) - endpoint - type: string - required: - - url - type: object - imageio: - description: DataVolumeSourceImageIO provides - the parameters to create a Data Volume from - an imageio source - properties: - certConfigMap: - description: CertConfigMap provides a reference - to the CA cert - type: string - diskId: - description: DiskID provides id of a disk - to be imported - type: string - secretRef: - description: SecretRef provides the secret - reference needed to access the ovirt-engine - type: string - url: - description: URL is the URL of the ovirt-engine - type: string - required: - - diskId - - url - type: object - pvc: - description: DataVolumeSourcePVC provides the - parameters to create a Data Volume from an - existing PVC - properties: - name: - description: The name of the source PVC - type: string - namespace: - description: The namespace of the source - PVC - type: string - required: - - name - - namespace - type: object - registry: - description: DataVolumeSourceRegistry provides - the parameters to create a Data Volume from - an registry source - properties: - certConfigMap: - description: CertConfigMap provides a reference - to the Registry certs - type: string - imageStream: - description: ImageStream is the name of - image stream for import - type: string - pullMethod: - description: PullMethod can be either "pod" - (default import), or "node" (node docker - cache based import) - type: string - secretRef: - description: SecretRef provides the secret - reference needed to access the Registry - source - type: string - url: - description: 'URL is the url of the registry - source (starting with the scheme: docker, - oci-archive)' - type: string - type: object - s3: - description: DataVolumeSourceS3 provides the - parameters to create a Data Volume from an - S3 source - properties: - certConfigMap: - description: CertConfigMap is a configmap - reference, containing a Certificate Authority(CA) - public key, and a base64 encoded pem certificate - type: string - secretRef: - description: SecretRef provides the secret - reference needed to access the S3 source - type: string - url: - description: URL is the url of the S3 source - type: string - required: - - url - type: object - snapshot: - description: DataVolumeSourceSnapshot provides - the parameters to create a Data Volume from - an existing VolumeSnapshot - properties: - name: - description: The name of the source VolumeSnapshot - type: string - namespace: - description: The namespace of the source - VolumeSnapshot - type: string - required: - - name - - namespace - type: object - upload: - description: DataVolumeSourceUpload provides - the parameters to create a Data Volume by - uploading the source - type: object - vddk: - description: DataVolumeSourceVDDK provides the - parameters to create a Data Volume from a - Vmware source - properties: - backingFile: - description: BackingFile is the path to - the virtual hard disk to migrate from - vCenter/ESXi - type: string - initImageURL: - description: InitImageURL is an optional - URL to an image containing an extracted - VDDK library, overrides v2v-vmware config - map - type: string - secretRef: - description: SecretRef provides a reference - to a secret containing the username and - password needed to access the vCenter - or ESXi host - type: string - thumbprint: - description: Thumbprint is the certificate - thumbprint of the vCenter or ESXi host - type: string - url: - description: URL is the URL of the vCenter - or ESXi host with the VM to migrate - type: string - uuid: - description: UUID is the UUID of the virtual - machine that the backing file is attached - to in vCenter/ESXi - type: string - type: object - type: object - sourceRef: - description: SourceRef is an indirect reference - to the source of data for the requested DataVolume - properties: - kind: - description: The kind of the source reference, - currently only "DataSource" is supported - type: string - name: - description: The name of the source reference - type: string - namespace: - description: The namespace of the source reference, - defaults to the DataVolume namespace - type: string - required: - - kind - - name - type: object - storage: - description: Storage is the requested storage specification - properties: - accessModes: - description: |- - AccessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - dataSource: - description: |- - This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. - There are two important differences between DataSource and DataSourceRef: - * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. - * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - Resources represents the minimum resources the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: A label query over volumes to consider - for binding. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - Name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: VolumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - type: object - status: - description: |- - DataVolumeTemplateDummyStatus is here simply for backwards compatibility with - a previous API. - nullable: true - type: object - required: - - spec - type: object - type: array - instancetype: - description: InstancetypeMatcher references a instancetype - that is used to fill fields in Template - properties: - inferFromVolume: - description: |- - InferFromVolume lists the name of a volume that should be used to infer or discover the instancetype - to be used through known annotations on the underlying resource. Once applied to the InstancetypeMatcher - this field is removed. - type: string - inferFromVolumeFailurePolicy: - description: |- - InferFromVolumeFailurePolicy controls what should happen on failure when inferring the instancetype. - Allowed values are: "RejectInferFromVolumeFailure" and "IgnoreInferFromVolumeFailure". - If not specified, "RejectInferFromVolumeFailure" is used by default. - type: string - kind: - description: |- - Kind specifies which instancetype resource is referenced. - Allowed values are: "VirtualMachineInstancetype" and "VirtualMachineClusterInstancetype". - If not specified, "VirtualMachineClusterInstancetype" is used by default. - type: string - name: - description: Name is the name of the VirtualMachineInstancetype - or VirtualMachineClusterInstancetype - type: string - revisionName: - description: |- - RevisionName specifies a ControllerRevision containing a specific copy of the - VirtualMachineInstancetype or VirtualMachineClusterInstancetype to be used. This is initially - captured the first time the instancetype is applied to the VirtualMachineInstance. - type: string - type: object - preference: - description: PreferenceMatcher references a set of preference - that is used to fill fields in Template - properties: - inferFromVolume: - description: |- - InferFromVolume lists the name of a volume that should be used to infer or discover the preference - to be used through known annotations on the underlying resource. Once applied to the PreferenceMatcher - this field is removed. - type: string - inferFromVolumeFailurePolicy: - description: |- - InferFromVolumeFailurePolicy controls what should happen on failure when preference the instancetype. - Allowed values are: "RejectInferFromVolumeFailure" and "IgnoreInferFromVolumeFailure". - If not specified, "RejectInferFromVolumeFailure" is used by default. - type: string - kind: - description: |- - Kind specifies which preference resource is referenced. - Allowed values are: "VirtualMachinePreference" and "VirtualMachineClusterPreference". - If not specified, "VirtualMachineClusterPreference" is used by default. - type: string - name: - description: Name is the name of the VirtualMachinePreference - or VirtualMachineClusterPreference - type: string - revisionName: - description: |- - RevisionName specifies a ControllerRevision containing a specific copy of the - VirtualMachinePreference or VirtualMachineClusterPreference to be used. This is - initially captured the first time the instancetype is applied to the VirtualMachineInstance. - type: string - type: object - runStrategy: - description: |- - Running state indicates the requested running state of the VirtualMachineInstance - mutually exclusive with Running - type: string - running: - description: |- - Running controls whether the associatied VirtualMachineInstance is created or not - Mutually exclusive with RunStrategy - type: boolean - template: - description: Template is the direct specification of VirtualMachineInstance - properties: - metadata: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: VirtualMachineInstance Spec contains the - VirtualMachineInstance specification. - properties: - accessCredentials: - description: Specifies a set of public keys to inject - into the vm guest - items: - description: |- - AccessCredential represents a credential source that can be used to - authorize remote access to the vm guest - Only one of its members may be specified. - properties: - sshPublicKey: - description: |- - SSHPublicKey represents the source and method of applying a ssh public - key into a guest virtual machine. - properties: - propagationMethod: - description: PropagationMethod represents - how the public key is injected into the - vm guest. - properties: - configDrive: - description: |- - ConfigDrivePropagation means that the ssh public keys are injected - into the VM using metadata using the configDrive cloud-init provider - type: object - noCloud: - description: |- - NoCloudPropagation means that the ssh public keys are injected - into the VM using metadata using the noCloud cloud-init provider - type: object - qemuGuestAgent: - description: |- - QemuGuestAgentAccessCredentailPropagation means ssh public keys are - dynamically injected into the vm at runtime via the qemu guest agent. - This feature requires the qemu guest agent to be running within the guest. - properties: - users: - description: |- - Users represents a list of guest users that should have the ssh public keys - added to their authorized_keys file. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - users - type: object - type: object - source: - description: Source represents where the - public keys are pulled from - properties: - secret: - description: Secret means that the access - credential is pulled from a kubernetes - secret - properties: - secretName: - description: SecretName represents - the name of the secret in the - VMI's namespace - type: string - required: - - secretName - type: object - type: object - required: - - propagationMethod - - source - type: object - userPassword: - description: |- - UserPassword represents the source and method for applying a guest user's - password - properties: - propagationMethod: - description: propagationMethod represents - how the user passwords are injected into - the vm guest. - properties: - qemuGuestAgent: - description: |- - QemuGuestAgentAccessCredentailPropagation means passwords are - dynamically injected into the vm at runtime via the qemu guest agent. - This feature requires the qemu guest agent to be running within the guest. - type: object - type: object - source: - description: Source represents where the - user passwords are pulled from - properties: - secret: - description: Secret means that the access - credential is pulled from a kubernetes - secret - properties: - secretName: - description: SecretName represents - the name of the secret in the - VMI's namespace - type: string - required: - - secretName - type: object - type: object - required: - - propagationMethod - - source - type: object - type: object - type: array - x-kubernetes-list-type: atomic - affinity: - description: If affinity is specifies, obey all the - affinity rules - properties: - nodeAffinity: - description: Describes node affinity scheduling - rules for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key - that the selector applies - to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key - that the selector applies - to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with - matching the corresponding nodeSelectorTerm, - in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node - selector terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key - that the selector applies - to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key - that the selector applies - to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling - rules (e.g. co-locate this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added - per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity - term, associated with the corresponding - weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the - label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the - label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same - node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added - per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity - term, associated with the corresponding - weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the - label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the - label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - architecture: - description: Specifies the architecture of the vm - guest you are attempting to run. Defaults to the - compiled architecture of the KubeVirt components - type: string - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines DNS - resolver options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - domain: - description: Specification of the desired behavior - of the VirtualMachineInstance on the host. - properties: - chassis: - description: Chassis specifies the chassis info - passed to the domain. - properties: - asset: - type: string - manufacturer: - type: string - serial: - type: string - sku: - type: string - version: - type: string - type: object - clock: - description: Clock sets the clock and timers of - the vmi. - properties: - timer: - description: Timer specifies whih timers are - attached to the vmi. - properties: - hpet: - description: HPET (High Precision Event - Timer) - multiple timers with periodic - interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup", "merge", "discard". - type: string - type: object - hyperv: - description: Hyperv (Hypervclock) - lets - guests read the host’s wall clock time - (paravirtualized). For windows guests. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - type: object - kvm: - description: "KVM \t(KVM clock) - lets - guests read the host’s wall clock time - (paravirtualized). For linux guests." - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - type: object - pit: - description: PIT (Programmable Interval - Timer) - a timer with periodic interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup", "discard". - type: string - type: object - rtc: - description: RTC (Real Time Clock) - a - continuously running timer with periodic - interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup". - type: string - track: - description: Track the guest or the - wall clock. - type: string - type: object - type: object - timezone: - description: |- - Timezone sets the guest clock to the specified timezone. - Zone name follows the TZ environment variable format (e.g. 'America/New_York'). - type: string - utc: - description: |- - UTC sets the guest clock to UTC on each boot. If an offset is specified, - guest changes to the clock will be kept during reboots and are not reset. - properties: - offsetSeconds: - description: |- - OffsetSeconds specifies an offset in seconds, relative to UTC. If set, - guest changes to the clock will be kept during reboots and not reset. - type: integer - type: object - type: object - x-kubernetes-preserve-unknown-fields: true - cpu: - description: CPU allow specified the detailed - CPU topology inside the vmi. - properties: - cores: - description: |- - Cores specifies the number of cores inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - dedicatedCpuPlacement: - description: |- - DedicatedCPUPlacement requests the scheduler to place the VirtualMachineInstance on a node - with enough dedicated pCPUs and pin the vCPUs to it. - type: boolean - features: - description: Features specifies the CPU features - list inside the VMI. - items: - description: CPUFeature allows specifying - a CPU feature. - properties: - name: - description: Name of the CPU feature - type: string - policy: - description: |- - Policy is the CPU feature attribute which can have the following attributes: - force - The virtual CPU will claim the feature is supported regardless of it being supported by host CPU. - require - Guest creation will fail unless the feature is supported by the host CPU or the hypervisor is able to emulate it. - optional - The feature will be supported by virtual CPU if and only if it is supported by host CPU. - disable - The feature will not be supported by virtual CPU. - forbid - Guest creation will fail if the feature is supported by host CPU. - Defaults to require - type: string - required: - - name - type: object - type: array - isolateEmulatorThread: - description: |- - IsolateEmulatorThread requests one more dedicated pCPU to be allocated for the VMI to place - the emulator thread on it. - type: boolean - maxSockets: - description: |- - MaxSockets specifies the maximum amount of sockets that can - be hotplugged - format: int32 - type: integer - model: - description: |- - Model specifies the CPU model inside the VMI. - List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map. - It is possible to specify special cases like "host-passthrough" to get the same CPU as the node - and "host-model" to get CPU closest to the node one. - Defaults to host-model. - type: string - numa: - description: NUMA allows specifying settings - for the guest NUMA topology - properties: - guestMappingPassthrough: - description: |- - GuestMappingPassthrough will create an efficient guest topology based on host CPUs exclusively assigned to a pod. - The created topology ensures that memory and CPUs on the virtual numa nodes never cross boundaries of host numa nodes. - type: object - type: object - realtime: - description: Realtime instructs the virt-launcher - to tune the VMI for lower latency, optional - for real time workloads - properties: - mask: - description: |- - Mask defines the vcpu mask expression that defines which vcpus are used for realtime. Format matches libvirt's expressions. - Example: "0-3,^1","0,2,3","2-3" - type: string - type: object - sockets: - description: |- - Sockets specifies the number of sockets inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - threads: - description: |- - Threads specifies the number of threads inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - type: object - devices: - description: Devices allows adding disks, network - interfaces, and others - properties: - autoattachGraphicsDevice: - description: |- - Whether to attach the default graphics device or not. - VNC will not be available if set to false. Defaults to true. - type: boolean - autoattachInputDevice: - description: |- - Whether to attach an Input Device. - Defaults to false. - type: boolean - autoattachMemBalloon: - description: |- - Whether to attach the Memory balloon device with default period. - Period can be adjusted in virt-config. - Defaults to true. - type: boolean - autoattachPodInterface: - description: Whether to attach a pod network - interface. Defaults to true. - type: boolean - autoattachSerialConsole: - description: |- - Whether to attach the default virtio-serial console or not. - Serial console access will not be available if set to false. Defaults to true. - type: boolean - autoattachVSOCK: - description: |- - Whether to attach the VSOCK CID to the VM or not. - VSOCK access will be available if set to true. Defaults to false. - type: boolean - blockMultiQueue: - description: |- - Whether or not to enable virtio multi-queue for block devices. - Defaults to false. - type: boolean - clientPassthrough: - description: To configure and access client - devices such as redirecting USB - type: object - disableHotplug: - description: DisableHotplug disabled the ability - to hotplug disks. - type: boolean - disks: - description: Disks describes disks, cdroms - and luns which are connected to the vmi. - items: - properties: - blockSize: - description: If specified, the virtual - disk will be presented with the given - block sizes. - properties: - custom: - description: CustomBlockSize represents - the desired logical and physical - block size for a VM disk. - properties: - logical: - type: integer - physical: - type: integer - required: - - logical - - physical - type: object - matchVolume: - description: Represents if a feature - is enabled or disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - bootOrder: - description: |- - BootOrder is an integer value > 0, used to determine ordering of boot devices. - Lower values take precedence. - Each disk or interface that has a boot order must have a unique value. - Disks without a boot order are not tried if a disk with a boot order exists. - type: integer - cache: - description: |- - Cache specifies which kvm disk cache mode should be used. - Supported values are: CacheNone, CacheWriteThrough. - type: string - cdrom: - description: Attach a volume as a cdrom - to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi. - type: string - readonly: - description: |- - ReadOnly. - Defaults to true. - type: boolean - tray: - description: |- - Tray indicates if the tray of the device is open or closed. - Allowed values are "open" and "closed". - Defaults to closed. - type: string - type: object - dedicatedIOThread: - description: |- - dedicatedIOThread indicates this disk should have an exclusive IO Thread. - Enabling this implies useIOThreads = true. - Defaults to false. - type: boolean - disk: - description: Attach a volume as a disk - to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi, usb. - type: string - pciAddress: - description: 'If specified, the - virtual disk will be placed on - the guests pci address with the - specified PCI address. For example: - 0000:81:01.10' - type: string - readonly: - description: |- - ReadOnly. - Defaults to false. - type: boolean - type: object - errorPolicy: - description: If specified, it can change - the default error policy (stop) for - the disk - type: string - io: - description: |- - IO specifies which QEMU disk IO mode should be used. - Supported values are: native, default, threads. - type: string - lun: - description: Attach a volume as a LUN - to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi. - type: string - readonly: - description: |- - ReadOnly. - Defaults to false. - type: boolean - reservation: - description: Reservation indicates - if the disk needs to support the - persistent reservation for the - SCSI disk - type: boolean - type: object - name: - description: Name is the device name - type: string - serial: - description: Serial provides the ability - to specify a serial number for the - disk device. - type: string - shareable: - description: If specified the disk is - made sharable and multiple write from - different VMs are permitted - type: boolean - tag: - description: If specified, disk address - and its tag will be provided to the - guest via config drive metadata - type: string - required: - - name - type: object - type: array - downwardMetrics: - description: DownwardMetrics creates a virtio - serials for exposing the downward metrics - to the vmi. - type: object - filesystems: - description: Filesystems describes filesystem - which is connected to the vmi. - items: - properties: - name: - description: Name is the device name - type: string - virtiofs: - description: Virtiofs is supported - type: object - required: - - name - - virtiofs - type: object - type: array - x-kubernetes-list-type: atomic - gpus: - description: Whether to attach a GPU device - to the vmi. - items: - properties: - deviceName: - type: string - name: - description: Name of the GPU device - as exposed by a device plugin - type: string - tag: - description: If specified, the virtual - network interface address and its - tag will be provided to the guest - via config drive - type: string - virtualGPUOptions: - properties: - display: - properties: - enabled: - description: |- - Enabled determines if a display addapter backed by a vGPU should be enabled or disabled on the guest. - Defaults to true. - type: boolean - ramFB: - description: |- - Enables a boot framebuffer, until the guest OS loads a real GPU driver - Defaults to true. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - type: object - required: - - deviceName - - name - type: object - type: array - x-kubernetes-list-type: atomic - hostDevices: - description: Whether to attach a host device - to the vmi. - items: - properties: - deviceName: - description: DeviceName is the resource - name of the host device exposed by - a device plugin - type: string - name: - type: string - tag: - description: If specified, the virtual - network interface address and its - tag will be provided to the guest - via config drive - type: string - required: - - deviceName - - name - type: object - type: array - x-kubernetes-list-type: atomic - inputs: - description: Inputs describe input devices - items: - properties: - bus: - description: |- - Bus indicates the bus of input device to emulate. - Supported values: virtio, usb. - type: string - name: - description: Name is the device name - type: string - type: - description: |- - Type indicated the type of input device. - Supported values: tablet. - type: string - required: - - name - - type - type: object - type: array - interfaces: - description: Interfaces describe network interfaces - which are added to the vmi. - items: - properties: - acpiIndex: - description: |- - If specified, the ACPI index is used to provide network interface device naming, that is stable across changes - in PCI addresses assigned to the device. - This value is required to be unique across all devices and be between 1 and (16*1024-1). - type: integer - binding: - description: |- - Binding specifies the binding plugin that will be used to connect the interface to the guest. - It provides an alternative to InterfaceBindingMethod. - version: 1alphav1 - properties: - name: - description: |- - Name references to the binding name as denined in the kubevirt CR. - version: 1alphav1 - type: string - required: - - name - type: object - bootOrder: - description: |- - BootOrder is an integer value > 0, used to determine ordering of boot devices. - Lower values take precedence. - Each interface or disk that has a boot order must have a unique value. - Interfaces without a boot order are not tried. - type: integer - bridge: - description: InterfaceBridge connects - to a given network via a linux bridge. - type: object - dhcpOptions: - description: If specified the network - interface will pass additional DHCP - options to the VMI - properties: - bootFileName: - description: If specified will pass - option 67 to interface's DHCP - server - type: string - ntpServers: - description: If specified will pass - the configured NTP server to the - VM via DHCP option 042. - items: - type: string - type: array - privateOptions: - description: 'If specified will - pass extra DHCP options for private - use, range: 224-254' - items: - description: DHCPExtraOptions - defines Extra DHCP options for - a VM. - properties: - option: - description: |- - Option is an Integer value from 224-254 - Required. - type: integer - value: - description: |- - Value is a String value for the Option provided - Required. - type: string - required: - - option - - value - type: object - type: array - tftpServerName: - description: If specified will pass - option 66 to interface's DHCP - server - type: string - type: object - macAddress: - description: 'Interface MAC address. - For example: de:ad:00:00:be:af or - DE-AD-00-00-BE-AF.' - type: string - macvtap: - description: Deprecated, please refer - to Kubevirt user guide for alternatives. - type: object - masquerade: - description: InterfaceMasquerade connects - to a given network using netfilter - rules to nat the traffic. - type: object - model: - description: |- - Interface model. - One of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio. - Defaults to virtio. - TODO:(ihar) switch to enums once opengen-api supports them. See: https://github.com/kubernetes/kube-openapi/issues/51 - type: string - name: - description: |- - Logical name of the interface as well as a reference to the associated networks. - Must match the Name of a Network. - type: string - passt: - description: Deprecated, please refer - to Kubevirt user guide for alternatives. - type: object - pciAddress: - description: 'If specified, the virtual - network interface will be placed on - the guests pci address with the specified - PCI address. For example: 0000:81:01.10' - type: string - ports: - description: List of ports to be forwarded - to the virtual machine. - items: - description: |- - Port represents a port to expose from the virtual machine. - Default protocol TCP. - The port field is mandatory - properties: - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - port: - description: |- - Number of port to expose for the virtual machine. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - protocol: - description: |- - Protocol for port. Must be UDP or TCP. - Defaults to "TCP". - type: string - required: - - port - type: object - type: array - slirp: - description: InterfaceSlirp connects - to a given network using QEMU user - networking mode. - type: object - sriov: - description: InterfaceSRIOV connects - to a given network by passing-through - an SR-IOV PCI device via vfio. - type: object - state: - description: |- - State represents the requested operational state of the interface. - The (only) value supported is `absent`, expressing a request to remove the interface. - type: string - tag: - description: If specified, the virtual - network interface address and its - tag will be provided to the guest - via config drive - type: string - required: - - name - type: object - type: array - logSerialConsole: - description: |- - Whether to log the auto-attached default serial console or not. - Serial console logs will be collect to a file and then streamed from a named `guest-console-log`. - Not relevant if autoattachSerialConsole is disabled. - Defaults to cluster wide setting on VirtualMachineOptions. - type: boolean - networkInterfaceMultiqueue: - description: If specified, virtual network - interfaces configured with a virtio bus - will also enable the vhost multiqueue feature - for network devices. The number of queues - created depends on additional factors of - the VirtualMachineInstance, like the number - of guest CPUs. - type: boolean - rng: - description: Whether to have random number - generator from host - type: object - sound: - description: Whether to emulate a sound device. - properties: - model: - description: |- - We only support ich9 or ac97. - If SoundDevice is not set: No sound card is emulated. - If SoundDevice is set but Model is not: ich9 - type: string - name: - description: User's defined name for this - sound device - type: string - required: - - name - type: object - tpm: - description: Whether to emulate a TPM device. - properties: - persistent: - description: |- - Persistent indicates the state of the TPM device should be kept accross reboots - Defaults to false - type: boolean - type: object - useVirtioTransitional: - description: |- - Fall back to legacy virtio 0.9 support if virtio bus is selected on devices. - This is helpful for old machines like CentOS6 or RHEL6 which - do not understand virtio_non_transitional (virtio 1.0). - type: boolean - watchdog: - description: Watchdog describes a watchdog - device which can be added to the vmi. - properties: - i6300esb: - description: i6300esb watchdog device. - properties: - action: - description: |- - The action to take. Valid values are poweroff, reset, shutdown. - Defaults to reset. - type: string - type: object - name: - description: Name of the watchdog. - type: string - required: - - name - type: object - type: object - features: - description: Features like acpi, apic, hyperv, - smm. - properties: - acpi: - description: |- - ACPI enables/disables ACPI inside the guest. - Defaults to enabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - apic: - description: Defaults to the machine type - setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - endOfInterrupt: - description: |- - EndOfInterrupt enables the end of interrupt notification in the guest. - Defaults to false. - type: boolean - type: object - hyperv: - description: Defaults to the machine type - setting. - properties: - evmcs: - description: |- - EVMCS Speeds up L2 vmexits, but disables other virtualization features. Requires vapic. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - frequencies: - description: |- - Frequencies improves the TSC clock source handling for Hyper-V on KVM. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - ipi: - description: |- - IPI improves performances in overcommited environments. Requires vpindex. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - reenlightenment: - description: |- - Reenlightenment enables the notifications on TSC frequency changes. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - relaxed: - description: |- - Relaxed instructs the guest OS to disable watchdog timeouts. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - reset: - description: |- - Reset enables Hyperv reboot/reset for the vmi. Requires synic. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - runtime: - description: |- - Runtime improves the time accounting to improve scheduling in the guest. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - spinlocks: - description: Spinlocks allows to configure - the spinlock retry attempts. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - spinlocks: - description: |- - Retries indicates the number of retries. - Must be a value greater or equal 4096. - Defaults to 4096. - format: int32 - type: integer - type: object - synic: - description: |- - SyNIC enables the Synthetic Interrupt Controller. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - synictimer: - description: |- - SyNICTimer enables Synthetic Interrupt Controller Timers, reducing CPU load. - Defaults to the machine type setting. - properties: - direct: - description: Represents if a feature - is enabled or disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - enabled: - type: boolean - type: object - tlbflush: - description: |- - TLBFlush improves performances in overcommited environments. Requires vpindex. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - vapic: - description: |- - VAPIC improves the paravirtualized handling of interrupts. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - vendorid: - description: |- - VendorID allows setting the hypervisor vendor id. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - vendorid: - description: |- - VendorID sets the hypervisor vendor id, visible to the vmi. - String up to twelve characters. - type: string - type: object - vpindex: - description: |- - VPIndex enables the Virtual Processor Index to help windows identifying virtual processors. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - kvm: - description: Configure how KVM presence is - exposed to the guest. - properties: - hidden: - description: |- - Hide the KVM hypervisor from standard MSR based discovery. - Defaults to false - type: boolean - type: object - pvspinlock: - description: |- - Notify the guest that the host supports paravirtual spinlocks. - For older kernels this feature should be explicitly disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - smm: - description: |- - SMM enables/disables System Management Mode. - TSEG not yet implemented. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - firmware: - description: Firmware. - properties: - acpi: - description: Information that can be set in - the ACPI table - properties: - slicNameRef: - description: |- - SlicNameRef should match the volume name of a secret object. The data in the secret should - be a binary blob that follows the ACPI SLIC standard, see: - https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653305(v=vs.85) - type: string - type: object - bootloader: - description: Settings to control the bootloader - that is used. - properties: - bios: - description: If set (default), BIOS will - be used. - properties: - useSerial: - description: If set, the BIOS output - will be transmitted over serial - type: boolean - type: object - efi: - description: If set, EFI will be used - instead of BIOS. - properties: - persistent: - description: |- - If set to true, Persistent will persist the EFI NVRAM across reboots. - Defaults to false - type: boolean - secureBoot: - description: |- - If set, SecureBoot will be enabled and the OVMF roms will be swapped for - SecureBoot-enabled ones. - Requires SMM to be enabled. - Defaults to true - type: boolean - type: object - type: object - kernelBoot: - description: Settings to set the kernel for - booting. - properties: - container: - description: Container defines the container - that containes kernel artifacts - properties: - image: - description: Image that contains initrd - / kernel files. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecret: - description: ImagePullSecret is the - name of the Docker registry secret - required to pull the image. The - secret must already exist. - type: string - initrdPath: - description: the fully-qualified path - to the ramdisk image in the host - OS - type: string - kernelPath: - description: The fully-qualified path - to the kernel image in the host - OS - type: string - required: - - image - type: object - kernelArgs: - description: Arguments to be passed to - the kernel at boot time - type: string - type: object - serial: - description: The system-serial-number in SMBIOS - type: string - uuid: - description: |- - UUID reported by the vmi bios. - Defaults to a random generated uid. - type: string - type: object - ioThreadsPolicy: - description: |- - Controls whether or not disks will share IOThreads. - Omitting IOThreadsPolicy disables use of IOThreads. - One of: shared, auto - type: string - launchSecurity: - description: Launch Security setting of the vmi. - properties: - sev: - description: AMD Secure Encrypted Virtualization - (SEV). - properties: - attestation: - description: If specified, run the attestation - process for a vmi. - type: object - dhCert: - description: Base64 encoded guest owner's - Diffie-Hellman key. - type: string - policy: - description: |- - Guest policy flags as defined in AMD SEV API specification. - Note: due to security reasons it is not allowed to enable guest debugging. Therefore NoDebug flag is not exposed to users and is always true. - properties: - encryptedState: - description: |- - SEV-ES is required. - Defaults to false. - type: boolean - type: object - session: - description: Base64 encoded session blob. - type: string - type: object - type: object - machine: - description: Machine type. - properties: - type: - description: QEMU machine type is the actual - chipset of the VirtualMachineInstance. - type: string - type: object - memory: - description: Memory allow specifying the VMI memory - features. - properties: - guest: - anyOf: - - type: integer - - type: string - description: |- - Guest allows to specifying the amount of memory which is visible inside the Guest OS. - The Guest must lie between Requests and Limits from the resources section. - Defaults to the requested memory in the resources section if not specified. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - hugepages: - description: Hugepages allow to use hugepages - for the VirtualMachineInstance instead of - regular memory. - properties: - pageSize: - description: PageSize specifies the hugepage - size, for x86_64 architecture valid - values are 1Gi and 2Mi. - type: string - type: object - maxGuest: - anyOf: - - type: integer - - type: string - description: |- - MaxGuest allows to specify the maximum amount of memory which is visible inside the Guest OS. - The delta between MaxGuest and Guest is the amount of memory that can be hot(un)plugged. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - resources: - description: Resources describes the Compute Resources - required by this vmi. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - Valid resource keys are "memory" and "cpu". - type: object - overcommitGuestOverhead: - description: |- - Don't ask the scheduler to take the guest-management overhead into account. Instead - put the overhead only into the container's memory limit. This can lead to crashes if - all memory is in use on a node. Defaults to false. - type: boolean - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests is a description of the initial vmi resources. - Valid resource keys are "memory" and "cpu". - type: object - type: object - required: - - devices - type: object - evictionStrategy: - description: |- - EvictionStrategy describes the strategy to follow when a node drain occurs. - The possible options are: - - "None": No action will be taken, according to the specified 'RunStrategy' the VirtualMachine will be restarted or shutdown. - - "LiveMigrate": the VirtualMachineInstance will be migrated instead of being shutdown. - - "LiveMigrateIfPossible": the same as "LiveMigrate" but only if the VirtualMachine is Live-Migratable, otherwise it will behave as "None". - - "External": the VirtualMachineInstance will be protected by a PDB and `vmi.Status.EvacuationNodeName` will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. - type: string - hostname: - description: |- - Specifies the hostname of the vmi - If not specified, the hostname will be set to the name of the vmi, if dhcp or cloud-init is configured properly. - type: string - livenessProbe: - description: |- - Periodic probe of VirtualMachineInstance liveness. - VirtualmachineInstances will be stopped if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: |- - One and only one of the following should be specified. - Exec specifies the action to take, it will be executed on the guest through the qemu-guest-agent. - If the guest agent is not available, this probe will fail. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - guestAgentPing: - description: GuestAgentPing contacts the qemu-guest-agent - for availability checks. - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: |- - TCPSocket specifies an action involving a TCP port. - TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - For exec probes the timeout fails the probe but does not terminate the command running on the guest. - This means a blocking command can result in an increasing load on the guest. - A small buffer will be added to the resulting workload exec probe to compensate for delays - caused by the qemu guest exec mechanism. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - networks: - description: List of networks that can be attached - to a vm's virtual interface. - items: - description: Network represents a network type and - a resource that should be connected to the vm. - properties: - multus: - description: Represents the multus cni network. - properties: - default: - description: |- - Select the default network and add it to the - multus-cni.io/default-network annotation. - type: boolean - networkName: - description: |- - References to a NetworkAttachmentDefinition CRD object. Format: - , /. If namespace is not - specified, VMI namespace is assumed. - type: string - required: - - networkName - type: object - name: - description: |- - Network name. - Must be a DNS_LABEL and unique within the vm. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - pod: - description: Represents the stock pod network - interface. - properties: - vmIPv6NetworkCIDR: - description: |- - IPv6 CIDR for the vm network. - Defaults to fd10:0:2::/120 if not specified. - type: string - vmNetworkCIDR: - description: |- - CIDR for vm network. - Default 10.0.2.0/24 if not specified. - type: string - type: object - required: - - name - type: object - type: array - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the vmi to fit on a node. - Selector which must match a node's labels for the vmi to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: |- - If specified, indicates the pod's priority. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessProbe: - description: |- - Periodic probe of VirtualMachineInstance service readiness. - VirtualmachineInstances will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: |- - One and only one of the following should be specified. - Exec specifies the action to take, it will be executed on the guest through the qemu-guest-agent. - If the guest agent is not available, this probe will fail. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - guestAgentPing: - description: GuestAgentPing contacts the qemu-guest-agent - for availability checks. - type: object - httpGet: - description: HTTPGet specifies the http request - to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the - request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom - header to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: |- - TCPSocket specifies an action involving a TCP port. - TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook - properties: - host: - description: 'Optional: Host name to connect - to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - For exec probes the timeout fails the probe but does not terminate the command running on the guest. - This means a blocking command can result in an increasing load on the guest. - A small buffer will be added to the resulting workload exec probe to compensate for delays - caused by the qemu guest exec mechanism. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - schedulerName: - description: |- - If specified, the VMI will be dispatched by specified scheduler. - If not specified, the VMI will be dispatched by default scheduler. - type: string - startStrategy: - description: StartStrategy can be set to "Paused" - if Virtual Machine should be started in paused state. - type: string - subdomain: - description: |- - If specified, the fully qualified vmi hostname will be "...svc.". - If not specified, the vmi will not have a domainname at all. The DNS entry will resolve to the vmi, - no matter if the vmi itself can pick up a hostname. - type: string - terminationGracePeriodSeconds: - description: Grace period observed after signalling - a VirtualMachineInstance to stop after which the - VirtualMachineInstance is force terminated. - format: int64 - type: integer - tolerations: - description: If toleration is specified, obey all - the toleration rules. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of VMIs will be spread across a given topology - domains. K8s scheduler will schedule VMI pods in a way which abides by the constraints. - items: - description: TopologySpreadConstraint specifies - how to spread matching pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: List of volumes that can be mounted by - disks belonging to the vmi. - items: - description: Volume represents a named volume in - a vmi. - properties: - cloudInitConfigDrive: - description: |- - CloudInitConfigDrive represents a cloud-init Config Drive user-data source. - The Config Drive data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. - More info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html - properties: - networkData: - description: NetworkData contains config - drive inline cloud-init networkdata. - type: string - networkDataBase64: - description: NetworkDataBase64 contains - config drive cloud-init networkdata as - a base64 encoded string. - type: string - networkDataSecretRef: - description: NetworkDataSecretRef references - a k8s secret that contains config drive - networkdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secretRef: - description: UserDataSecretRef references - a k8s secret that contains config drive - userdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - userData: - description: UserData contains config drive - inline cloud-init userdata. - type: string - userDataBase64: - description: UserDataBase64 contains config - drive cloud-init userdata as a base64 - encoded string. - type: string - type: object - cloudInitNoCloud: - description: |- - CloudInitNoCloud represents a cloud-init NoCloud user-data source. - The NoCloud data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. - More info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html - properties: - networkData: - description: NetworkData contains NoCloud - inline cloud-init networkdata. - type: string - networkDataBase64: - description: NetworkDataBase64 contains - NoCloud cloud-init networkdata as a base64 - encoded string. - type: string - networkDataSecretRef: - description: NetworkDataSecretRef references - a k8s secret that contains NoCloud networkdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secretRef: - description: UserDataSecretRef references - a k8s secret that contains NoCloud userdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - userData: - description: UserData contains NoCloud inline - cloud-init userdata. - type: string - userDataBase64: - description: UserDataBase64 contains NoCloud - cloud-init userdata as a base64 encoded - string. - type: string - type: object - configMap: - description: |- - ConfigMapSource represents a reference to a ConfigMap in the same namespace. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - optional: - description: Specify whether the ConfigMap - or it's keys must be defined - type: boolean - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - x-kubernetes-map-type: atomic - containerDisk: - description: |- - ContainerDisk references a docker image, embedding a qcow or raw disk. - More info: https://kubevirt.gitbooks.io/user-guide/registry-disk.html - properties: - image: - description: Image is the name of the image - with the embedded disk. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecret: - description: ImagePullSecret is the name - of the Docker registry secret required - to pull the image. The secret must already - exist. - type: string - path: - description: Path defines the path to disk - file in the container - type: string - required: - - image - type: object - dataVolume: - description: |- - DataVolume represents the dynamic creation a PVC for this volume as well as - the process of populating that PVC with a disk image. - properties: - hotpluggable: - description: Hotpluggable indicates whether - the volume can be hotplugged and hotunplugged. - type: boolean - name: - description: |- - Name of both the DataVolume and the PVC in the same namespace. - After PVC population the DataVolume is garbage collected by default. - type: string - required: - - name - type: object - downwardAPI: - description: DownwardAPI represents downward - API about the pod that should populate this - volume - properties: - fields: - description: Fields is a list of downward - API volume file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a - field of the pod: only annotations, - labels, name, namespace and uid - are supported.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in - terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field - to select in the specified API - version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path is the - relative path name of the file to - be created. Must not be absolute - or contain the ''..'' path. Must - be utf-8 encoded. The first item - of the relative path must not start - with ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container name: - required for volumes, optional - for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - downwardMetrics: - description: |- - DownwardMetrics adds a very small disk to VMIs which contains a limited view of host and guest - metrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics. - type: object - emptyDisk: - description: |- - EmptyDisk represents a temporary disk which shares the vmis lifecycle. - More info: https://kubevirt.gitbooks.io/user-guide/disks-and-volumes.html - properties: - capacity: - anyOf: - - type: integer - - type: string - description: Capacity of the sparse disk. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - required: - - capacity - type: object - ephemeral: - description: Ephemeral is a special volume source - that "wraps" specified source and provides - copy-on-write image on top of it. - properties: - persistentVolumeClaim: - description: |- - PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. - Directly attached to the vmi via qemu. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - type: object - hostDisk: - description: HostDisk represents a disk created - on the cluster level - properties: - capacity: - anyOf: - - type: integer - - type: string - description: Capacity of the sparse disk - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - path: - description: The path to HostDisk image - located on the cluster - type: string - shared: - description: Shared indicate whether the - path is shared between nodes - type: boolean - type: - description: |- - Contains information if disk.img exists or should be created - allowed options are 'Disk' and 'DiskOrCreate' - type: string - required: - - path - - type - type: object - memoryDump: - description: MemoryDump is attached to the virt - launcher and is populated with a memory dump - of the vmi - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - hotpluggable: - description: Hotpluggable indicates whether - the volume can be hotplugged and hotunplugged. - type: boolean - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - name: - description: |- - Volume's name. - Must be a DNS_LABEL and unique within the vmi. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - persistentVolumeClaim: - description: |- - PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. - Directly attached to the vmi via qemu. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - hotpluggable: - description: Hotpluggable indicates whether - the volume can be hotplugged and hotunplugged. - type: boolean - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - secret: - description: |- - SecretVolumeSource represents a reference to a secret data in the same namespace. - More info: https://kubernetes.io/docs/concepts/configuration/secret/ - properties: - optional: - description: Specify whether the Secret - or it's keys must be defined - type: boolean - secretName: - description: |- - Name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - serviceAccount: - description: |- - ServiceAccountVolumeSource represents a reference to a service account. - There can only be one volume of this type! - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - properties: - serviceAccountName: - description: |- - Name of the service account in the pod's namespace to use. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - type: object - sysprep: - description: Represents a Sysprep volume source. - properties: - configMap: - description: ConfigMap references a ConfigMap - that contains Sysprep answer file named - autounattend.xml that should be attached - as disk of CDROM type. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secret: - description: Secret references a k8s Secret - that contains Sysprep answer file named - autounattend.xml that should be attached - as disk of CDROM type. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - required: - - domain - type: object - type: object - required: - - template - type: object - type: object - type: object - status: - description: KubevirtMachineStatus defines the observed state of KubevirtMachine. - properties: - addresses: - description: Addresses contains the associated addresses for the machine. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions defines current service state of the KubevirtMachine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - loadBalancerConfigured: - description: |- - LoadBalancerConfigured denotes that the machine has been - added to the load balancer - type: boolean - nodeupdated: - description: NodeUpdated denotes that the ProviderID is updated on - Node of this KubevirtMachine - type: boolean - ready: - default: false - description: Ready denotes that the machine is ready - type: boolean - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index dca23bc1a..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-kubevirtmachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,4521 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1alpha1 - name: kubevirtmachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: KubevirtMachineTemplate - listKind: KubevirtMachineTemplateList - plural: kubevirtmachinetemplates - singular: kubevirtmachinetemplate - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: KubevirtMachineTemplate is the Schema for the kubevirtmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: KubevirtMachineTemplateSpec defines the desired state of - KubevirtMachineTemplate. - properties: - template: - description: KubevirtMachineTemplateResource describes the data needed - to create a KubevirtMachine from a template. - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - infraClusterSecretRef: - description: |- - InfraClusterSecretRef is a reference to a secret with a kubeconfig for external cluster used for infra. - When nil, this defaults to the value present in the KubevirtCluster object's spec associated with this machine. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - providerID: - description: ProviderID TBD what to use for Kubevirt - type: string - virtualMachineBootstrapCheck: - description: BootstrapCheckSpec defines how the CAPK controller - is checking CAPI Sentinel file inside the VM. - properties: - checkStrategy: - default: ssh - description: |- - CheckStrategy describes how CAPK controller will validate a successful CAPI bootstrap. - Following specified method, CAPK will try to retrieve the state of the CAPI Sentinel file from the VM. - Possible values are: "none" or "ssh" (default is "ssh") and this value is validated by apiserver. - enum: - - none - - ssh - type: string - type: object - virtualMachineTemplate: - description: VirtualMachineTemplateSpec defines the desired - state of the kubevirt VM. - properties: - metadata: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: VirtualMachineSpec contains the VirtualMachine - specification. - properties: - dataVolumeTemplates: - description: |- - dataVolumeTemplates is a list of dataVolumes that the VirtualMachineInstance template can reference. - DataVolumes in this list are dynamically created for the VirtualMachine and are tied to the VirtualMachine's life-cycle. - items: - nullable: true - 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: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: DataVolumeSpec contains the DataVolume - specification. - properties: - checkpoints: - description: Checkpoints is a list of DataVolumeCheckpoints, - representing stages in a multistage import. - items: - description: DataVolumeCheckpoint defines - a stage in a warm migration. - properties: - current: - description: Current is the identifier - of the snapshot created for this - checkpoint. - type: string - previous: - description: Previous is the identifier - of the snapshot from the previous - checkpoint. - type: string - required: - - current - - previous - type: object - type: array - contentType: - description: 'DataVolumeContentType options: - "kubevirt", "archive"' - enum: - - kubevirt - - archive - type: string - finalCheckpoint: - description: FinalCheckpoint indicates whether - the current DataVolumeCheckpoint is the - final checkpoint. - type: boolean - preallocation: - description: Preallocation controls whether - storage for DataVolumes should be allocated - in advance. - type: boolean - priorityClassName: - description: PriorityClassName for Importer, - Cloner and Uploader pod - type: string - pvc: - description: PVC is the PVC specification - properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of - resource being referenced - type: string - name: - description: Name is the name of - resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of - resource being referenced - type: string - name: - description: Name is the name of - resource being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: selector is a label query - over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: - description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding - reference to the PersistentVolume - backing this claim. - type: string - type: object - source: - description: Source is the src of the data - for the requested DataVolume - properties: - blank: - description: DataVolumeBlankImage provides - the parameters to create a new raw - blank image for the PVC - type: object - gcs: - description: DataVolumeSourceGCS provides - the parameters to create a Data Volume - from an GCS source - properties: - secretRef: - description: SecretRef provides - the secret reference needed to - access the GCS source - type: string - url: - description: URL is the url of the - GCS source - type: string - required: - - url - type: object - http: - description: DataVolumeSourceHTTP can - be either an http or https endpoint, - with an optional basic auth user name - and password, and an optional configmap - containing additional CAs - properties: - certConfigMap: - description: CertConfigMap is a - configmap reference, containing - a Certificate Authority(CA) public - key, and a base64 encoded pem - certificate - type: string - extraHeaders: - description: ExtraHeaders is a list - of strings containing extra headers - to include with HTTP transfer - requests - items: - type: string - type: array - secretExtraHeaders: - description: SecretExtraHeaders - is a list of Secret references, - each containing an extra HTTP - header that may include sensitive - information - items: - type: string - type: array - secretRef: - description: SecretRef A Secret - reference, the secret should contain - accessKeyId (user name) base64 - encoded, and secretKey (password) - also base64 encoded - type: string - url: - description: URL is the URL of the - http(s) endpoint - type: string - required: - - url - type: object - imageio: - description: DataVolumeSourceImageIO - provides the parameters to create - a Data Volume from an imageio source - properties: - certConfigMap: - description: CertConfigMap provides - a reference to the CA cert - type: string - diskId: - description: DiskID provides id - of a disk to be imported - type: string - secretRef: - description: SecretRef provides - the secret reference needed to - access the ovirt-engine - type: string - url: - description: URL is the URL of the - ovirt-engine - type: string - required: - - diskId - - url - type: object - pvc: - description: DataVolumeSourcePVC provides - the parameters to create a Data Volume - from an existing PVC - properties: - name: - description: The name of the source - PVC - type: string - namespace: - description: The namespace of the - source PVC - type: string - required: - - name - - namespace - type: object - registry: - description: DataVolumeSourceRegistry - provides the parameters to create - a Data Volume from an registry source - properties: - certConfigMap: - description: CertConfigMap provides - a reference to the Registry certs - type: string - imageStream: - description: ImageStream is the - name of image stream for import - type: string - pullMethod: - description: PullMethod can be either - "pod" (default import), or "node" - (node docker cache based import) - type: string - secretRef: - description: SecretRef provides - the secret reference needed to - access the Registry source - type: string - url: - description: 'URL is the url of - the registry source (starting - with the scheme: docker, oci-archive)' - type: string - type: object - s3: - description: DataVolumeSourceS3 provides - the parameters to create a Data Volume - from an S3 source - properties: - certConfigMap: - description: CertConfigMap is a - configmap reference, containing - a Certificate Authority(CA) public - key, and a base64 encoded pem - certificate - type: string - secretRef: - description: SecretRef provides - the secret reference needed to - access the S3 source - type: string - url: - description: URL is the url of the - S3 source - type: string - required: - - url - type: object - snapshot: - description: DataVolumeSourceSnapshot - provides the parameters to create - a Data Volume from an existing VolumeSnapshot - properties: - name: - description: The name of the source - VolumeSnapshot - type: string - namespace: - description: The namespace of the - source VolumeSnapshot - type: string - required: - - name - - namespace - type: object - upload: - description: DataVolumeSourceUpload - provides the parameters to create - a Data Volume by uploading the source - type: object - vddk: - description: DataVolumeSourceVDDK provides - the parameters to create a Data Volume - from a Vmware source - properties: - backingFile: - description: BackingFile is the - path to the virtual hard disk - to migrate from vCenter/ESXi - type: string - initImageURL: - description: InitImageURL is an - optional URL to an image containing - an extracted VDDK library, overrides - v2v-vmware config map - type: string - secretRef: - description: SecretRef provides - a reference to a secret containing - the username and password needed - to access the vCenter or ESXi - host - type: string - thumbprint: - description: Thumbprint is the certificate - thumbprint of the vCenter or ESXi - host - type: string - url: - description: URL is the URL of the - vCenter or ESXi host with the - VM to migrate - type: string - uuid: - description: UUID is the UUID of - the virtual machine that the backing - file is attached to in vCenter/ESXi - type: string - type: object - type: object - sourceRef: - description: SourceRef is an indirect reference - to the source of data for the requested - DataVolume - properties: - kind: - description: The kind of the source - reference, currently only "DataSource" - is supported - type: string - name: - description: The name of the source - reference - type: string - namespace: - description: The namespace of the source - reference, defaults to the DataVolume - namespace - type: string - required: - - kind - - name - type: object - storage: - description: Storage is the requested storage - specification - properties: - accessModes: - description: |- - AccessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - dataSource: - description: |- - This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) * An existing custom resource that implements data population (Alpha) In order to use custom resource types that implement data population, the AnyVolumeDataSource feature gate must be enabled. If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of - resource being referenced - type: string - name: - description: Name is the name of - resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - Specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. - There are two important differences between DataSource and DataSourceRef: - * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. - * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of - resource being referenced - type: string - name: - description: Name is the name of - resource being referenced - type: string - namespace: - description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. - type: string - required: - - kind - - name - type: object - resources: - description: |- - Resources represents the minimum resources the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - selector: - description: A label query over volumes - to consider for binding. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - Name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeMode: - description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: VolumeName is the binding - reference to the PersistentVolume - backing this claim. - type: string - type: object - type: object - status: - description: |- - DataVolumeTemplateDummyStatus is here simply for backwards compatibility with - a previous API. - nullable: true - type: object - required: - - spec - type: object - type: array - instancetype: - description: InstancetypeMatcher references a instancetype - that is used to fill fields in Template - properties: - inferFromVolume: - description: |- - InferFromVolume lists the name of a volume that should be used to infer or discover the instancetype - to be used through known annotations on the underlying resource. Once applied to the InstancetypeMatcher - this field is removed. - type: string - inferFromVolumeFailurePolicy: - description: |- - InferFromVolumeFailurePolicy controls what should happen on failure when inferring the instancetype. - Allowed values are: "RejectInferFromVolumeFailure" and "IgnoreInferFromVolumeFailure". - If not specified, "RejectInferFromVolumeFailure" is used by default. - type: string - kind: - description: |- - Kind specifies which instancetype resource is referenced. - Allowed values are: "VirtualMachineInstancetype" and "VirtualMachineClusterInstancetype". - If not specified, "VirtualMachineClusterInstancetype" is used by default. - type: string - name: - description: Name is the name of the VirtualMachineInstancetype - or VirtualMachineClusterInstancetype - type: string - revisionName: - description: |- - RevisionName specifies a ControllerRevision containing a specific copy of the - VirtualMachineInstancetype or VirtualMachineClusterInstancetype to be used. This is initially - captured the first time the instancetype is applied to the VirtualMachineInstance. - type: string - type: object - preference: - description: PreferenceMatcher references a set of - preference that is used to fill fields in Template - properties: - inferFromVolume: - description: |- - InferFromVolume lists the name of a volume that should be used to infer or discover the preference - to be used through known annotations on the underlying resource. Once applied to the PreferenceMatcher - this field is removed. - type: string - inferFromVolumeFailurePolicy: - description: |- - InferFromVolumeFailurePolicy controls what should happen on failure when preference the instancetype. - Allowed values are: "RejectInferFromVolumeFailure" and "IgnoreInferFromVolumeFailure". - If not specified, "RejectInferFromVolumeFailure" is used by default. - type: string - kind: - description: |- - Kind specifies which preference resource is referenced. - Allowed values are: "VirtualMachinePreference" and "VirtualMachineClusterPreference". - If not specified, "VirtualMachineClusterPreference" is used by default. - type: string - name: - description: Name is the name of the VirtualMachinePreference - or VirtualMachineClusterPreference - type: string - revisionName: - description: |- - RevisionName specifies a ControllerRevision containing a specific copy of the - VirtualMachinePreference or VirtualMachineClusterPreference to be used. This is - initially captured the first time the instancetype is applied to the VirtualMachineInstance. - type: string - type: object - runStrategy: - description: |- - Running state indicates the requested running state of the VirtualMachineInstance - mutually exclusive with Running - type: string - running: - description: |- - Running controls whether the associatied VirtualMachineInstance is created or not - Mutually exclusive with RunStrategy - type: boolean - template: - description: Template is the direct specification - of VirtualMachineInstance - properties: - metadata: - nullable: true - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: VirtualMachineInstance Spec contains - the VirtualMachineInstance specification. - properties: - accessCredentials: - description: Specifies a set of public keys - to inject into the vm guest - items: - description: |- - AccessCredential represents a credential source that can be used to - authorize remote access to the vm guest - Only one of its members may be specified. - properties: - sshPublicKey: - description: |- - SSHPublicKey represents the source and method of applying a ssh public - key into a guest virtual machine. - properties: - propagationMethod: - description: PropagationMethod represents - how the public key is injected - into the vm guest. - properties: - configDrive: - description: |- - ConfigDrivePropagation means that the ssh public keys are injected - into the VM using metadata using the configDrive cloud-init provider - type: object - noCloud: - description: |- - NoCloudPropagation means that the ssh public keys are injected - into the VM using metadata using the noCloud cloud-init provider - type: object - qemuGuestAgent: - description: |- - QemuGuestAgentAccessCredentailPropagation means ssh public keys are - dynamically injected into the vm at runtime via the qemu guest agent. - This feature requires the qemu guest agent to be running within the guest. - properties: - users: - description: |- - Users represents a list of guest users that should have the ssh public keys - added to their authorized_keys file. - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - users - type: object - type: object - source: - description: Source represents where - the public keys are pulled from - properties: - secret: - description: Secret means that - the access credential is pulled - from a kubernetes secret - properties: - secretName: - description: SecretName - represents the name of - the secret in the VMI's - namespace - type: string - required: - - secretName - type: object - type: object - required: - - propagationMethod - - source - type: object - userPassword: - description: |- - UserPassword represents the source and method for applying a guest user's - password - properties: - propagationMethod: - description: propagationMethod represents - how the user passwords are injected - into the vm guest. - properties: - qemuGuestAgent: - description: |- - QemuGuestAgentAccessCredentailPropagation means passwords are - dynamically injected into the vm at runtime via the qemu guest agent. - This feature requires the qemu guest agent to be running within the guest. - type: object - type: object - source: - description: Source represents where - the user passwords are pulled - from - properties: - secret: - description: Secret means that - the access credential is pulled - from a kubernetes secret - properties: - secretName: - description: SecretName - represents the name of - the secret in the VMI's - namespace - type: string - required: - - secretName - type: object - type: object - required: - - propagationMethod - - source - type: object - type: object - type: array - x-kubernetes-list-type: atomic - affinity: - description: If affinity is specifies, obey - all the affinity rules - properties: - nodeAffinity: - description: Describes node affinity scheduling - rules for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector - term, associated with the - corresponding weight. - properties: - matchExpressions: - description: A list of node - selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label - key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node - selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label - key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated - with matching the corresponding - nodeSelectorTerm, in the range - 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list - of node selector terms. The - terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node - selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label - key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node - selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label - key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling - rules (e.g. co-locate this pod in the - same node, zone, etc. as some other - pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all - of the matched WeightedPodAffinityTerm - fields are added per-node to find - the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod - affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label - selector requirements. - The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key - is the label - key that the - selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label - selector requirements. - The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key - is the label - key that the - selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is - the label key that - the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is - the label key that - the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity - scheduling rules (e.g. avoid putting - this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all - of the matched WeightedPodAffinityTerm - fields are added per-node to find - the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod - affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label - selector requirements. - The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key - is the label - key that the - selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label - selector requirements. - The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key - is the label - key that the - selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is - the label key that - the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions - is a list of label selector - requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is - the label key that - the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - architecture: - description: Specifies the architecture of - the vm guest you are attempting to run. - Defaults to the compiled architecture of - the KubeVirt components - type: string - dnsConfig: - description: |- - Specifies the DNS parameters of a pod. - Parameters specified here will be merged to the generated DNS - configuration based on DNSPolicy. - properties: - nameservers: - description: |- - A list of DNS name server IP addresses. - This will be appended to the base nameservers generated from DNSPolicy. - Duplicated nameservers will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - description: |- - A list of DNS resolver options. - This will be merged with the base options generated from DNSPolicy. - Duplicated entries will be removed. Resolution options given in Options - will override those that appear in the base DNSPolicy. - items: - description: PodDNSConfigOption defines - DNS resolver options of a pod. - properties: - name: - description: Required. - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - description: |- - A list of DNS search domains for host-name lookup. - This will be appended to the base search paths generated from DNSPolicy. - Duplicated search paths will be removed. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - description: |- - Set DNS policy for the pod. - Defaults to "ClusterFirst". - Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - To have DNS options set along with hostNetwork, you have to specify DNS policy - explicitly to 'ClusterFirstWithHostNet'. - type: string - domain: - description: Specification of the desired - behavior of the VirtualMachineInstance on - the host. - properties: - chassis: - description: Chassis specifies the chassis - info passed to the domain. - properties: - asset: - type: string - manufacturer: - type: string - serial: - type: string - sku: - type: string - version: - type: string - type: object - clock: - description: Clock sets the clock and - timers of the vmi. - properties: - timer: - description: Timer specifies whih - timers are attached to the vmi. - properties: - hpet: - description: HPET (High Precision - Event Timer) - multiple timers - with periodic interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup", "merge", "discard". - type: string - type: object - hyperv: - description: Hyperv (Hypervclock) - - lets guests read the host’s - wall clock time (paravirtualized). - For windows guests. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - type: object - kvm: - description: "KVM \t(KVM clock) - - lets guests read the host’s - wall clock time (paravirtualized). - For linux guests." - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - type: object - pit: - description: PIT (Programmable - Interval Timer) - a timer with - periodic interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup", "discard". - type: string - type: object - rtc: - description: RTC (Real Time Clock) - - a continuously running timer - with periodic interrupts. - properties: - present: - description: |- - Enabled set to false makes sure that the machine type or a preset can't add the timer. - Defaults to true. - type: boolean - tickPolicy: - description: |- - TickPolicy determines what happens when QEMU misses a deadline for injecting a tick to the guest. - One of "delay", "catchup". - type: string - track: - description: Track the guest - or the wall clock. - type: string - type: object - type: object - timezone: - description: |- - Timezone sets the guest clock to the specified timezone. - Zone name follows the TZ environment variable format (e.g. 'America/New_York'). - type: string - utc: - description: |- - UTC sets the guest clock to UTC on each boot. If an offset is specified, - guest changes to the clock will be kept during reboots and are not reset. - properties: - offsetSeconds: - description: |- - OffsetSeconds specifies an offset in seconds, relative to UTC. If set, - guest changes to the clock will be kept during reboots and not reset. - type: integer - type: object - type: object - x-kubernetes-preserve-unknown-fields: true - cpu: - description: CPU allow specified the detailed - CPU topology inside the vmi. - properties: - cores: - description: |- - Cores specifies the number of cores inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - dedicatedCpuPlacement: - description: |- - DedicatedCPUPlacement requests the scheduler to place the VirtualMachineInstance on a node - with enough dedicated pCPUs and pin the vCPUs to it. - type: boolean - features: - description: Features specifies the - CPU features list inside the VMI. - items: - description: CPUFeature allows specifying - a CPU feature. - properties: - name: - description: Name of the CPU - feature - type: string - policy: - description: |- - Policy is the CPU feature attribute which can have the following attributes: - force - The virtual CPU will claim the feature is supported regardless of it being supported by host CPU. - require - Guest creation will fail unless the feature is supported by the host CPU or the hypervisor is able to emulate it. - optional - The feature will be supported by virtual CPU if and only if it is supported by host CPU. - disable - The feature will not be supported by virtual CPU. - forbid - Guest creation will fail if the feature is supported by host CPU. - Defaults to require - type: string - required: - - name - type: object - type: array - isolateEmulatorThread: - description: |- - IsolateEmulatorThread requests one more dedicated pCPU to be allocated for the VMI to place - the emulator thread on it. - type: boolean - maxSockets: - description: |- - MaxSockets specifies the maximum amount of sockets that can - be hotplugged - format: int32 - type: integer - model: - description: |- - Model specifies the CPU model inside the VMI. - List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map. - It is possible to specify special cases like "host-passthrough" to get the same CPU as the node - and "host-model" to get CPU closest to the node one. - Defaults to host-model. - type: string - numa: - description: NUMA allows specifying - settings for the guest NUMA topology - properties: - guestMappingPassthrough: - description: |- - GuestMappingPassthrough will create an efficient guest topology based on host CPUs exclusively assigned to a pod. - The created topology ensures that memory and CPUs on the virtual numa nodes never cross boundaries of host numa nodes. - type: object - type: object - realtime: - description: Realtime instructs the - virt-launcher to tune the VMI for - lower latency, optional for real - time workloads - properties: - mask: - description: |- - Mask defines the vcpu mask expression that defines which vcpus are used for realtime. Format matches libvirt's expressions. - Example: "0-3,^1","0,2,3","2-3" - type: string - type: object - sockets: - description: |- - Sockets specifies the number of sockets inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - threads: - description: |- - Threads specifies the number of threads inside the vmi. - Must be a value greater or equal 1. - format: int32 - type: integer - type: object - devices: - description: Devices allows adding disks, - network interfaces, and others - properties: - autoattachGraphicsDevice: - description: |- - Whether to attach the default graphics device or not. - VNC will not be available if set to false. Defaults to true. - type: boolean - autoattachInputDevice: - description: |- - Whether to attach an Input Device. - Defaults to false. - type: boolean - autoattachMemBalloon: - description: |- - Whether to attach the Memory balloon device with default period. - Period can be adjusted in virt-config. - Defaults to true. - type: boolean - autoattachPodInterface: - description: Whether to attach a pod - network interface. Defaults to true. - type: boolean - autoattachSerialConsole: - description: |- - Whether to attach the default virtio-serial console or not. - Serial console access will not be available if set to false. Defaults to true. - type: boolean - autoattachVSOCK: - description: |- - Whether to attach the VSOCK CID to the VM or not. - VSOCK access will be available if set to true. Defaults to false. - type: boolean - blockMultiQueue: - description: |- - Whether or not to enable virtio multi-queue for block devices. - Defaults to false. - type: boolean - clientPassthrough: - description: To configure and access - client devices such as redirecting - USB - type: object - disableHotplug: - description: DisableHotplug disabled - the ability to hotplug disks. - type: boolean - disks: - description: Disks describes disks, - cdroms and luns which are connected - to the vmi. - items: - properties: - blockSize: - description: If specified, the - virtual disk will be presented - with the given block sizes. - properties: - custom: - description: CustomBlockSize - represents the desired - logical and physical block - size for a VM disk. - properties: - logical: - type: integer - physical: - type: integer - required: - - logical - - physical - type: object - matchVolume: - description: Represents - if a feature is enabled - or disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - bootOrder: - description: |- - BootOrder is an integer value > 0, used to determine ordering of boot devices. - Lower values take precedence. - Each disk or interface that has a boot order must have a unique value. - Disks without a boot order are not tried if a disk with a boot order exists. - type: integer - cache: - description: |- - Cache specifies which kvm disk cache mode should be used. - Supported values are: CacheNone, CacheWriteThrough. - type: string - cdrom: - description: Attach a volume - as a cdrom to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi. - type: string - readonly: - description: |- - ReadOnly. - Defaults to true. - type: boolean - tray: - description: |- - Tray indicates if the tray of the device is open or closed. - Allowed values are "open" and "closed". - Defaults to closed. - type: string - type: object - dedicatedIOThread: - description: |- - dedicatedIOThread indicates this disk should have an exclusive IO Thread. - Enabling this implies useIOThreads = true. - Defaults to false. - type: boolean - disk: - description: Attach a volume - as a disk to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi, usb. - type: string - pciAddress: - description: 'If specified, - the virtual disk will - be placed on the guests - pci address with the specified - PCI address. For example: - 0000:81:01.10' - type: string - readonly: - description: |- - ReadOnly. - Defaults to false. - type: boolean - type: object - errorPolicy: - description: If specified, it - can change the default error - policy (stop) for the disk - type: string - io: - description: |- - IO specifies which QEMU disk IO mode should be used. - Supported values are: native, default, threads. - type: string - lun: - description: Attach a volume - as a LUN to the vmi. - properties: - bus: - description: |- - Bus indicates the type of disk device to emulate. - supported values: virtio, sata, scsi. - type: string - readonly: - description: |- - ReadOnly. - Defaults to false. - type: boolean - reservation: - description: Reservation - indicates if the disk - needs to support the persistent - reservation for the SCSI - disk - type: boolean - type: object - name: - description: Name is the device - name - type: string - serial: - description: Serial provides - the ability to specify a serial - number for the disk device. - type: string - shareable: - description: If specified the - disk is made sharable and - multiple write from different - VMs are permitted - type: boolean - tag: - description: If specified, disk - address and its tag will be - provided to the guest via - config drive metadata - type: string - required: - - name - type: object - type: array - downwardMetrics: - description: DownwardMetrics creates - a virtio serials for exposing the - downward metrics to the vmi. - type: object - filesystems: - description: Filesystems describes - filesystem which is connected to - the vmi. - items: - properties: - name: - description: Name is the device - name - type: string - virtiofs: - description: Virtiofs is supported - type: object - required: - - name - - virtiofs - type: object - type: array - x-kubernetes-list-type: atomic - gpus: - description: Whether to attach a GPU - device to the vmi. - items: - properties: - deviceName: - type: string - name: - description: Name of the GPU - device as exposed by a device - plugin - type: string - tag: - description: If specified, the - virtual network interface - address and its tag will be - provided to the guest via - config drive - type: string - virtualGPUOptions: - properties: - display: - properties: - enabled: - description: |- - Enabled determines if a display addapter backed by a vGPU should be enabled or disabled on the guest. - Defaults to true. - type: boolean - ramFB: - description: |- - Enables a boot framebuffer, until the guest OS loads a real GPU driver - Defaults to true. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - type: object - required: - - deviceName - - name - type: object - type: array - x-kubernetes-list-type: atomic - hostDevices: - description: Whether to attach a host - device to the vmi. - items: - properties: - deviceName: - description: DeviceName is the - resource name of the host - device exposed by a device - plugin - type: string - name: - type: string - tag: - description: If specified, the - virtual network interface - address and its tag will be - provided to the guest via - config drive - type: string - required: - - deviceName - - name - type: object - type: array - x-kubernetes-list-type: atomic - inputs: - description: Inputs describe input - devices - items: - properties: - bus: - description: |- - Bus indicates the bus of input device to emulate. - Supported values: virtio, usb. - type: string - name: - description: Name is the device - name - type: string - type: - description: |- - Type indicated the type of input device. - Supported values: tablet. - type: string - required: - - name - - type - type: object - type: array - interfaces: - description: Interfaces describe network - interfaces which are added to the - vmi. - items: - properties: - acpiIndex: - description: |- - If specified, the ACPI index is used to provide network interface device naming, that is stable across changes - in PCI addresses assigned to the device. - This value is required to be unique across all devices and be between 1 and (16*1024-1). - type: integer - binding: - description: |- - Binding specifies the binding plugin that will be used to connect the interface to the guest. - It provides an alternative to InterfaceBindingMethod. - version: 1alphav1 - properties: - name: - description: |- - Name references to the binding name as denined in the kubevirt CR. - version: 1alphav1 - type: string - required: - - name - type: object - bootOrder: - description: |- - BootOrder is an integer value > 0, used to determine ordering of boot devices. - Lower values take precedence. - Each interface or disk that has a boot order must have a unique value. - Interfaces without a boot order are not tried. - type: integer - bridge: - description: InterfaceBridge - connects to a given network - via a linux bridge. - type: object - dhcpOptions: - description: If specified the - network interface will pass - additional DHCP options to - the VMI - properties: - bootFileName: - description: If specified - will pass option 67 to - interface's DHCP server - type: string - ntpServers: - description: If specified - will pass the configured - NTP server to the VM via - DHCP option 042. - items: - type: string - type: array - privateOptions: - description: 'If specified - will pass extra DHCP options - for private use, range: - 224-254' - items: - description: DHCPExtraOptions - defines Extra DHCP options - for a VM. - properties: - option: - description: |- - Option is an Integer value from 224-254 - Required. - type: integer - value: - description: |- - Value is a String value for the Option provided - Required. - type: string - required: - - option - - value - type: object - type: array - tftpServerName: - description: If specified - will pass option 66 to - interface's DHCP server - type: string - type: object - macAddress: - description: 'Interface MAC - address. For example: de:ad:00:00:be:af - or DE-AD-00-00-BE-AF.' - type: string - macvtap: - description: Deprecated, please - refer to Kubevirt user guide - for alternatives. - type: object - masquerade: - description: InterfaceMasquerade - connects to a given network - using netfilter rules to nat - the traffic. - type: object - model: - description: |- - Interface model. - One of: e1000, e1000e, ne2k_pci, pcnet, rtl8139, virtio. - Defaults to virtio. - TODO:(ihar) switch to enums once opengen-api supports them. See: https://github.com/kubernetes/kube-openapi/issues/51 - type: string - name: - description: |- - Logical name of the interface as well as a reference to the associated networks. - Must match the Name of a Network. - type: string - passt: - description: Deprecated, please - refer to Kubevirt user guide - for alternatives. - type: object - pciAddress: - description: 'If specified, - the virtual network interface - will be placed on the guests - pci address with the specified - PCI address. For example: - 0000:81:01.10' - type: string - ports: - description: List of ports to - be forwarded to the virtual - machine. - items: - description: |- - Port represents a port to expose from the virtual machine. - Default protocol TCP. - The port field is mandatory - properties: - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - port: - description: |- - Number of port to expose for the virtual machine. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - protocol: - description: |- - Protocol for port. Must be UDP or TCP. - Defaults to "TCP". - type: string - required: - - port - type: object - type: array - slirp: - description: InterfaceSlirp - connects to a given network - using QEMU user networking - mode. - type: object - sriov: - description: InterfaceSRIOV - connects to a given network - by passing-through an SR-IOV - PCI device via vfio. - type: object - state: - description: |- - State represents the requested operational state of the interface. - The (only) value supported is `absent`, expressing a request to remove the interface. - type: string - tag: - description: If specified, the - virtual network interface - address and its tag will be - provided to the guest via - config drive - type: string - required: - - name - type: object - type: array - logSerialConsole: - description: |- - Whether to log the auto-attached default serial console or not. - Serial console logs will be collect to a file and then streamed from a named `guest-console-log`. - Not relevant if autoattachSerialConsole is disabled. - Defaults to cluster wide setting on VirtualMachineOptions. - type: boolean - networkInterfaceMultiqueue: - description: If specified, virtual - network interfaces configured with - a virtio bus will also enable the - vhost multiqueue feature for network - devices. The number of queues created - depends on additional factors of - the VirtualMachineInstance, like - the number of guest CPUs. - type: boolean - rng: - description: Whether to have random - number generator from host - type: object - sound: - description: Whether to emulate a - sound device. - properties: - model: - description: |- - We only support ich9 or ac97. - If SoundDevice is not set: No sound card is emulated. - If SoundDevice is set but Model is not: ich9 - type: string - name: - description: User's defined name - for this sound device - type: string - required: - - name - type: object - tpm: - description: Whether to emulate a - TPM device. - properties: - persistent: - description: |- - Persistent indicates the state of the TPM device should be kept accross reboots - Defaults to false - type: boolean - type: object - useVirtioTransitional: - description: |- - Fall back to legacy virtio 0.9 support if virtio bus is selected on devices. - This is helpful for old machines like CentOS6 or RHEL6 which - do not understand virtio_non_transitional (virtio 1.0). - type: boolean - watchdog: - description: Watchdog describes a - watchdog device which can be added - to the vmi. - properties: - i6300esb: - description: i6300esb watchdog - device. - properties: - action: - description: |- - The action to take. Valid values are poweroff, reset, shutdown. - Defaults to reset. - type: string - type: object - name: - description: Name of the watchdog. - type: string - required: - - name - type: object - type: object - features: - description: Features like acpi, apic, - hyperv, smm. - properties: - acpi: - description: |- - ACPI enables/disables ACPI inside the guest. - Defaults to enabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - apic: - description: Defaults to the machine - type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - endOfInterrupt: - description: |- - EndOfInterrupt enables the end of interrupt notification in the guest. - Defaults to false. - type: boolean - type: object - hyperv: - description: Defaults to the machine - type setting. - properties: - evmcs: - description: |- - EVMCS Speeds up L2 vmexits, but disables other virtualization features. Requires vapic. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - frequencies: - description: |- - Frequencies improves the TSC clock source handling for Hyper-V on KVM. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - ipi: - description: |- - IPI improves performances in overcommited environments. Requires vpindex. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - reenlightenment: - description: |- - Reenlightenment enables the notifications on TSC frequency changes. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - relaxed: - description: |- - Relaxed instructs the guest OS to disable watchdog timeouts. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - reset: - description: |- - Reset enables Hyperv reboot/reset for the vmi. Requires synic. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - runtime: - description: |- - Runtime improves the time accounting to improve scheduling in the guest. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - spinlocks: - description: Spinlocks allows - to configure the spinlock retry - attempts. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - spinlocks: - description: |- - Retries indicates the number of retries. - Must be a value greater or equal 4096. - Defaults to 4096. - format: int32 - type: integer - type: object - synic: - description: |- - SyNIC enables the Synthetic Interrupt Controller. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - synictimer: - description: |- - SyNICTimer enables Synthetic Interrupt Controller Timers, reducing CPU load. - Defaults to the machine type setting. - properties: - direct: - description: Represents if - a feature is enabled or - disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - enabled: - type: boolean - type: object - tlbflush: - description: |- - TLBFlush improves performances in overcommited environments. Requires vpindex. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - vapic: - description: |- - VAPIC improves the paravirtualized handling of interrupts. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - vendorid: - description: |- - VendorID allows setting the hypervisor vendor id. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - vendorid: - description: |- - VendorID sets the hypervisor vendor id, visible to the vmi. - String up to twelve characters. - type: string - type: object - vpindex: - description: |- - VPIndex enables the Virtual Processor Index to help windows identifying virtual processors. - Defaults to the machine type setting. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - kvm: - description: Configure how KVM presence - is exposed to the guest. - properties: - hidden: - description: |- - Hide the KVM hypervisor from standard MSR based discovery. - Defaults to false - type: boolean - type: object - pvspinlock: - description: |- - Notify the guest that the host supports paravirtual spinlocks. - For older kernels this feature should be explicitly disabled. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - smm: - description: |- - SMM enables/disables System Management Mode. - TSEG not yet implemented. - properties: - enabled: - description: |- - Enabled determines if the feature should be enabled or disabled on the guest. - Defaults to true. - type: boolean - type: object - type: object - firmware: - description: Firmware. - properties: - acpi: - description: Information that can - be set in the ACPI table - properties: - slicNameRef: - description: |- - SlicNameRef should match the volume name of a secret object. The data in the secret should - be a binary blob that follows the ACPI SLIC standard, see: - https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653305(v=vs.85) - type: string - type: object - bootloader: - description: Settings to control the - bootloader that is used. - properties: - bios: - description: If set (default), - BIOS will be used. - properties: - useSerial: - description: If set, the BIOS - output will be transmitted - over serial - type: boolean - type: object - efi: - description: If set, EFI will - be used instead of BIOS. - properties: - persistent: - description: |- - If set to true, Persistent will persist the EFI NVRAM across reboots. - Defaults to false - type: boolean - secureBoot: - description: |- - If set, SecureBoot will be enabled and the OVMF roms will be swapped for - SecureBoot-enabled ones. - Requires SMM to be enabled. - Defaults to true - type: boolean - type: object - type: object - kernelBoot: - description: Settings to set the kernel - for booting. - properties: - container: - description: Container defines - the container that containes - kernel artifacts - properties: - image: - description: Image that contains - initrd / kernel files. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecret: - description: ImagePullSecret - is the name of the Docker - registry secret required - to pull the image. The secret - must already exist. - type: string - initrdPath: - description: the fully-qualified - path to the ramdisk image - in the host OS - type: string - kernelPath: - description: The fully-qualified - path to the kernel image - in the host OS - type: string - required: - - image - type: object - kernelArgs: - description: Arguments to be passed - to the kernel at boot time - type: string - type: object - serial: - description: The system-serial-number - in SMBIOS - type: string - uuid: - description: |- - UUID reported by the vmi bios. - Defaults to a random generated uid. - type: string - type: object - ioThreadsPolicy: - description: |- - Controls whether or not disks will share IOThreads. - Omitting IOThreadsPolicy disables use of IOThreads. - One of: shared, auto - type: string - launchSecurity: - description: Launch Security setting of - the vmi. - properties: - sev: - description: AMD Secure Encrypted - Virtualization (SEV). - properties: - attestation: - description: If specified, run - the attestation process for - a vmi. - type: object - dhCert: - description: Base64 encoded guest - owner's Diffie-Hellman key. - type: string - policy: - description: |- - Guest policy flags as defined in AMD SEV API specification. - Note: due to security reasons it is not allowed to enable guest debugging. Therefore NoDebug flag is not exposed to users and is always true. - properties: - encryptedState: - description: |- - SEV-ES is required. - Defaults to false. - type: boolean - type: object - session: - description: Base64 encoded session - blob. - type: string - type: object - type: object - machine: - description: Machine type. - properties: - type: - description: QEMU machine type is - the actual chipset of the VirtualMachineInstance. - type: string - type: object - memory: - description: Memory allow specifying the - VMI memory features. - properties: - guest: - anyOf: - - type: integer - - type: string - description: |- - Guest allows to specifying the amount of memory which is visible inside the Guest OS. - The Guest must lie between Requests and Limits from the resources section. - Defaults to the requested memory in the resources section if not specified. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - hugepages: - description: Hugepages allow to use - hugepages for the VirtualMachineInstance - instead of regular memory. - properties: - pageSize: - description: PageSize specifies - the hugepage size, for x86_64 - architecture valid values are - 1Gi and 2Mi. - type: string - type: object - maxGuest: - anyOf: - - type: integer - - type: string - description: |- - MaxGuest allows to specify the maximum amount of memory which is visible inside the Guest OS. - The delta between MaxGuest and Guest is the amount of memory that can be hot(un)plugged. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - resources: - description: Resources describes the Compute - Resources required by this vmi. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - Valid resource keys are "memory" and "cpu". - type: object - overcommitGuestOverhead: - description: |- - Don't ask the scheduler to take the guest-management overhead into account. Instead - put the overhead only into the container's memory limit. This can lead to crashes if - all memory is in use on a node. Defaults to false. - type: boolean - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests is a description of the initial vmi resources. - Valid resource keys are "memory" and "cpu". - type: object - type: object - required: - - devices - type: object - evictionStrategy: - description: |- - EvictionStrategy describes the strategy to follow when a node drain occurs. - The possible options are: - - "None": No action will be taken, according to the specified 'RunStrategy' the VirtualMachine will be restarted or shutdown. - - "LiveMigrate": the VirtualMachineInstance will be migrated instead of being shutdown. - - "LiveMigrateIfPossible": the same as "LiveMigrate" but only if the VirtualMachine is Live-Migratable, otherwise it will behave as "None". - - "External": the VirtualMachineInstance will be protected by a PDB and `vmi.Status.EvacuationNodeName` will be set on eviction. This is mainly useful for cluster-api-provider-kubevirt (capk) which needs a way for VMI's to be blocked from eviction, yet signal capk that eviction has been called on the VMI so the capk controller can handle tearing the VMI down. Details can be found in the commit description https://github.com/kubevirt/kubevirt/commit/c1d77face705c8b126696bac9a3ee3825f27f1fa. - type: string - hostname: - description: |- - Specifies the hostname of the vmi - If not specified, the hostname will be set to the name of the vmi, if dhcp or cloud-init is configured properly. - type: string - livenessProbe: - description: |- - Periodic probe of VirtualMachineInstance liveness. - VirtualmachineInstances will be stopped if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: |- - One and only one of the following should be specified. - Exec specifies the action to take, it will be executed on the guest through the qemu-guest-agent. - If the guest agent is not available, this probe will fail. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - guestAgentPing: - description: GuestAgentPing contacts the - qemu-guest-agent for availability checks. - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set - in the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in - HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the - HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: |- - TCPSocket specifies an action involving a TCP port. - TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook - properties: - host: - description: 'Optional: Host name - to connect to, defaults to the pod - IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - For exec probes the timeout fails the probe but does not terminate the command running on the guest. - This means a blocking command can result in an increasing load on the guest. - A small buffer will be added to the resulting workload exec probe to compensate for delays - caused by the qemu guest exec mechanism. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - networks: - description: List of networks that can be - attached to a vm's virtual interface. - items: - description: Network represents a network - type and a resource that should be connected - to the vm. - properties: - multus: - description: Represents the multus cni - network. - properties: - default: - description: |- - Select the default network and add it to the - multus-cni.io/default-network annotation. - type: boolean - networkName: - description: |- - References to a NetworkAttachmentDefinition CRD object. Format: - , /. If namespace is not - specified, VMI namespace is assumed. - type: string - required: - - networkName - type: object - name: - description: |- - Network name. - Must be a DNS_LABEL and unique within the vm. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - pod: - description: Represents the stock pod - network interface. - properties: - vmIPv6NetworkCIDR: - description: |- - IPv6 CIDR for the vm network. - Defaults to fd10:0:2::/120 if not specified. - type: string - vmNetworkCIDR: - description: |- - CIDR for vm network. - Default 10.0.2.0/24 if not specified. - type: string - type: object - required: - - name - type: object - type: array - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the vmi to fit on a node. - Selector which must match a node's labels for the vmi to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: |- - If specified, indicates the pod's priority. - If not specified, the pod priority will be default or zero if there is no - default. - type: string - readinessProbe: - description: |- - Periodic probe of VirtualMachineInstance service readiness. - VirtualmachineInstances will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: |- - One and only one of the following should be specified. - Exec specifies the action to take, it will be executed on the guest through the qemu-guest-agent. - If the guest agent is not available, this probe will fail. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - guestAgentPing: - description: GuestAgentPing contacts the - qemu-guest-agent for availability checks. - type: object - httpGet: - description: HTTPGet specifies the http - request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set - in the request. HTTP allows repeated - headers. - items: - description: HTTPHeader describes - a custom header to be used in - HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field - value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the - HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the VirtualMachineInstance has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: |- - TCPSocket specifies an action involving a TCP port. - TCP hooks not yet supported - TODO: implement a realistic TCP lifecycle hook - properties: - host: - description: 'Optional: Host name - to connect to, defaults to the pod - IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - For exec probes the timeout fails the probe but does not terminate the command running on the guest. - This means a blocking command can result in an increasing load on the guest. - A small buffer will be added to the resulting workload exec probe to compensate for delays - caused by the qemu guest exec mechanism. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - schedulerName: - description: |- - If specified, the VMI will be dispatched by specified scheduler. - If not specified, the VMI will be dispatched by default scheduler. - type: string - startStrategy: - description: StartStrategy can be set to "Paused" - if Virtual Machine should be started in - paused state. - type: string - subdomain: - description: |- - If specified, the fully qualified vmi hostname will be "...svc.". - If not specified, the vmi will not have a domainname at all. The DNS entry will resolve to the vmi, - no matter if the vmi itself can pick up a hostname. - type: string - terminationGracePeriodSeconds: - description: Grace period observed after signalling - a VirtualMachineInstance to stop after which - the VirtualMachineInstance is force terminated. - format: int64 - type: integer - tolerations: - description: If toleration is specified, obey - all the toleration rules. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: |- - TopologySpreadConstraints describes how a group of VMIs will be spread across a given topology - domains. K8s scheduler will schedule VMI pods in a way which abides by the constraints. - items: - description: TopologySpreadConstraint specifies - how to spread matching pods among the - given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - - If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - - If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - description: List of volumes that can be mounted - by disks belonging to the vmi. - items: - description: Volume represents a named volume - in a vmi. - properties: - cloudInitConfigDrive: - description: |- - CloudInitConfigDrive represents a cloud-init Config Drive user-data source. - The Config Drive data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. - More info: https://cloudinit.readthedocs.io/en/latest/topics/datasources/configdrive.html - properties: - networkData: - description: NetworkData contains - config drive inline cloud-init - networkdata. - type: string - networkDataBase64: - description: NetworkDataBase64 contains - config drive cloud-init networkdata - as a base64 encoded string. - type: string - networkDataSecretRef: - description: NetworkDataSecretRef - references a k8s secret that contains - config drive networkdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secretRef: - description: UserDataSecretRef references - a k8s secret that contains config - drive userdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - userData: - description: UserData contains config - drive inline cloud-init userdata. - type: string - userDataBase64: - description: UserDataBase64 contains - config drive cloud-init userdata - as a base64 encoded string. - type: string - type: object - cloudInitNoCloud: - description: |- - CloudInitNoCloud represents a cloud-init NoCloud user-data source. - The NoCloud data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. - More info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html - properties: - networkData: - description: NetworkData contains - NoCloud inline cloud-init networkdata. - type: string - networkDataBase64: - description: NetworkDataBase64 contains - NoCloud cloud-init networkdata - as a base64 encoded string. - type: string - networkDataSecretRef: - description: NetworkDataSecretRef - references a k8s secret that contains - NoCloud networkdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secretRef: - description: UserDataSecretRef references - a k8s secret that contains NoCloud - userdata. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - userData: - description: UserData contains NoCloud - inline cloud-init userdata. - type: string - userDataBase64: - description: UserDataBase64 contains - NoCloud cloud-init userdata as - a base64 encoded string. - type: string - type: object - configMap: - description: |- - ConfigMapSource represents a reference to a ConfigMap in the same namespace. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - optional: - description: Specify whether the - ConfigMap or it's keys must be - defined - type: boolean - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - x-kubernetes-map-type: atomic - containerDisk: - description: |- - ContainerDisk references a docker image, embedding a qcow or raw disk. - More info: https://kubevirt.gitbooks.io/user-guide/registry-disk.html - properties: - image: - description: Image is the name of - the image with the embedded disk. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecret: - description: ImagePullSecret is - the name of the Docker registry - secret required to pull the image. - The secret must already exist. - type: string - path: - description: Path defines the path - to disk file in the container - type: string - required: - - image - type: object - dataVolume: - description: |- - DataVolume represents the dynamic creation a PVC for this volume as well as - the process of populating that PVC with a disk image. - properties: - hotpluggable: - description: Hotpluggable indicates - whether the volume can be hotplugged - and hotunplugged. - type: boolean - name: - description: |- - Name of both the DataVolume and the PVC in the same namespace. - After PVC population the DataVolume is garbage collected by default. - type: string - required: - - name - type: object - downwardAPI: - description: DownwardAPI represents - downward API about the pod that should - populate this volume - properties: - fields: - description: Fields is a list of - downward API volume file - items: - description: DownwardAPIVolumeFile - represents information to create - the file containing the pod - field - properties: - fieldRef: - description: 'Required: Selects - a field of the pod: only - annotations, labels, name, - namespace and uid are supported.' - properties: - apiVersion: - description: Version of - the schema the FieldPath - is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the - field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: 'Required: Path - is the relative path name - of the file to be created. - Must not be absolute or - contain the ''..'' path. - Must be utf-8 encoded. The - first item of the relative - path must not start with - ''..''' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - properties: - containerName: - description: 'Container - name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies - the output format of - the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: - resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - downwardMetrics: - description: |- - DownwardMetrics adds a very small disk to VMIs which contains a limited view of host and guest - metrics. The disk content is compatible with vhostmd (https://github.com/vhostmd/vhostmd) and vm-dump-metrics. - type: object - emptyDisk: - description: |- - EmptyDisk represents a temporary disk which shares the vmis lifecycle. - More info: https://kubevirt.gitbooks.io/user-guide/disks-and-volumes.html - properties: - capacity: - anyOf: - - type: integer - - type: string - description: Capacity of the sparse - disk. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - required: - - capacity - type: object - ephemeral: - description: Ephemeral is a special - volume source that "wraps" specified - source and provides copy-on-write - image on top of it. - properties: - persistentVolumeClaim: - description: |- - PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. - Directly attached to the vmi via qemu. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - type: object - hostDisk: - description: HostDisk represents a disk - created on the cluster level - properties: - capacity: - anyOf: - - type: integer - - type: string - description: Capacity of the sparse - disk - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - path: - description: The path to HostDisk - image located on the cluster - type: string - shared: - description: Shared indicate whether - the path is shared between nodes - type: boolean - type: - description: |- - Contains information if disk.img exists or should be created - allowed options are 'Disk' and 'DiskOrCreate' - type: string - required: - - path - - type - type: object - memoryDump: - description: MemoryDump is attached - to the virt launcher and is populated - with a memory dump of the vmi - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - hotpluggable: - description: Hotpluggable indicates - whether the volume can be hotplugged - and hotunplugged. - type: boolean - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - name: - description: |- - Volume's name. - Must be a DNS_LABEL and unique within the vmi. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - persistentVolumeClaim: - description: |- - PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. - Directly attached to the vmi via qemu. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - properties: - claimName: - description: |- - claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - type: string - hotpluggable: - description: Hotpluggable indicates - whether the volume can be hotplugged - and hotunplugged. - type: boolean - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - secret: - description: |- - SecretVolumeSource represents a reference to a secret data in the same namespace. - More info: https://kubernetes.io/docs/concepts/configuration/secret/ - properties: - optional: - description: Specify whether the - Secret or it's keys must be defined - type: boolean - secretName: - description: |- - Name of the secret in the pod's namespace to use. - More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - type: string - volumeLabel: - description: |- - The volume label of the resulting disk inside the VMI. - Different bootstrapping mechanisms require different values. - Typical values are "cidata" (cloud-init), "config-2" (cloud-init) or "OEMDRV" (kickstart). - type: string - type: object - serviceAccount: - description: |- - ServiceAccountVolumeSource represents a reference to a service account. - There can only be one volume of this type! - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - properties: - serviceAccountName: - description: |- - Name of the service account in the pod's namespace to use. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - type: string - type: object - sysprep: - description: Represents a Sysprep volume - source. - properties: - configMap: - description: ConfigMap references - a ConfigMap that contains Sysprep - answer file named autounattend.xml - that should be attached as disk - of CDROM type. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - secret: - description: Secret references a - k8s Secret that contains Sysprep - answer file named autounattend.xml - that should be attached as disk - of CDROM type. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - required: - - domain - type: object - type: object - required: - - template - type: object - type: object - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-machinedeployments.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-machinedeployments.cluster.x-k8s.io.yaml deleted file mode 100644 index ca97a6558..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-machinedeployments.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,564 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: machinedeployments.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: MachineDeployment - listKind: MachineDeploymentList - plural: machinedeployments - shortNames: - - md - singular: machinedeployment - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Total number of machines desired by this MachineDeployment - jsonPath: .spec.replicas - name: Desired - priority: 10 - type: integer - - description: Total number of non-terminated machines targeted by this MachineDeployment - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Total number of ready machines targeted by this MachineDeployment - jsonPath: .status.readyReplicas - name: Ready - type: integer - - description: Total number of non-terminated machines targeted by this deployment - that have the desired template spec - jsonPath: .status.updatedReplicas - name: Updated - type: integer - - description: Total number of unavailable machines targeted by this MachineDeployment - jsonPath: .status.unavailableReplicas - name: Unavailable - type: integer - - description: MachineDeployment status such as ScalingUp/ScalingDown/Running/Failed/Unknown - jsonPath: .status.phase - name: Phase - type: string - - description: Time duration since creation of MachineDeployment - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Kubernetes version associated with this MachineDeployment - jsonPath: .spec.template.spec.version - name: Version - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: MachineDeployment is the Schema for the machinedeployments API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MachineDeploymentSpec defines the desired state of MachineDeployment. - properties: - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - minReadySeconds: - description: |- - MinReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available. - Defaults to 0 (machine will be considered available as soon as the Node is ready) - format: int32 - type: integer - paused: - description: Indicates that the deployment is paused. - type: boolean - progressDeadlineSeconds: - description: |- - The maximum time in seconds for a deployment to make progress before it - is considered to be failed. The deployment controller will continue to - process failed deployments and a condition with a ProgressDeadlineExceeded - reason will be surfaced in the deployment status. Note that progress will - not be estimated during the time a deployment is paused. Defaults to 600s. - format: int32 - type: integer - replicas: - description: |- - Number of desired machines. - This is a pointer to distinguish between explicit zero and not specified. - - - Defaults to: - * if the Kubernetes autoscaler min size and max size annotations are set: - - if it's a new MachineDeployment, use min size - - if the replicas field of the old MachineDeployment is < min size, use min size - - if the replicas field of the old MachineDeployment is > max size, use max size - - if the replicas field of the old MachineDeployment is in the (min size, max size) range, keep the value from the oldMD - * otherwise use 1 - Note: Defaulting will be run whenever the replicas field is not set: - * A new MachineDeployment is created with replicas not set. - * On an existing MachineDeployment the replicas field was first set and is now unset. - Those cases are especially relevant for the following Kubernetes autoscaler use cases: - * A new MachineDeployment is created and replicas should be managed by the autoscaler - * An existing MachineDeployment which initially wasn't controlled by the autoscaler - should be later controlled by the autoscaler - format: int32 - type: integer - revisionHistoryLimit: - description: |- - The number of old MachineSets to retain to allow rollback. - This is a pointer to distinguish between explicit zero and not specified. - Defaults to 1. - format: int32 - type: integer - rolloutAfter: - description: |- - RolloutAfter is a field to indicate a rollout should be performed - after the specified time even if no changes have been made to the - MachineDeployment. - Example: In the YAML the time can be specified in the RFC3339 format. - To specify the rolloutAfter target as March 9, 2023, at 9 am UTC - use "2023-03-09T09:00:00Z". - format: date-time - type: string - selector: - description: |- - Label selector for machines. Existing MachineSets whose machines are - selected by this will be the ones affected by this deployment. - It must match the machine template's labels. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - strategy: - description: |- - The deployment strategy to use to replace existing machines with - new ones. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if - MachineDeploymentStrategyType = RollingUpdate. - properties: - deletePolicy: - description: |- - DeletePolicy defines the policy used by the MachineDeployment to identify nodes to delete when downscaling. - Valid values are "Random, "Newest", "Oldest" - When no value is supplied, the default DeletePolicy of MachineSet is used - enum: - - Random - - Newest - - Oldest - type: string - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be scheduled above the - desired number of machines. - Value can be an absolute number (ex: 5) or a percentage of - desired machines (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Defaults to 1. - Example: when this is set to 30%, the new MachineSet can be scaled - up immediately when the rolling update starts, such that the total - number of old and new machines do not exceed 130% of desired - machines. Once old machines have been killed, new MachineSet can - be scaled up further, ensuring that total number of machines running - at any time during the update is at most 130% of desired machines. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired - machines (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Defaults to 0. - Example: when this is set to 30%, the old MachineSet can be scaled - down to 70% of desired machines immediately when the rolling update - starts. Once new machines are ready, old MachineSet can be scaled - down further, followed by scaling up the new MachineSet, ensuring - that the total number of machines available at all times - during the update is at least 70% of desired machines. - x-kubernetes-int-or-string: true - type: object - type: - description: |- - Type of deployment. Allowed values are RollingUpdate and OnDelete. - The default is RollingUpdate. - enum: - - RollingUpdate - - OnDelete - type: string - type: object - template: - description: Template describes the machines that will be created. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: |- - Specification of the desired behavior of the machine. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - bootstrap: - description: |- - Bootstrap is a reference to a local struct which encapsulates - fields to configure the Machine’s bootstrapping mechanism. - properties: - configRef: - description: |- - ConfigRef is a reference to a bootstrap provider-specific resource - that holds configuration details. The reference is optional to - allow users/operators to specify Bootstrap.DataSecretName without - the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: |- - DataSecretName is the name of the secret that stores the bootstrap data script. - If nil, the Machine should remain in the Pending state. - type: string - type: object - clusterName: - description: ClusterName is the name of the Cluster this object - belongs to. - minLength: 1 - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machine will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - type: string - infrastructureRef: - description: |- - InfrastructureRef is a required reference to a custom resource - offered by an infrastructure provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - providerID: - description: |- - ProviderID is the identification ID of the machine provided by the provider. - This field must match the provider ID as seen on the node object corresponding to this machine. - This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler - with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out - machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a - generic out-of-tree provider for autoscaler, this field is required by autoscaler to be - able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver - and then a comparison is done to find out unregistered machines and are marked for delete. - This field will be set by the actuators and consumed by higher level entities like autoscaler that will - be interfacing with cluster-api as generic provider. - type: string - version: - description: |- - Version defines the desired Kubernetes version. - This field is meant to be optionally used by bootstrap providers. - type: string - required: - - bootstrap - - clusterName - - infrastructureRef - type: object - type: object - required: - - clusterName - - selector - - template - type: object - status: - description: MachineDeploymentStatus defines the observed state of MachineDeployment. - properties: - availableReplicas: - description: |- - Total number of available machines (ready for at least minReadySeconds) - targeted by this deployment. - format: int32 - type: integer - conditions: - description: Conditions defines current service state of the MachineDeployment. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - observedGeneration: - description: The generation observed by the deployment controller. - format: int64 - type: integer - phase: - description: Phase represents the current phase of a MachineDeployment - (ScalingUp, ScalingDown, Running, Failed, or Unknown). - type: string - readyReplicas: - description: Total number of ready machines targeted by this deployment. - format: int32 - type: integer - replicas: - description: |- - Total number of non-terminated machines targeted by this deployment - (their labels match the selector). - format: int32 - type: integer - selector: - description: |- - Selector is the same as the label selector but in the string format to avoid introspection - by clients. The string will be in the same format as the query-param syntax. - More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors - type: string - unavailableReplicas: - description: |- - Total number of unavailable machines targeted by this deployment. - This is the total number of machines that are still required for - the deployment to have 100% available capacity. They may either - be machines that are running but not yet available or machines - that still have not been created. - format: int32 - type: integer - updatedReplicas: - description: |- - Total number of non-terminated machines targeted by this deployment - that have the desired template spec. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.selector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-machinehealthchecks.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-machinehealthchecks.cluster.x-k8s.io.yaml deleted file mode 100644 index 1b51cbc48..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-machinehealthchecks.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,316 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: machinehealthchecks.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: MachineHealthCheck - listKind: MachineHealthCheckList - plural: machinehealthchecks - shortNames: - - mhc - - mhcs - singular: machinehealthcheck - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Number of machines currently monitored - jsonPath: .status.expectedMachines - name: ExpectedMachines - type: integer - - description: Maximum number of unhealthy machines allowed - jsonPath: .spec.maxUnhealthy - name: MaxUnhealthy - type: string - - description: Current observed healthy machines - jsonPath: .status.currentHealthy - name: CurrentHealthy - type: integer - - description: Time duration since creation of MachineHealthCheck - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: MachineHealthCheck is the Schema for the machinehealthchecks - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Specification of machine health check policy - properties: - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - maxUnhealthy: - anyOf: - - type: integer - - type: string - description: |- - Any further remediation is only allowed if at most "MaxUnhealthy" machines selected by - "selector" are not healthy. - x-kubernetes-int-or-string: true - nodeStartupTimeout: - description: |- - Machines older than this duration without a node will be considered to have - failed and will be remediated. - If not set, this value is defaulted to 10 minutes. - If you wish to disable this feature, set the value explicitly to 0. - type: string - remediationTemplate: - description: |- - RemediationTemplate is a reference to a remediation template - provided by an infrastructure provider. - - - This field is completely optional, when filled, the MachineHealthCheck controller - creates a new object from the template referenced and hands off remediation of the machine to - a controller that lives outside of Cluster API. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - selector: - description: Label selector to match machines whose health will be - exercised - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - unhealthyConditions: - description: |- - UnhealthyConditions contains a list of the conditions that determine - whether a node is considered unhealthy. The conditions are combined in a - logical OR, i.e. if any of the conditions is met, the node is unhealthy. - items: - description: |- - UnhealthyCondition represents a Node condition type and value with a timeout - specified as a duration. When the named condition has been in the given - status for at least the timeout value, a node is considered unhealthy. - properties: - status: - minLength: 1 - type: string - timeout: - type: string - type: - minLength: 1 - type: string - required: - - status - - timeout - - type - type: object - minItems: 1 - type: array - unhealthyRange: - description: |- - Any further remediation is only allowed if the number of machines selected by "selector" as not healthy - is within the range of "UnhealthyRange". Takes precedence over MaxUnhealthy. - Eg. "[3-5]" - This means that remediation will be allowed only when: - (a) there are at least 3 unhealthy machines (and) - (b) there are at most 5 unhealthy machines - pattern: ^\[[0-9]+-[0-9]+\]$ - type: string - required: - - clusterName - - selector - - unhealthyConditions - type: object - status: - description: Most recently observed status of MachineHealthCheck resource - properties: - conditions: - description: Conditions defines current service state of the MachineHealthCheck. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - currentHealthy: - description: total number of healthy machines counted by this machine - health check - format: int32 - minimum: 0 - type: integer - expectedMachines: - description: total number of machines counted by this machine health - check - format: int32 - minimum: 0 - type: integer - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - remediationsAllowed: - description: |- - RemediationsAllowed is the number of further remediations allowed by this machine health check before - maxUnhealthy short circuiting will be applied - format: int32 - minimum: 0 - type: integer - targets: - description: Targets shows the current list of machines the machine - health check is watching - items: - type: string - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-machinepools.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-machinepools.cluster.x-k8s.io.yaml deleted file mode 100644 index a3457b488..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-machinepools.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,476 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: machinepools.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: MachinePool - listKind: MachinePoolList - plural: machinepools - shortNames: - - mp - singular: machinepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Total number of machines desired by this MachinePool - jsonPath: .spec.replicas - name: Desired - priority: 10 - type: integer - - description: MachinePool replicas count - jsonPath: .status.replicas - name: Replicas - type: string - - description: MachinePool status such as Terminating/Pending/Provisioning/Running/Failed - etc - jsonPath: .status.phase - name: Phase - type: string - - description: Time duration since creation of MachinePool - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Kubernetes version associated with this MachinePool - jsonPath: .spec.template.spec.version - name: Version - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: MachinePool is the Schema for the machinepools API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MachinePoolSpec defines the desired state of MachinePool. - properties: - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - failureDomains: - description: FailureDomains is the list of failure domains this MachinePool - should be attached to. - items: - type: string - type: array - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine instances should - be ready. - Defaults to 0 (machine instance will be considered available as soon as it - is ready) - NOTE: No logic is implemented for this field and it currently has no behaviour. - format: int32 - type: integer - providerIDList: - description: |- - ProviderIDList are the identification IDs of machine instances provided by the provider. - This field must match the provider IDs as seen on the node objects corresponding to a machine pool's machine instances. - items: - type: string - type: array - replicas: - description: |- - Number of desired machines. Defaults to 1. - This is a pointer to distinguish between explicit zero and not specified. - format: int32 - type: integer - template: - description: Template describes the machines that will be created. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: |- - Specification of the desired behavior of the machine. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - bootstrap: - description: |- - Bootstrap is a reference to a local struct which encapsulates - fields to configure the Machine’s bootstrapping mechanism. - properties: - configRef: - description: |- - ConfigRef is a reference to a bootstrap provider-specific resource - that holds configuration details. The reference is optional to - allow users/operators to specify Bootstrap.DataSecretName without - the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: |- - DataSecretName is the name of the secret that stores the bootstrap data script. - If nil, the Machine should remain in the Pending state. - type: string - type: object - clusterName: - description: ClusterName is the name of the Cluster this object - belongs to. - minLength: 1 - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machine will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - type: string - infrastructureRef: - description: |- - InfrastructureRef is a required reference to a custom resource - offered by an infrastructure provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - providerID: - description: |- - ProviderID is the identification ID of the machine provided by the provider. - This field must match the provider ID as seen on the node object corresponding to this machine. - This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler - with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out - machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a - generic out-of-tree provider for autoscaler, this field is required by autoscaler to be - able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver - and then a comparison is done to find out unregistered machines and are marked for delete. - This field will be set by the actuators and consumed by higher level entities like autoscaler that will - be interfacing with cluster-api as generic provider. - type: string - version: - description: |- - Version defines the desired Kubernetes version. - This field is meant to be optionally used by bootstrap providers. - type: string - required: - - bootstrap - - clusterName - - infrastructureRef - type: object - type: object - required: - - clusterName - - template - type: object - status: - description: MachinePoolStatus defines the observed state of MachinePool. - properties: - availableReplicas: - description: The number of available replicas (ready for at least - minReadySeconds) for this MachinePool. - format: int32 - type: integer - bootstrapReady: - description: BootstrapReady is the state of the bootstrap provider. - type: boolean - conditions: - description: Conditions define the current service state of the MachinePool. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage indicates that there is a problem reconciling the state, - and will be set to a descriptive error message. - type: string - failureReason: - description: |- - FailureReason indicates that there is a problem reconciling the state, and - will be set to a token value suitable for programmatic interpretation. - type: string - infrastructureReady: - description: InfrastructureReady is the state of the infrastructure - provider. - type: boolean - nodeRefs: - description: NodeRefs will point to the corresponding Nodes if it - they exist. - items: - description: |- - ObjectReference contains enough information to let you inspect or modify the referred object. - --- - New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. - 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. - 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular - restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". - Those cannot be well described when embedded. - 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. - 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity - during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple - and the version of the actual struct is irrelevant. - 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type - will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. - - - Instead of using this type, create a locally provided and used type that is well-focused on your reference. - For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - type: array - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - phase: - description: |- - Phase represents the current phase of cluster actuation. - E.g. Pending, Running, Terminating, Failed etc. - type: string - readyReplicas: - description: The number of ready replicas for this MachinePool. A - machine is considered ready when the node has been created and is - "Ready". - format: int32 - type: integer - replicas: - description: Replicas is the most recently observed number of replicas. - format: int32 - type: integer - unavailableReplicas: - description: |- - Total number of unavailable machine instances targeted by this machine pool. - This is the total number of machine instances that are still required for - the machine pool to have 100% available capacity. They may either - be machine instances that are running but not yet available or machine instances - that still have not been created. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - scale: - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-machines.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-machines.cluster.x-k8s.io.yaml deleted file mode 100644 index d452d9639..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-machines.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,475 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: machines.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: Machine - listKind: MachineList - plural: machines - shortNames: - - ma - singular: machine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Node name associated with this machine - jsonPath: .status.nodeRef.name - name: NodeName - type: string - - description: Provider ID - jsonPath: .spec.providerID - name: ProviderID - type: string - - description: Machine status such as Terminating/Pending/Running/Failed etc - jsonPath: .status.phase - name: Phase - type: string - - description: Time duration since creation of Machine - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Kubernetes version associated with this Machine - jsonPath: .spec.version - name: Version - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: Machine is the Schema for the machines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MachineSpec defines the desired state of Machine. - properties: - bootstrap: - description: |- - Bootstrap is a reference to a local struct which encapsulates - fields to configure the Machine’s bootstrapping mechanism. - properties: - configRef: - description: |- - ConfigRef is a reference to a bootstrap provider-specific resource - that holds configuration details. The reference is optional to - allow users/operators to specify Bootstrap.DataSecretName without - the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: |- - DataSecretName is the name of the secret that stores the bootstrap data script. - If nil, the Machine should remain in the Pending state. - type: string - type: object - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machine will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - type: string - infrastructureRef: - description: |- - InfrastructureRef is a required reference to a custom resource - offered by an infrastructure provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - providerID: - description: |- - ProviderID is the identification ID of the machine provided by the provider. - This field must match the provider ID as seen on the node object corresponding to this machine. - This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler - with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out - machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a - generic out-of-tree provider for autoscaler, this field is required by autoscaler to be - able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver - and then a comparison is done to find out unregistered machines and are marked for delete. - This field will be set by the actuators and consumed by higher level entities like autoscaler that will - be interfacing with cluster-api as generic provider. - type: string - version: - description: |- - Version defines the desired Kubernetes version. - This field is meant to be optionally used by bootstrap providers. - type: string - required: - - bootstrap - - clusterName - - infrastructureRef - type: object - status: - description: MachineStatus defines the observed state of Machine. - properties: - addresses: - description: |- - Addresses is a list of addresses assigned to the machine. - This field is copied from the infrastructure provider reference. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - bootstrapReady: - description: BootstrapReady is the state of the bootstrap provider. - type: boolean - certificatesExpiryDate: - description: |- - CertificatesExpiryDate is the expiry date of the machine certificates. - This value is only set for control plane machines. - format: date-time - type: string - conditions: - description: Conditions defines current service state of the Machine. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the Machine and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - infrastructureReady: - description: InfrastructureReady is the state of the infrastructure - provider. - type: boolean - lastUpdated: - description: LastUpdated identifies when the phase of the Machine - last transitioned. - format: date-time - type: string - nodeInfo: - description: |- - NodeInfo is a set of ids/uuids to uniquely identify the node. - More info: https://kubernetes.io/docs/concepts/nodes/node/#info - properties: - architecture: - description: The Architecture reported by the node - type: string - bootID: - description: Boot ID reported by the node. - type: string - containerRuntimeVersion: - description: ContainerRuntime Version reported by the node through - runtime remote API (e.g. containerd://1.4.2). - type: string - kernelVersion: - description: Kernel Version reported by the node from 'uname -r' - (e.g. 3.16.0-0.bpo.4-amd64). - type: string - kubeProxyVersion: - description: KubeProxy Version reported by the node. - type: string - kubeletVersion: - description: Kubelet Version reported by the node. - type: string - machineID: - description: |- - MachineID reported by the node. For unique machine identification - in the cluster this field is preferred. Learn more from man(5) - machine-id: http://man7.org/linux/man-pages/man5/machine-id.5.html - type: string - operatingSystem: - description: The Operating System reported by the node - type: string - osImage: - description: OS Image reported by the node from /etc/os-release - (e.g. Debian GNU/Linux 7 (wheezy)). - type: string - systemUUID: - description: |- - SystemUUID reported by the node. For unique machine identification - MachineID is preferred. This field is specific to Red Hat hosts - https://access.redhat.com/documentation/en-us/red_hat_subscription_management/1/html/rhsm/uuid - type: string - required: - - architecture - - bootID - - containerRuntimeVersion - - kernelVersion - - kubeProxyVersion - - kubeletVersion - - machineID - - operatingSystem - - osImage - - systemUUID - type: object - nodeRef: - description: NodeRef will point to the corresponding Node if it exists. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - phase: - description: |- - Phase represents the current phase of machine actuation. - E.g. Pending, Running, Terminating, Failed etc. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-machinesets.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-machinesets.cluster.x-k8s.io.yaml deleted file mode 100644 index 395db9ebb..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-machinesets.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,481 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: machinesets.cluster.x-k8s.io -spec: - group: cluster.x-k8s.io - names: - categories: - - cluster-api - kind: MachineSet - listKind: MachineSetList - plural: machinesets - shortNames: - - ms - singular: machineset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Total number of machines desired by this machineset - jsonPath: .spec.replicas - name: Desired - priority: 10 - type: integer - - description: Total number of non-terminated machines targeted by this machineset - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Total number of ready machines targeted by this machineset. - jsonPath: .status.readyReplicas - name: Ready - type: integer - - description: Total number of available machines (ready for at least minReadySeconds) - jsonPath: .status.availableReplicas - name: Available - type: integer - - description: Time duration since creation of MachineSet - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Kubernetes version associated with this MachineSet - jsonPath: .spec.template.spec.version - name: Version - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: MachineSet is the Schema for the machinesets API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MachineSetSpec defines the desired state of MachineSet. - properties: - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - deletePolicy: - description: |- - DeletePolicy defines the policy used to identify nodes to delete when downscaling. - Defaults to "Random". Valid values are "Random, "Newest", "Oldest" - enum: - - Random - - Newest - - Oldest - type: string - minReadySeconds: - description: |- - MinReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available. - Defaults to 0 (machine will be considered available as soon as the Node is ready) - format: int32 - type: integer - replicas: - description: |- - Replicas is the number of desired replicas. - This is a pointer to distinguish between explicit zero and unspecified. - - - Defaults to: - * if the Kubernetes autoscaler min size and max size annotations are set: - - if it's a new MachineSet, use min size - - if the replicas field of the old MachineSet is < min size, use min size - - if the replicas field of the old MachineSet is > max size, use max size - - if the replicas field of the old MachineSet is in the (min size, max size) range, keep the value from the oldMS - * otherwise use 1 - Note: Defaulting will be run whenever the replicas field is not set: - * A new MachineSet is created with replicas not set. - * On an existing MachineSet the replicas field was first set and is now unset. - Those cases are especially relevant for the following Kubernetes autoscaler use cases: - * A new MachineSet is created and replicas should be managed by the autoscaler - * An existing MachineSet which initially wasn't controlled by the autoscaler - should be later controlled by the autoscaler - format: int32 - type: integer - selector: - description: |- - Selector is a label query over machines that should match the replica count. - Label keys and values that must match in order to be controlled by this MachineSet. - It must match the machine template's labels. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - template: - description: |- - Template is the object that describes the machine that will be created if - insufficient replicas are detected. - Object references to custom resources are treated as templates. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - properties: - annotations: - additionalProperties: - type: string - description: |- - Annotations is an unstructured key value map stored with a resource that may be - set by external tools to store and retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations - type: object - labels: - additionalProperties: - type: string - description: |- - Map of string keys and values that can be used to organize and categorize - (scope and select) objects. May match selectors of replication controllers - and services. - More info: http://kubernetes.io/docs/user-guide/labels - type: object - type: object - spec: - description: |- - Specification of the desired behavior of the machine. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - bootstrap: - description: |- - Bootstrap is a reference to a local struct which encapsulates - fields to configure the Machine’s bootstrapping mechanism. - properties: - configRef: - description: |- - ConfigRef is a reference to a bootstrap provider-specific resource - that holds configuration details. The reference is optional to - allow users/operators to specify Bootstrap.DataSecretName without - the need of a controller. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - dataSecretName: - description: |- - DataSecretName is the name of the secret that stores the bootstrap data script. - If nil, the Machine should remain in the Pending state. - type: string - type: object - clusterName: - description: ClusterName is the name of the Cluster this object - belongs to. - minLength: 1 - type: string - failureDomain: - description: |- - FailureDomain is the failure domain the machine will be created in. - Must match a key in the FailureDomains map stored on the cluster object. - type: string - infrastructureRef: - description: |- - InfrastructureRef is a required reference to a custom resource - offered by an infrastructure provider. - properties: - apiVersion: - description: API version of the referent. - type: string - fieldPath: - description: |- - If referring to a piece of an object instead of an entire object, this string - should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - For example, if the object reference is to a container within a pod, this would take on a value like: - "spec.containers{name}" (where "name" refers to the name of the container that triggered - the event) or if no container name is specified "spec.containers[2]" (container with - index 2 in this pod). This syntax is chosen only to have some well-defined way of - referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. - type: string - kind: - description: |- - Kind of the referent. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - namespace: - description: |- - Namespace of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - type: string - resourceVersion: - description: |- - Specific resourceVersion to which this reference is made, if any. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency - type: string - uid: - description: |- - UID of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - type: string - type: object - x-kubernetes-map-type: atomic - nodeDeletionTimeout: - description: |- - NodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine - hosts after the Machine is marked for deletion. A duration of 0 will retry deletion indefinitely. - Defaults to 10 seconds. - type: string - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - type: string - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes - to be detached. The default value is 0, meaning that the volumes can be detached without any time limitations. - type: string - providerID: - description: |- - ProviderID is the identification ID of the machine provided by the provider. - This field must match the provider ID as seen on the node object corresponding to this machine. - This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler - with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out - machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a - generic out-of-tree provider for autoscaler, this field is required by autoscaler to be - able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver - and then a comparison is done to find out unregistered machines and are marked for delete. - This field will be set by the actuators and consumed by higher level entities like autoscaler that will - be interfacing with cluster-api as generic provider. - type: string - version: - description: |- - Version defines the desired Kubernetes version. - This field is meant to be optionally used by bootstrap providers. - type: string - required: - - bootstrap - - clusterName - - infrastructureRef - type: object - type: object - required: - - clusterName - - selector - type: object - status: - description: MachineSetStatus defines the observed state of MachineSet. - properties: - availableReplicas: - description: The number of available replicas (ready for at least - minReadySeconds) for this MachineSet. - format: int32 - type: integer - conditions: - description: Conditions defines current service state of the MachineSet. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - type: string - failureReason: - description: |- - In the event that there is a terminal problem reconciling the - replicas, both FailureReason and FailureMessage will be set. FailureReason - will be populated with a succinct value suitable for machine - interpretation, while FailureMessage will contain a more verbose - string suitable for logging and human consumption. - - - These fields should not be set for transitive errors that a - controller faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the MachineTemplate's spec or the configuration of - the machine controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the machine controller, or the - responsible machine controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the MachineSet object and/or logged in the - controller's output. - type: string - fullyLabeledReplicas: - description: The number of replicas that have labels matching the - labels of the machine template of the MachineSet. - format: int32 - type: integer - observedGeneration: - description: ObservedGeneration reflects the generation of the most - recently observed MachineSet. - format: int64 - type: integer - readyReplicas: - description: The number of ready replicas for this MachineSet. A machine - is considered ready when the node has been created and is "Ready". - format: int32 - type: integer - replicas: - description: Replicas is the most recently observed number of replicas. - format: int32 - type: integer - selector: - description: |- - Selector is the same as the label selector but in the string format to avoid introspection - by clients. The string will be in the same format as the query-param syntax. - More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors - type: string - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.selector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-nodepools.hypershift.openshift.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-nodepools.hypershift.openshift.io.yaml deleted file mode 100644 index 41f0da2d3..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-nodepools.hypershift.openshift.io.yaml +++ /dev/null @@ -1,2554 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - name: nodepools.hypershift.openshift.io -spec: - group: hypershift.openshift.io - names: - kind: NodePool - listKind: NodePoolList - plural: nodepools - shortNames: - - np - - nps - singular: nodepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Desired Nodes - jsonPath: .spec.replicas - name: Desired Nodes - type: integer - - description: Available Nodes - jsonPath: .status.replicas - name: Current Nodes - type: integer - - description: Autoscaling Enabled - jsonPath: .status.conditions[?(@.type=="AutoscalingEnabled")].status - name: Autoscaling - type: string - - description: Node Autorepair Enabled - jsonPath: .status.conditions[?(@.type=="AutorepairEnabled")].status - name: Autorepair - type: string - - description: Current version - jsonPath: .status.version - name: Version - type: string - - description: UpdatingVersion in progress - jsonPath: .status.conditions[?(@.type=="UpdatingVersion")].status - name: UpdatingVersion - type: string - - description: UpdatingConfig in progress - jsonPath: .status.conditions[?(@.type=="UpdatingConfig")].status - name: UpdatingConfig - type: string - - description: Message - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Message - type: string - deprecated: true - deprecationWarning: v1alpha1 is a deprecated version for NodePool - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - NodePool is a scalable set of worker nodes attached to a HostedCluster. - NodePool machine architectures are uniform within a given pool, and are - independent of the control plane’s underlying machine architecture. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the desired behavior of the NodePool. - properties: - arch: - default: amd64 - description: "Arch is the preferred processor architecture for the - NodePool (currently only supported on AWS)\nNOTE: This is set as - optional to prevent validation from failing due to a limitation - on client side validation with open API machinery:\n\thttps://github.com/kubernetes/kubernetes/issues/108768#issuecomment-1253912215\nTODO - Add ppc64le and s390x to enum validation once the architectures - are supported" - enum: - - arm64 - - amd64 - type: string - autoScaling: - description: Autoscaling specifies auto-scaling behavior for the NodePool. - properties: - max: - description: Max is the maximum number of nodes allowed in the - pool. Must be >= 1. - format: int32 - minimum: 1 - type: integer - min: - description: Min is the minimum number of nodes to maintain in - the pool. Must be >= 1. - format: int32 - minimum: 1 - type: integer - required: - - max - - min - type: object - clusterName: - description: |- - ClusterName is the name of the HostedCluster this NodePool belongs to. - - - TODO(dan): Should this be a LocalObjectReference? - type: string - x-kubernetes-validations: - - message: ClusterName is immutable - rule: self == oldSelf - config: - description: |- - Config is a list of references to ConfigMaps containing serialized - MachineConfig resources to be injected into the ignition configurations of - nodes in the NodePool. The MachineConfig API schema is defined here: - - - https://github.com/openshift/machine-config-operator/blob/18963e4f8fe66e8c513ca4b131620760a414997f/pkg/apis/machineconfiguration.openshift.io/v1/types.go#L185 - - - Each ConfigMap must have a single key named "config" whose value is the - JSON or YAML of a serialized MachineConfig. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - management: - description: |- - Management specifies behavior for managing nodes in the pool, such as - upgrade strategies and auto-repair behaviors. - properties: - autoRepair: - default: false - description: |- - AutoRepair specifies whether health checks should be enabled for machines - in the NodePool. The default is false. - type: boolean - inPlace: - description: InPlace is the configuration for in-place upgrades. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - MaxUnavailable is the maximum number of nodes that can be unavailable - during the update. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding down. - - - Defaults to 1. - - - Example: when this is set to 30%, a max of 30% of the nodes can be made - unschedulable/unavailable immediately when the update starts. Once a set - of nodes is updated, more nodes can be made unschedulable for update, - ensuring that the total number of nodes schedulable at all times during - the update is at least 70% of desired nodes. - x-kubernetes-int-or-string: true - type: object - replace: - default: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - strategy: RollingUpdate - description: Replace is the configuration for rolling upgrades. - properties: - rollingUpdate: - description: |- - RollingUpdate specifies a rolling update strategy which upgrades nodes by - creating new nodes and deleting the old ones. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - MaxSurge is the maximum number of nodes that can be provisioned above the - desired number of nodes. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding up. - - - This can not be 0 if MaxUnavailable is 0. - - - Defaults to 1. - - - Example: when this is set to 30%, new nodes can be provisioned immediately - when the rolling update starts, such that the total number of old and new - nodes do not exceed 130% of desired nodes. Once old nodes have been - deleted, new nodes can be provisioned, ensuring that total number of nodes - running at any time during the update is at most 130% of desired nodes. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - MaxUnavailable is the maximum number of nodes that can be unavailable - during the update. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding down. - - - This can not be 0 if MaxSurge is 0. - - - Defaults to 0. - - - Example: when this is set to 30%, old nodes can be deleted down to 70% of - desired nodes immediately when the rolling update starts. Once new nodes - are ready, more old nodes be deleted, followed by provisioning new nodes, - ensuring that the total number of nodes available at all times during the - update is at least 70% of desired nodes. - x-kubernetes-int-or-string: true - type: object - strategy: - description: Strategy is the node replacement strategy for - nodes in the pool. - enum: - - RollingUpdate - - OnDelete - type: string - type: object - upgradeType: - description: UpgradeType specifies the type of strategy for handling - upgrades. - enum: - - Replace - - InPlace - type: string - x-kubernetes-validations: - - message: UpgradeType is immutable - rule: self == oldSelf - required: - - upgradeType - type: object - nodeCount: - description: |- - Deprecated: Use Replicas instead. NodeCount will be dropped in the next - api release. - format: int32 - type: integer - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the total amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - TODO (alberto): Today changing this field will trigger a recreate rolling update, which kind of defeats - the purpose of the change. In future we plan to propagate this field in-place. - https://github.com/kubernetes-sigs/cluster-api/issues/5880 - type: string - nodeLabels: - additionalProperties: - type: string - description: |- - NodeLabels propagates a list of labels to Nodes, only once on creation. - Valid values are those in https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set - type: object - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the maximum amount of time that the controller will spend on detaching volume from a node. - After the timeout, volumes that haven't been detached are skipped. - type: string - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - Platform specifies the underlying infrastructure provider for the NodePool - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies the configuration used when using - Agent platform. - properties: - agentLabelSelector: - description: |- - AgentLabelSelector contains labels that must be set on an Agent in order to - be selected for a Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - aws: - description: AWS specifies the configuration used when operating - on AWS. - properties: - ami: - description: |- - AMI is the image id to use for node instances. If unspecified, the default - is chosen based on the NodePool release payload image. - type: string - instanceProfile: - description: InstanceProfile is the AWS EC2 instance profile, - which is a container for an IAM role that the EC2 instance - uses. - type: string - instanceType: - description: InstanceType is an ec2 instance type for node - instances (e.g. m5.large). - type: string - resourceTags: - description: |- - ResourceTags is an optional list of additional tags to apply to AWS node - instances. - - - These will be merged with HostedCluster scoped tags, and HostedCluster tags - take precedence in case of conflicts. - - - See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - rootVolume: - description: RootVolume specifies configuration for the root - volume of node instances. - properties: - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - x-kubernetes-validations: - - message: Encrypted is immutable - rule: self == oldSelf - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: |- - IOPS is the number of IOPS requested for the disk. This is only valid - for type io1. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - - - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - type: - description: Type is the type of the volume. - type: string - required: - - size - - type - type: object - securityGroups: - description: |- - SecurityGroups is an optional set of security groups to associate with node - instances. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - subnet: - description: Subnet is the subnet to use for node instances. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - x-kubernetes-validations: - - message: subnet is invalid, a valid subnet id or filters - must be set, but not both - rule: 'has(self.id) && self.id.startsWith(''subnet-'') ? - !has(self.filters) : size(self.filters) > 0' - tenancy: - description: |- - Tenancy indicates if instance should run on shared or single-tenant hardware. - - - Possible values: - default: NodePool instances run on shared hardware. - dedicated: Each NodePool instance runs on single-tenant hardware. - host: NodePool instances run on user's pre-allocated dedicated hosts. - enum: - - default - - dedicated - - host - type: string - required: - - instanceType - type: object - azure: - properties: - availabilityZone: - description: |- - AvailabilityZone is the failure domain identifier where the VM should be attached to. This must not be specified - for clusters in a location that does not support AvailabilityZone. - type: string - diagnostics: - description: |- - Diagnostics specifies the diagnostics settings for a virtual machine. - If not specified, then Boot diagnostics will be disabled. - properties: - storageAccountType: - default: Disabled - description: |- - StorageAccountType determines if the storage account for storing the diagnostics data - should be disabled (Disabled), provisioned by Azure (Managed) or by the user (UserManaged). - enum: - - Managed - - UserManaged - - Disabled - type: string - storageAccountURI: - description: |- - StorageAccountURI is the URI of the user-managed storage account. - The URI typically will be `https://.blob.core.windows.net/` - but may differ if you are using Azure DNS zone endpoints. - You can find the correct endpoint by looking for the Blob Primary Endpoint in the - endpoints tab in the Azure console or with the CLI by issuing - `az storage account list --query='[].{name: name, "resource group": resourceGroup, "blob endpoint": primaryEndpoints.blob}'`. - format: uri - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: storageAccountURI is required when storageAccountType - is UserManaged - rule: 'self.storageAccountType == ''UserManaged'' ? has(self.storageAccountURI) - : true' - diskEncryptionSetID: - description: |- - DiskEncryptionSetID is the ID of the DiskEncryptionSet resource to use to encrypt the OS disks for the VMs. This - needs to exist in the same subscription id listed in the Hosted Cluster, hcluster.Spec.Platform.Azure.SubscriptionID. - DiskEncryptionSetID should also exist in a resource group under the same subscription id and the same location - listed in the Hosted Cluster, hcluster.Spec.Platform.Azure.Location. - type: string - diskSizeGB: - default: 120 - description: DiskSizeGB is the size in GB to assign to the - OS disk - format: int32 - minimum: 16 - type: integer - diskStorageAccountType: - default: Premium_LRS - description: |- - DiskStorageAccountType is the disk storage account type to use. Valid values are: - * Standard_LRS: HDD - * StandardSSD_LRS: Standard SSD - * Premium_LRS: Premium SDD - * UltraSSD_LRS: Ultra SDD - - - Defaults to Premium_LRS. For more details, visit the Azure documentation: - https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison - enum: - - Standard_LRS - - StandardSSD_LRS - - Premium_LRS - - UltraSSD_LRS - type: string - enableEphemeralOSDisk: - description: EnableEphemeralOSDisk is a flag when set to true, - will enable ephemeral OS disk. - type: boolean - image: - description: Image is the image to boot the VMs with - properties: - azureImageType: - description: |- - Type is the type of image data that will be provided to the Azure VM. This can be either "ImageID" or - "AzureMarketplace". - enum: - - ImageID - - AzureMarketplace - type: string - azureMarketplace: - description: AzureMarketplace contains the Azure Marketplace - image info to use to boot the Azure VMs from. - properties: - offer: - description: Offer specifies the name of a group of - related images created by the publisher. - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization - that created the image - minLength: 1 - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - type: string - version: - description: |- - Version specifies the version of an image sku. The allowed formats are Major.Minor.Build or 'latest'. Major, - Minor, and Build are decimal numbers. Specify 'latest' to use the latest version of an image available at - deployment time. Even if you use 'latest', the VM image will not automatically update after deploy time even if a - new version becomes available. - minLength: 1 - type: string - required: - - offer - - publisher - - sku - - version - type: object - imageID: - description: ImageID is the Azure resource ID of a VHD - image to use to boot the Azure VMs from. - type: string - required: - - azureImageType - type: object - x-kubernetes-validations: - - message: Image is immutable - rule: self == oldSelf - machineIdentityID: - type: string - subnetID: - description: |- - SubnetID is the subnet ID of an existing subnet where the nodes in the nodepool will be created. This can be a - different subnet than the one listed in the HostedCluster, hcluster.Spec.Platform.Azure.SubnetID, but must exist - in the same hcluster.Spec.Platform.Azure.VnetID and must exist under the same subscription ID, - hcluster.Spec.Platform.Azure.SubscriptionID. - type: string - x-kubernetes-validations: - - message: SubnetID is immutable - rule: self == oldSelf - vmsize: - description: VMSize is the Azure VM instance type to use for - the nodes being created in the nodepool. - type: string - required: - - image - - machineIdentityID - - subnetID - - vmsize - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: Kubevirt specifies the configuration used when operating - on KubeVirt platform. - properties: - additionalNetworks: - description: AdditionalNetworks specify the extra networks - attached to the nodes - items: - description: |- - KubevirtNetwork specifies the configuration for a virtual machine - network interface - properties: - name: - description: |- - Name specify the network attached to the nodes - it is a value with the format "[namespace]/[name]" to reference the - multus network attachment definition - type: string - required: - - name - type: object - type: array - attachDefaultNetwork: - default: true - description: |- - AttachDefaultNetwork specify if the default pod network should be attached to the nodes - this can only be set to false if AdditionalNetworks are configured - type: boolean - compute: - default: - cores: 2 - memory: 8Gi - description: Compute contains values representing the virtual - hardware requested for the VM - properties: - cores: - default: 2 - description: Cores represents how many cores the guest - VM should have - format: int32 - type: integer - memory: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Memory represents how much guest memory the - VM should have - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - qosClass: - default: Burstable - description: |- - QosClass If set to "Guaranteed", requests the scheduler to place the VirtualMachineInstance on a node with - limit memory and CPU, equal to be the requested values, to set the VMI as a Guaranteed QoS Class; - See here for more details: - https://kubevirt.io/user-guide/operations/node_overcommit/#requesting-the-right-qos-class-for-virtualmachineinstances - enum: - - Burstable - - Guaranteed - type: string - type: object - hostDevices: - description: |- - KubevirtHostDevices specifies the host devices (e.g. GPU devices) to be passed - from the management cluster, to the nodepool nodes - items: - properties: - count: - default: 1 - description: |- - Count is the number of instances the specified host device will be attached to each of the - NodePool's nodes. Default is 1. - minimum: 1 - type: integer - deviceName: - description: |- - DeviceName is the name of the host device that is desired to be utilized in the HostedCluster's NodePool - The device can be any supported PCI device, including GPU, either as a passthrough or a vGPU slice. - type: string - required: - - deviceName - type: object - type: array - networkInterfaceMultiqueue: - default: Enable - description: |- - NetworkInterfaceMultiQueue If set to "Enable", virtual network interfaces configured with a virtio bus will also - enable the vhost multiqueue feature for network devices. The number of queues created depends on additional - factors of the VirtualMachineInstance, like the number of guest CPUs. - enum: - - Enable - - Disable - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the kubevirt VirtualMachine to fit on a node. - Selector which must match a node's labels for the VM to be scheduled on that node. More info: - https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - rootVolume: - default: - persistent: - size: 32Gi - type: Persistent - description: RootVolume represents values associated with - the VM volume that will host rhcos - properties: - cacheStrategy: - description: CacheStrategy defines the boot image caching - strategy. Default - no caching - properties: - type: - default: None - description: Type is the type of the caching strategy - enum: - - None - - PVC - type: string - required: - - type - type: object - diskImage: - description: Image represents what rhcos image to use - for the node pool - properties: - containerDiskImage: - description: ContainerDiskImage is a string representing - the container image that holds the root disk - type: string - type: object - persistent: - description: |- - Persistent volume type means the VM's storage is backed by a PVC - VMs that use persistent volumes can survive disruption events like restart and eviction - This is the default type used when no storage type is defined. - properties: - accessModes: - description: |- - AccessModes is an array that contains the desired Access Modes the root volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes - items: - enum: - - ReadWriteOnce - - ReadWriteMany - - ReadOnly - - ReadWriteOncePod - type: string - type: array - size: - anyOf: - - type: integer - - type: string - default: 32Gi - description: Size is the size of the persistent storage - volume - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - storageClass: - description: StorageClass is the storageClass used - for the underlying PVC that hosts the volume - type: string - volumeMode: - description: |- - VolumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - enum: - - Filesystem - - Block - type: string - type: object - type: - default: Persistent - description: Type represents the type of storage to associate - with the kubevirt VMs. - enum: - - Persistent - type: string - type: object - required: - - rootVolume - type: object - powervs: - description: PowerVS specifies the configuration used when using - IBMCloud PowerVS platform. - properties: - image: - description: |- - Image used for deploying the nodes. If unspecified, the default - is chosen based on the NodePool release payload image. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - imageDeletePolicy: - default: delete - description: |- - ImageDeletePolicy is policy for the image deletion. - - - delete: delete the image from the infrastructure. - retain: delete the image from the openshift but retain in the infrastructure. - - - The default is delete - enum: - - delete - - retain - type: string - memoryGiB: - default: 32 - description: |- - MemoryGiB is the size of a virtual machine's memory, in GiB. - maximum value for the MemoryGiB depends on the selected SystemType. - when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. - when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. - when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. - The minimum memory is 32 GiB. - - - When omitted, this means the user has no opinion and the platform is left to choose a reasonable - default. The current default is 32. - format: int32 - type: integer - processorType: - default: shared - description: |- - ProcessorType is the VM instance processor type. - It must be set to one of the following values: Dedicated, Capped or Shared. - - - Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. - Shared: Shared among other clients. - Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. - - - if the processorType is selected as Dedicated, then Processors value cannot be fractional. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The current default is shared. - enum: - - dedicated - - shared - - capped - type: string - processors: - anyOf: - - type: integer - - type: string - default: "0.5" - description: |- - Processors is the number of virtual processors in a virtual machine. - when the processorType is selected as Dedicated the processors value cannot be fractional. - maximum value for the Processors depends on the selected SystemType. - when SystemType is set to e880 or e980 maximum Processors value is 143. - when SystemType is set to s922 maximum Processors value is 15. - minimum value for Processors depends on the selected ProcessorType. - when ProcessorType is set as Shared or Capped, The minimum processors is 0.5. - when ProcessorType is set as Dedicated, The minimum processors is 1. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The default is set based on the selected ProcessorType. - when ProcessorType selected as Dedicated, the default is set to 1. - when ProcessorType selected as Shared or Capped, the default is set to 0.5. - x-kubernetes-int-or-string: true - storageType: - default: tier1 - description: |- - StorageType for the image and nodes, this will be ignored if Image is specified. - The storage tiers in PowerVS are based on I/O operations per second (IOPS). - It means that the performance of your storage volumes is limited to the maximum number of IOPS based on volume size and storage tier. - Although, the exact numbers might change over time, the Tier 3 storage is currently set to 3 IOPS/GB, and the Tier 1 storage is currently set to 10 IOPS/GB. - - - The default is tier1 - enum: - - tier1 - - tier3 - type: string - systemType: - default: s922 - description: |- - SystemType is the System type used to host the instance. - systemType determines the number of cores and memory that is available. - Few of the supported SystemTypes are s922,e880,e980. - e880 systemType available only in Dallas Datacenters. - e980 systemType available in Datacenters except Dallas and Washington. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The current default is s922 which is generally available. - type: string - type: object - type: - description: Type specifies the platform name. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - type: string - x-kubernetes-validations: - - message: Type is immutable - rule: self == oldSelf - required: - - type - type: object - x-kubernetes-validations: - - message: Platform is immutable - rule: self == oldSelf - release: - description: |- - Release specifies the OCP release used for the NodePool. This informs the - ignition configuration for machines, as well as other platform specific - machine properties (e.g. an AMI on the AWS platform). - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - replicas: - description: |- - Replicas is the desired number of nodes the pool should maintain. If - unset, the default value is 0. - format: int32 - type: integer - taints: - description: Taints if specified, propagates a list of taints to Nodes, - only once on creation. - items: - description: |- - Taint is as v1 Core but without TimeAdded. - https://github.com/kubernetes/kubernetes/blob/ed8cad1e80d096257921908a52ac69cf1f41a098/staging/src/k8s.io/api/core/v1/types.go#L3037-L3053 - properties: - effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Required. The taint key to be applied to a node. - type: string - value: - description: The taint value corresponding to the taint key. - type: string - required: - - effect - - key - type: object - type: array - tuningConfig: - description: |- - TuningConfig is a list of references to ConfigMaps containing serialized - Tuned resources to define the tuning configuration to be applied to - nodes in the NodePool. The Tuned API is defined here: - - - https://github.com/openshift/cluster-node-tuning-operator/blob/2c76314fb3cc8f12aef4a0dcd67ddc3677d5b54f/pkg/apis/tuned/v1/tuned_types.go - - - Each ConfigMap must have a single key named "tuned" whose value is the - JSON or YAML of a serialized Tuned. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - required: - - clusterName - - management - - platform - - release - type: object - status: - description: Status is the latest observed status of the NodePool. - properties: - conditions: - description: |- - Conditions represents the latest available observations of the node pool's - current state. - items: - description: |- - We define our own condition type since metav1.Condition has validation - for Reason that might be broken by what we bubble up from CAPI. - NodePoolCondition defines an observation of NodePool resource operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - observedGeneration: - format: int64 - minimum: 0 - type: integer - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - platform: - description: Platform hols the specific statuses - properties: - kubeVirt: - description: KubeVirt contains the KubeVirt platform statuses - properties: - cacheName: - description: CacheName holds the name of the cache DataVolume, - if exists - type: string - credentials: - description: |- - Credentials shows the client credentials used when creating KubeVirt virtual machines. - This filed is only exists when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - type: object - type: object - replicas: - description: Replicas is the latest observed number of nodes in the - pool. - format: int32 - type: integer - version: - description: |- - Version is the semantic version of the latest applied release specified by - the NodePool. - type: string - type: object - type: object - served: true - storage: false - subresources: - scale: - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} - - additionalPrinterColumns: - - description: Cluster - jsonPath: .spec.clusterName - name: Cluster - type: string - - description: Desired Nodes - jsonPath: .spec.replicas - name: Desired Nodes - type: integer - - description: Available Nodes - jsonPath: .status.replicas - name: Current Nodes - type: integer - - description: Autoscaling Enabled - jsonPath: .status.conditions[?(@.type=="AutoscalingEnabled")].status - name: Autoscaling - type: string - - description: Node Autorepair Enabled - jsonPath: .status.conditions[?(@.type=="AutorepairEnabled")].status - name: Autorepair - type: string - - description: Current version - jsonPath: .status.version - name: Version - type: string - - description: UpdatingVersion in progress - jsonPath: .status.conditions[?(@.type=="UpdatingVersion")].status - name: UpdatingVersion - type: string - - description: UpdatingConfig in progress - jsonPath: .status.conditions[?(@.type=="UpdatingConfig")].status - name: UpdatingConfig - type: string - - description: Message - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Message - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - NodePool is a scalable set of worker nodes attached to a HostedCluster. - NodePool machine architectures are uniform within a given pool, and are - independent of the control plane’s underlying machine architecture. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the desired behavior of the NodePool. - properties: - arch: - default: amd64 - description: "Arch is the preferred processor architecture for the - NodePool (currently only supported on AWS)\nNOTE: This is set as - optional to prevent validation from failing due to a limitation - on client side validation with open API machinery:\n\thttps://github.com/kubernetes/kubernetes/issues/108768#issuecomment-1253912215\nTODO - Add s390x to enum validation once the architecture is supported" - enum: - - arm64 - - amd64 - - ppc64le - type: string - x-kubernetes-validations: - - message: Arch is immutable - rule: self == oldSelf - autoScaling: - description: Autoscaling specifies auto-scaling behavior for the NodePool. - properties: - max: - description: Max is the maximum number of nodes allowed in the - pool. Must be >= 1. - format: int32 - minimum: 1 - type: integer - min: - description: Min is the minimum number of nodes to maintain in - the pool. Must be >= 1. - format: int32 - minimum: 1 - type: integer - required: - - max - - min - type: object - x-kubernetes-validations: - - message: max must be equal or greater than min - rule: self.max >= self.min - clusterName: - description: |- - ClusterName is the name of the HostedCluster this NodePool belongs to. - - - TODO(dan): Should this be a LocalObjectReference? - type: string - x-kubernetes-validations: - - message: ClusterName is immutable - rule: self == oldSelf - config: - description: |- - Config is a list of references to ConfigMaps containing serialized - MachineConfig resources to be injected into the ignition configurations of - nodes in the NodePool. The MachineConfig API schema is defined here: - - - https://github.com/openshift/machine-config-operator/blob/18963e4f8fe66e8c513ca4b131620760a414997f/pkg/apis/machineconfiguration.openshift.io/v1/types.go#L185 - - - Each ConfigMap must have a single key named "config" whose value is the YML - with one or more serialized machineconfiguration.openshift.io resources: - KubeletConfig - ContainerRuntimeConfig - MachineConfig - ClusterImagePolicy - ImageContentSourcePolicy - or - ImageDigestMirrorSet - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - management: - description: |- - Management specifies behavior for managing nodes in the pool, such as - upgrade strategies and auto-repair behaviors. - properties: - autoRepair: - default: false - description: |- - AutoRepair specifies whether health checks should be enabled for machines - in the NodePool. The default is false. - type: boolean - inPlace: - description: InPlace is the configuration for in-place upgrades. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - MaxUnavailable is the maximum number of nodes that can be unavailable - during the update. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding down. - - - Defaults to 1. - - - Example: when this is set to 30%, a max of 30% of the nodes can be made - unschedulable/unavailable immediately when the update starts. Once a set - of nodes is updated, more nodes can be made unschedulable for update, - ensuring that the total number of nodes schedulable at all times during - the update is at least 70% of desired nodes. - x-kubernetes-int-or-string: true - type: object - replace: - default: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - strategy: RollingUpdate - description: Replace is the configuration for rolling upgrades. - properties: - rollingUpdate: - description: |- - RollingUpdate specifies a rolling update strategy which upgrades nodes by - creating new nodes and deleting the old ones. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - MaxSurge is the maximum number of nodes that can be provisioned above the - desired number of nodes. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding up. - - - This can not be 0 if MaxUnavailable is 0. - - - Defaults to 1. - - - Example: when this is set to 30%, new nodes can be provisioned immediately - when the rolling update starts, such that the total number of old and new - nodes do not exceed 130% of desired nodes. Once old nodes have been - deleted, new nodes can be provisioned, ensuring that total number of nodes - running at any time during the update is at most 130% of desired nodes. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - MaxUnavailable is the maximum number of nodes that can be unavailable - during the update. - - - Value can be an absolute number (ex: 5) or a percentage of desired nodes - (ex: 10%). - - - Absolute number is calculated from percentage by rounding down. - - - This can not be 0 if MaxSurge is 0. - - - Defaults to 0. - - - Example: when this is set to 30%, old nodes can be deleted down to 70% of - desired nodes immediately when the rolling update starts. Once new nodes - are ready, more old nodes be deleted, followed by provisioning new nodes, - ensuring that the total number of nodes available at all times during the - update is at least 70% of desired nodes. - x-kubernetes-int-or-string: true - type: object - strategy: - description: Strategy is the node replacement strategy for - nodes in the pool. - enum: - - RollingUpdate - - OnDelete - type: string - type: object - upgradeType: - description: UpgradeType specifies the type of strategy for handling - upgrades. - enum: - - Replace - - InPlace - type: string - x-kubernetes-validations: - - message: UpgradeType is immutable - rule: self == oldSelf - required: - - upgradeType - type: object - nodeDrainTimeout: - description: |- - NodeDrainTimeout is the maximum amount of time that the controller will spend on draining a node. - The default value is 0, meaning that the node can be drained without any time limitations. - NOTE: NodeDrainTimeout is different from `kubectl drain --timeout` - TODO (alberto): Today changing this field will trigger a recreate rolling update, which kind of defeats - the purpose of the change. In future we plan to propagate this field in-place. - https://github.com/kubernetes-sigs/cluster-api/issues/5880 / https://github.com/kubernetes-sigs/cluster-api/pull/10589 - type: string - nodeLabels: - additionalProperties: - type: string - description: |- - NodeLabels propagates a list of labels to Nodes, only once on creation. - Valid values are those in https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set - type: object - nodeVolumeDetachTimeout: - description: |- - NodeVolumeDetachTimeout is the maximum amount of time that the controller will spend on detaching volumes from a node. - The default value is 0, meaning that the volumes will be detached from the node without any time limitations. - After the timeout, the detachment of volumes that haven't been detached yet is skipped. - TODO (cbusse): Same comment as Alberto's for `NodeDrainTimeout`: - Today changing this field will trigger a recreate rolling update, which kind of defeats - the purpose of the change. In future we plan to propagate this field in-place. - https://github.com/kubernetes-sigs/cluster-api/issues/5880 / https://github.com/kubernetes-sigs/cluster-api/pull/10589 - type: string - pausedUntil: - description: |- - PausedUntil is a field that can be used to pause reconciliation on a resource. - Either a date can be provided in RFC3339 format or a boolean. If a date is - provided: reconciliation is paused on the resource until that date. If the boolean true is - provided: reconciliation is paused on the resource until the field is removed. - type: string - platform: - description: |- - Platform specifies the underlying infrastructure provider for the NodePool - and is used to configure platform specific behavior. - properties: - agent: - description: Agent specifies the configuration used when using - Agent platform. - properties: - agentLabelSelector: - description: |- - AgentLabelSelector contains labels that must be set on an Agent in order to - be selected for a Machine. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - type: object - aws: - description: AWS specifies the configuration used when operating - on AWS. - properties: - ami: - description: |- - AMI is the image id to use for node instances. If unspecified, the default - is chosen based on the NodePool release payload image. - type: string - instanceProfile: - description: InstanceProfile is the AWS EC2 instance profile, - which is a container for an IAM role that the EC2 instance - uses. - type: string - instanceType: - description: InstanceType is an ec2 instance type for node - instances (e.g. m5.large). - type: string - resourceTags: - description: |- - ResourceTags is an optional list of additional tags to apply to AWS node - instances. - - - These will be merged with HostedCluster scoped tags, and HostedCluster tags - take precedence in case of conflicts. - - - See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for - information on tagging AWS resources. AWS supports a maximum of 50 tags per - resource. OpenShift reserves 25 tags for its use, leaving 25 tags available - for the user. - items: - description: AWSResourceTag is a tag to apply to AWS resources - created for the cluster. - properties: - key: - description: Key is the key of the tag. - maxLength: 128 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - value: - description: |- - Value is the value of the tag. - - - Some AWS service do not support empty values. Since tags are added to - resources in many services, the length of the tag value must meet the - requirements of all services. - maxLength: 256 - minLength: 1 - pattern: ^[0-9A-Za-z_.:/=+-@]+$ - type: string - required: - - key - - value - type: object - maxItems: 25 - type: array - rootVolume: - description: RootVolume specifies configuration for the root - volume of node instances. - properties: - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - x-kubernetes-validations: - - message: Encrypted is immutable - rule: self == oldSelf - encryptionKey: - description: |- - EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. - If Encrypted is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: |- - IOPS is the number of IOPS requested for the disk. This is only valid - for type io1. - format: int64 - type: integer - size: - description: |- - Size specifies size (in Gi) of the storage device. - - - Must be greater than the image snapshot size or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - type: - description: Type is the type of the volume. - type: string - required: - - size - - type - type: object - securityGroups: - description: |- - SecurityGroups is an optional set of security groups to associate with node - instances. - items: - description: |- - AWSResourceReference is a reference to a specific AWS resource by ID or filters. - Only one of ID or Filters may be specified. Specifying more than one will result in - a validation error. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - subnet: - description: Subnet is the subnet to use for node instances. - properties: - filters: - description: |- - Filters is a set of key/value pairs used to identify a resource - They are applied according to the rules defined by the AWS API: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html - items: - description: Filter is a filter used to identify an - AWS resource - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - x-kubernetes-validations: - - message: subnet is invalid, a valid subnet id or filters - must be set, but not both - rule: 'has(self.id) && self.id.startsWith(''subnet-'') ? - !has(self.filters) : size(self.filters) > 0' - tenancy: - description: |- - Tenancy indicates if instance should run on shared or single-tenant hardware. - - - Possible values: - default: NodePool instances run on shared hardware. - dedicated: Each NodePool instance runs on single-tenant hardware. - host: NodePool instances run on user's pre-allocated dedicated hosts. - enum: - - default - - dedicated - - host - type: string - required: - - instanceType - - subnet - type: object - azure: - properties: - availabilityZone: - description: |- - AvailabilityZone is the failure domain identifier where the VM should be attached to. This must not be specified - for clusters in a location that does not support AvailabilityZone. - type: string - diagnostics: - description: |- - Diagnostics specifies the diagnostics settings for a virtual machine. - If not specified, then Boot diagnostics will be disabled. - properties: - storageAccountType: - default: Disabled - description: |- - StorageAccountType determines if the storage account for storing the diagnostics data - should be disabled (Disabled), provisioned by Azure (Managed) or by the user (UserManaged). - enum: - - Managed - - UserManaged - - Disabled - type: string - storageAccountURI: - description: |- - StorageAccountURI is the URI of the user-managed storage account. - The URI typically will be `https://.blob.core.windows.net/` - but may differ if you are using Azure DNS zone endpoints. - You can find the correct endpoint by looking for the Blob Primary Endpoint in the - endpoints tab in the Azure console or with the CLI by issuing - `az storage account list --query='[].{name: name, "resource group": resourceGroup, "blob endpoint": primaryEndpoints.blob}'`. - format: uri - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: storageAccountURI is required when storageAccountType - is UserManaged - rule: 'self.storageAccountType == ''UserManaged'' ? has(self.storageAccountURI) - : true' - diskEncryptionSetID: - description: |- - DiskEncryptionSetID is the ID of the DiskEncryptionSet resource to use to encrypt the OS disks for the VMs. This - needs to exist in the same subscription id listed in the Hosted Cluster, HostedCluster.Spec.Platform.Azure.SubscriptionID. - DiskEncryptionSetID should also exist in a resource group under the same subscription id and the same location - listed in the Hosted Cluster, HostedCluster.Spec.Platform.Azure.Location. - type: string - diskSizeGB: - default: 30 - description: |- - DiskSizeGB is the size in GB to assign to the OS disk - CAPZ default is 30GB, https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/b3708019a67ff19407b87d63c402af94ca4246f6/api/v1beta1/types.go#L599 - format: int32 - minimum: 16 - type: integer - diskStorageAccountType: - default: Premium_LRS - description: |- - DiskStorageAccountType is the disk storage account type to use. Valid values are: - * Standard_LRS: HDD - * StandardSSD_LRS: Standard SSD - * Premium_LRS: Premium SDD - * UltraSSD_LRS: Ultra SDD - - - Defaults to Premium_LRS. For more details, visit the Azure documentation: - https://docs.microsoft.com/en-us/azure/virtual-machines/disks-types#disk-type-comparison - enum: - - Standard_LRS - - StandardSSD_LRS - - Premium_LRS - - UltraSSD_LRS - type: string - enableEphemeralOSDisk: - description: EnableEphemeralOSDisk is a flag when set to true, - will enable ephemeral OS disk. - type: boolean - image: - description: |- - ImageID is the id of the image to boot from. If unset, the default image at the location below will be used and - is expected to exist: subscription//resourceGroups//providers/Microsoft.Compute/images/rhcos.x86_64.vhd. - The and the are expected to be the same resource group documented in the - Hosted Cluster specification respectively, HostedCluster.Spec.Platform.Azure.SubscriptionID and - HostedCluster.Spec.Platform.Azure.ResourceGroupName. - properties: - azureImageType: - description: |- - Type is the type of image data that will be provided to the Azure VM. This can be either "ImageID" or - "AzureMarketplace". - enum: - - ImageID - - AzureMarketplace - type: string - azureMarketplace: - description: AzureMarketplace contains the Azure Marketplace - image info to use to boot the Azure VMs from. - properties: - offer: - description: Offer specifies the name of a group of - related images created by the publisher. - minLength: 1 - type: string - publisher: - description: Publisher is the name of the organization - that created the image - maxLength: 50 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9-_]{2,49}$ - type: string - sku: - description: |- - SKU specifies an instance of an offer, such as a major release of a distribution. - For example, 18.04-LTS, 2019-Datacenter - minLength: 1 - pattern: ^[a-z0-9-_]+$ - type: string - version: - description: |- - Version specifies the version of an image sku. The allowed formats are Major.Minor.Build or 'latest'. Major, - Minor, and Build are decimal numbers. Specify 'latest' to use the latest version of an image available at - deployment time. Even if you use 'latest', the VM image will not automatically update after deploy time even if a - new version becomes available. - maxLength: 32 - minLength: 1 - pattern: ^[0-9]+\.[0-9]+\.[0-9]+$ - type: string - required: - - offer - - publisher - - sku - - version - type: object - imageID: - description: ImageID is the Azure resource ID of a VHD - image to use to boot the Azure VMs from. - type: string - required: - - azureImageType - type: object - machineIdentityID: - description: |- - MachineIdentityID is a user-assigned identity assigned to the VMs used to authenticate with Azure services. This - field is expected to exist under the same resource group as HostedCluster.Spec.Platform.Azure.ResourceGroupName. This - user assigned identity is expected to have the Contributor role assigned to it and scoped to the resource group - under HostedCluster.Spec.Platform.Azure.ResourceGroupName. - - - If this field is not supplied, the Service Principal credentials will be written to a file on the disk of each VM - in order to be accessible by the cloud provider; the aforementioned credentials provided are the same ones as - HostedCluster.Spec.Platform.Azure.Credentials. However, this is less secure than using a managed identity. - type: string - subnetID: - description: |- - SubnetID is the subnet ID of an existing subnet where the nodes in the nodepool will be created. This can be a - different subnet than the one listed in the HostedCluster, HostedCluster.Spec.Platform.Azure.SubnetID, but must - exist in the same HostedCluster.Spec.Platform.Azure.VnetID and must exist under the same subscription ID, - HostedCluster.Spec.Platform.Azure.SubscriptionID. - type: string - x-kubernetes-validations: - - message: SubnetID is immutable - rule: self == oldSelf - vmsize: - description: VMSize is the Azure VM instance type to use for - the nodes being created in the nodepool. - type: string - required: - - image - - subnetID - - vmsize - type: object - ibmcloud: - description: IBMCloud defines IBMCloud specific settings for components - properties: - providerType: - description: ProviderType is a specific supported infrastructure - provider within IBM Cloud. - type: string - type: object - kubevirt: - description: Kubevirt specifies the configuration used when operating - on KubeVirt platform. - properties: - additionalNetworks: - description: AdditionalNetworks specify the extra networks - attached to the nodes - items: - description: |- - KubevirtNetwork specifies the configuration for a virtual machine - network interface - properties: - name: - description: |- - Name specify the network attached to the nodes - it is a value with the format "[namespace]/[name]" to reference the - multus network attachment definition - type: string - required: - - name - type: object - type: array - attachDefaultNetwork: - default: true - description: |- - AttachDefaultNetwork specify if the default pod network should be attached to the nodes - this can only be set to false if AdditionalNetworks are configured - type: boolean - compute: - default: - cores: 2 - memory: 8Gi - description: Compute contains values representing the virtual - hardware requested for the VM - properties: - cores: - default: 2 - description: Cores represents how many cores the guest - VM should have - format: int32 - type: integer - memory: - anyOf: - - type: integer - - type: string - default: 8Gi - description: Memory represents how much guest memory the - VM should have - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - qosClass: - default: Burstable - description: |- - QosClass If set to "Guaranteed", requests the scheduler to place the VirtualMachineInstance on a node with - limit memory and CPU, equal to be the requested values, to set the VMI as a Guaranteed QoS Class; - See here for more details: - https://kubevirt.io/user-guide/operations/node_overcommit/#requesting-the-right-qos-class-for-virtualmachineinstances - enum: - - Burstable - - Guaranteed - type: string - type: object - hostDevices: - description: |- - KubevirtHostDevices specifies the host devices (e.g. GPU devices) to be passed - from the management cluster, to the nodepool nodes - items: - properties: - count: - default: 1 - description: |- - Count is the number of instances the specified host device will be attached to each of the - NodePool's nodes. Default is 1. - minimum: 1 - type: integer - deviceName: - description: |- - DeviceName is the name of the host device that is desired to be utilized in the HostedCluster's NodePool - The device can be any supported PCI device, including GPU, either as a passthrough or a vGPU slice. - type: string - required: - - deviceName - type: object - type: array - networkInterfaceMultiqueue: - default: Enable - description: |- - NetworkInterfaceMultiQueue If set to "Enable", virtual network interfaces configured with a virtio bus will also - enable the vhost multiqueue feature for network devices. The number of queues created depends on additional - factors of the VirtualMachineInstance, like the number of guest CPUs. - enum: - - Enable - - Disable - type: string - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the kubevirt VirtualMachine to fit on a node. - Selector which must match a node's labels for the VM to be scheduled on that node. More info: - https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - rootVolume: - default: - persistent: - size: 32Gi - type: Persistent - description: RootVolume represents values associated with - the VM volume that will host rhcos - properties: - cacheStrategy: - description: CacheStrategy defines the boot image caching - strategy. Default - no caching - properties: - type: - default: None - description: Type is the type of the caching strategy - enum: - - None - - PVC - type: string - required: - - type - type: object - diskImage: - description: Image represents what rhcos image to use - for the node pool - properties: - containerDiskImage: - description: ContainerDiskImage is a string representing - the container image that holds the root disk - type: string - type: object - persistent: - description: |- - Persistent volume type means the VM's storage is backed by a PVC - VMs that use persistent volumes can survive disruption events like restart and eviction - This is the default type used when no storage type is defined. - properties: - accessModes: - description: |- - AccessModes is an array that contains the desired Access Modes the root volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes - items: - enum: - - ReadWriteOnce - - ReadWriteMany - - ReadOnly - - ReadWriteOncePod - type: string - type: array - size: - anyOf: - - type: integer - - type: string - default: 32Gi - description: Size is the size of the persistent storage - volume - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - storageClass: - description: StorageClass is the storageClass used - for the underlying PVC that hosts the volume - type: string - volumeMode: - description: |- - VolumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - enum: - - Filesystem - - Block - type: string - type: object - type: - default: Persistent - description: Type represents the type of storage to associate - with the kubevirt VMs. - enum: - - Persistent - type: string - type: object - required: - - rootVolume - type: object - openstack: - description: OpenStack specifies the configuration used when using - OpenStack platform. - properties: - flavor: - description: Flavor is the OpenStack flavor to use for the - node instances. - type: string - imageName: - description: |- - ImageName is the OpenStack Glance image name to use for node instances. If unspecified, the default - is chosen based on the NodePool release payload image. - type: string - required: - - flavor - type: object - powervs: - description: PowerVS specifies the configuration used when using - IBMCloud PowerVS platform. - properties: - image: - description: |- - Image used for deploying the nodes. If unspecified, the default - is chosen based on the NodePool release payload image. - properties: - id: - description: ID of resource - type: string - name: - description: Name of resource - type: string - type: object - imageDeletePolicy: - default: delete - description: |- - ImageDeletePolicy is policy for the image deletion. - - - delete: delete the image from the infrastructure. - retain: delete the image from the openshift but retain in the infrastructure. - - - The default is delete - enum: - - delete - - retain - type: string - memoryGiB: - default: 32 - description: |- - MemoryGiB is the size of a virtual machine's memory, in GiB. - maximum value for the MemoryGiB depends on the selected SystemType. - when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. - when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. - when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. - The minimum memory is 32 GiB. - - - When omitted, this means the user has no opinion and the platform is left to choose a reasonable - default. The current default is 32. - format: int32 - type: integer - processorType: - default: shared - description: |- - ProcessorType is the VM instance processor type. - It must be set to one of the following values: Dedicated, Capped or Shared. - - - Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. - Shared: Shared among other clients. - Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. - - - if the processorType is selected as Dedicated, then Processors value cannot be fractional. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The current default is shared. - enum: - - dedicated - - shared - - capped - type: string - processors: - anyOf: - - type: integer - - type: string - default: "0.5" - description: |- - Processors is the number of virtual processors in a virtual machine. - when the processorType is selected as Dedicated the processors value cannot be fractional. - maximum value for the Processors depends on the selected SystemType. - when SystemType is set to e880 or e980 maximum Processors value is 143. - when SystemType is set to s922 maximum Processors value is 15. - minimum value for Processors depends on the selected ProcessorType. - when ProcessorType is set as Shared or Capped, The minimum processors is 0.5. - when ProcessorType is set as Dedicated, The minimum processors is 1. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The default is set based on the selected ProcessorType. - when ProcessorType selected as Dedicated, the default is set to 1. - when ProcessorType selected as Shared or Capped, the default is set to 0.5. - x-kubernetes-int-or-string: true - storageType: - default: tier1 - description: |- - StorageType for the image and nodes, this will be ignored if Image is specified. - The storage tiers in PowerVS are based on I/O operations per second (IOPS). - It means that the performance of your storage volumes is limited to the maximum number of IOPS based on volume size and storage tier. - Although, the exact numbers might change over time, the Tier 3 storage is currently set to 3 IOPS/GB, and the Tier 1 storage is currently set to 10 IOPS/GB. - - - The default is tier1 - enum: - - tier1 - - tier3 - type: string - systemType: - default: s922 - description: |- - SystemType is the System type used to host the instance. - systemType determines the number of cores and memory that is available. - Few of the supported SystemTypes are s922,e880,e980. - e880 systemType available only in Dallas Datacenters. - e980 systemType available in Datacenters except Dallas and Washington. - When omitted, this means that the user has no opinion and the platform is left to choose a - reasonable default. The current default is s922 which is generally available. - type: string - type: object - type: - description: Type specifies the platform name. - enum: - - AWS - - None - - IBMCloud - - Agent - - KubeVirt - - Azure - - PowerVS - - OpenStack - type: string - x-kubernetes-validations: - - message: Type is immutable - rule: self == oldSelf - required: - - type - type: object - release: - description: |- - Release specifies the OCP release used for the NodePool. This informs the - ignition configuration for machines, as well as other platform specific - machine properties (e.g. an AMI on the AWS platform). - properties: - image: - description: Image is the image pullspec of an OCP release payload - image. - pattern: ^(\w+\S+)$ - type: string - required: - - image - type: object - replicas: - description: |- - Replicas is the desired number of nodes the pool should maintain. If - unset, the default value is 0. - format: int32 - type: integer - taints: - description: Taints if specified, propagates a list of taints to Nodes, - only once on creation. - items: - description: |- - Taint is as v1 Core but without TimeAdded. - https://github.com/kubernetes/kubernetes/blob/ed8cad1e80d096257921908a52ac69cf1f41a098/staging/src/k8s.io/api/core/v1/types.go#L3037-L3053 - properties: - effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Required. The taint key to be applied to a node. - type: string - value: - description: The taint value corresponding to the taint key. - pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ - type: string - required: - - effect - - key - type: object - type: array - tuningConfig: - description: |- - TuningConfig is a list of references to ConfigMaps containing serialized - Tuned or PerformanceProfile resources to define the tuning configuration to be applied to - nodes in the NodePool. The Tuned API is defined here: - - - https://github.com/openshift/cluster-node-tuning-operator/blob/2c76314fb3cc8f12aef4a0dcd67ddc3677d5b54f/pkg/apis/tuned/v1/tuned_types.go - - - The PerformanceProfile API is defined here: - https://github.com/openshift/cluster-node-tuning-operator/tree/b41042d42d4ba5bb2e99960248cf1d6ae4935018/pkg/apis/performanceprofile/v2 - - - Each ConfigMap must have a single key named "tuning" whose value is the - JSON or YAML of a serialized Tuned or PerformanceProfile. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - TODO: Add other useful fields. apiVersion, kind, uid? - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. - type: string - type: object - x-kubernetes-map-type: atomic - type: array - required: - - clusterName - - management - - platform - - release - type: object - x-kubernetes-validations: - - message: Arch is required once set - rule: '!has(oldSelf.arch) || has(self.arch)' - - message: Setting Arch to arm64 is only supported for AWS and Azure - rule: self.arch != 'arm64' || has(self.platform.aws) || has(self.platform.azure) - - message: Both replicas or autoScaling should not be set - rule: '!has(self.replicas) || !has(self.autoScaling)' - status: - description: Status is the latest observed status of the NodePool. - properties: - conditions: - description: |- - Conditions represents the latest available observations of the node pool's - current state. - items: - description: |- - We define our own condition type since metav1.Condition has validation - for Reason that might be broken by what we bubble up from CAPI. - NodePoolCondition defines an observation of NodePool resource operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - observedGeneration: - format: int64 - minimum: 0 - type: integer - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - platform: - description: Platform hols the specific statuses - properties: - kubeVirt: - description: KubeVirt contains the KubeVirt platform statuses - properties: - cacheName: - description: CacheName holds the name of the cache DataVolume, - if exists - type: string - credentials: - description: |- - Credentials shows the client credentials used when creating KubeVirt virtual machines. - This filed is only exists when the KubeVirt virtual machines are being placed - on a cluster separate from the one hosting the Hosted Control Plane components. - - - The default behavior when Credentials is not defined is for the KubeVirt VMs to be placed on - the same cluster and namespace as the Hosted Control Plane. - properties: - infraKubeConfigSecret: - description: |- - InfraKubeConfigSecret is a reference to a secret that contains the kubeconfig for the external infra cluster - that will be used to host the KubeVirt virtual machines for this cluster. - properties: - key: - type: string - name: - type: string - required: - - key - - name - type: object - x-kubernetes-validations: - - message: infraKubeConfigSecret is immutable - rule: self == oldSelf - infraNamespace: - description: |- - InfraNamespace defines the namespace on the external infra cluster that is used to host the KubeVirt - virtual machines. This namespace must already exist before creating the HostedCluster and the kubeconfig - referenced in the InfraKubeConfigSecret must have access to manage the required resources within this - namespace. - type: string - x-kubernetes-validations: - - message: infraNamespace is immutable - rule: self == oldSelf - required: - - infraNamespace - type: object - type: object - type: object - replicas: - description: Replicas is the latest observed number of nodes in the - pool. - format: int32 - type: integer - version: - description: |- - Version is the semantic version of the latest applied release specified by - the NodePool. - type: string - type: object - type: object - served: true - storage: true - subresources: - scale: - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclusters.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclusters.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index c030af5ae..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclusters.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,2300 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: openstackclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: OpenStackCluster - listKind: OpenStackClusterList - plural: openstackclusters - shortNames: - - osc - singular: openstackcluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this OpenStackCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for OpenStack instances - jsonPath: .status.ready - name: Ready - type: string - - description: Network the cluster is using - jsonPath: .status.network.id - name: Network - type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint - priority: 1 - type: string - - description: Bastion address for breakglass access - jsonPath: .status.bastion.floatingIP - name: Bastion IP - type: string - - description: Time duration since creation of OpenStackCluster - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: OpenStackCluster is the Schema for the openstackclusters API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: OpenStackClusterSpec defines the desired state of OpenStackCluster. - properties: - apiServerFixedIP: - description: |- - APIServerFixedIP is the fixed IP which will be associated with the API server. - In the case where the API server has a floating IP but not a managed load balancer, - this field is not used. - If a managed load balancer is used and this field is not specified, a fixed IP will - be dynamically allocated for the load balancer. - If a managed load balancer is not used AND the API server floating IP is disabled, - this field MUST be specified and should correspond to a pre-allocated port that - holds the fixed IP to be used as a VIP. - type: string - apiServerFloatingIP: - description: |- - APIServerFloatingIP is the floatingIP which will be associated with the API server. - The floatingIP will be created if it does not already exist. - If not specified, a new floatingIP is allocated. - This field is not used if DisableAPIServerFloatingIP is set to true. - type: string - apiServerLoadBalancer: - description: |- - APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. - If not specified, no load balancer will be created for the API server. - properties: - additionalPorts: - description: AdditionalPorts adds additional tcp ports to the - load balancer. - items: - type: integer - type: array - x-kubernetes-list-type: set - allowedCIDRs: - description: AllowedCIDRs restrict access to all API-Server listeners - to the given address CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: set - availabilityZone: - description: AvailabilityZone is the failure domain that will - be used to create the APIServerLoadBalancer Spec. - type: string - enabled: - default: true - description: |- - Enabled defines whether a load balancer should be created. This value - defaults to true if an APIServerLoadBalancer is given. - - - There is no reason to set this to false. To disable creation of the - API server loadbalancer, omit the APIServerLoadBalancer field in the - cluster spec instead. - type: boolean - network: - description: Network defines which network should the load balancer - be allocated on. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID is - provided, the other filters cannot be provided. Must be - in UUID format. - format: uuid - type: string - type: object - provider: - description: |- - Provider specifies name of a specific Octavia provider to use for the - API load balancer. The Octavia default will be used if it is not - specified. - type: string - subnets: - description: |- - Subnets define which subnets should the load balancer be allocated on. - It is expected that subnets are located on the network specified in this resource. - Only the first element is taken into account. - kubebuilder:validation:MaxLength:=2 - items: - description: SubnetParam specifies an OpenStack subnet to use. - It may be specified by either ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the subnet. - It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not be - validated. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - required: - - enabled - type: object - apiServerPort: - description: |- - APIServerPort is the port on which the listener on the APIServer - will be created - type: integer - bastion: - description: |- - Bastion is the OpenStack instance to login the nodes - - - As a rolling update is not ideal during a bastion host session, we - prevent changes to a running bastion configuration. To make changes, it's required - to first set `enabled: false` which will remove the bastion and then changes can be made. - properties: - availabilityZone: - description: AvailabilityZone is the failure domain that will - be used to create the Bastion Spec. - type: string - enabled: - default: true - description: |- - Enabled means that bastion is enabled. The bastion is enabled by - default if this field is not specified. Set this field to false to disable the - bastion. - - - It is not currently possible to remove the bastion from the cluster - spec without first disabling it by setting this field to false and - waiting until the bastion has been deleted. - type: boolean - floatingIP: - description: |- - FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID. - The floating IP should already exist and should not be associated with a port. If FIP of this address does not - exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. - format: ipv4 - type: string - spec: - description: Spec for the bastion itself - properties: - additionalBlockDevices: - description: AdditionalBlockDevices is a list of specifications - for additional block devices to attach to the server instance - items: - description: AdditionalBlockDevice is a block device to - attach to the server. - properties: - name: - description: |- - Name of the block device in the context of a machine. - If the block device is a volume, the Cinder volume will be named - as a combination of the machine name and this name. - Also, this name will be used for tagging the block device. - Information about the block device tag can be obtained from the OpenStack - metadata API or the config drive. - Name cannot be 'root', which is reserved for the root volume. - type: string - sizeGiB: - description: SizeGiB is the size of the block device - in gibibytes (GiB). - minimum: 1 - type: integer - storage: - description: |- - Storage specifies the storage type of the block device and - additional storage options. - properties: - type: - description: |- - Type is the type of block device to create. - This can be either "Volume" or "Local". - type: string - volume: - description: Volume contains additional storage - options for a volume block device. - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' - or default - rule: '!has(self.from) || self.from == ''Name'' - ? has(self.name) : !has(self.name)' - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - type: object - required: - - type - type: object - required: - - name - - sizeGiB - - storage - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - configDrive: - description: Config Drive support - type: boolean - flavor: - description: The flavor reference for the flavor for your - server instance. - type: string - floatingIPPoolRef: - description: |- - floatingIPPoolRef is a reference to a IPPool that will be assigned - to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP - will be assigned to the OpenStackMachine. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this machine. If not specified, the - credentials specified in the cluster will be used. - properties: - cloudName: - description: CloudName specifies the name of the entry - in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - image: - description: |- - The image to use for your server instance. - If the rootVolume is specified, this will be used when creating the root volume. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: |- - Filter describes a query for an image. If specified, the combination - of name and tags must return a single matching image or an error will - be raised. - minProperties: 1 - properties: - name: - description: The name of the desired image. If specified, - the combination of name and tags must return a single - matching image or an error will be raised. - type: string - tags: - description: The tags associated with the desired - image. If specified, the combination of name and - tags must return a single matching image or an error - will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the image. ID will not - be validated before use. - format: uuid - type: string - type: object - ports: - description: |- - Ports to be attached to the server instance. They are created if a port with the given name does not already exist. - If not specified a default port will be added for the default cluster network. - items: - properties: - adminStateUp: - description: AdminStateUp specifies whether the port - should be created in the up (true) or down (false) - state. The default is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable description - for the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of subnet and/or - IP address to assign to the port. If specified, these - must be subnets of the port's network. - items: - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If Subnet - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: |- - Subnet is an openstack subnet query that will return the id of a subnet to create - the fixed IP of a port in. This query must not return more than one subnet. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to - select the subnet. It must match exactly - one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. - It will not be validated. - format: uuid - type: string - type: object - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the host where - the port resides. - type: string - macAddress: - description: MACAddress specifies the MAC address of - the port. If not specified, the MAC address will be - generated. - type: string - nameSuffix: - description: NameSuffix will be appended to the name - of the port if specified. If unspecified, instead - the 0-based index of the port in the list is used. - type: string - network: - description: |- - Network is a query for an openstack network that the port will be created or discovered on. - This will fail if the query returns more than one network. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select - an OpenStack network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. - If ID is provided, the other filters cannot be - provided. Must be in UUID format. - format: uuid - type: string - type: object - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables the - OVS hardware offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables the “trusted - mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or disables - the propagate uplink status on the port. - type: boolean - securityGroups: - description: SecurityGroups is a list of the names, - uuids, filters or any combination these of the security - groups to assign to the instance. - items: - description: SecurityGroupParam specifies an OpenStack - security group. It may be specified by ID or filter, - but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select - an OpenStack security group. If provided, cannot - be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group - to use. If ID is provided, the other filters - cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - tags: - description: |- - Tags applied to the port (and corresponding trunk, if a trunk is configured.) - These tags are applied in addition to the instance's tags, which will also be applied to the port. - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: |- - Trunk specifies whether trunking is enabled at the port level. If not - provided the value is inherited from the machine, or false for a - bastion host. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single value_spec - key-value pair. - properties: - key: - description: Key is the key in the key-value pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the key-value - pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - rootVolume: - description: The volume metadata to boot from - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' or default - rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) - : !has(self.name)' - sizeGiB: - description: SizeGiB is the size of the block device in - gibibytes (GiB). - minimum: 1 - type: integer - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - required: - - sizeGiB - type: object - securityGroups: - description: The names of the security groups to assign to - the instance - items: - description: SecurityGroupParam specifies an OpenStack security - group. It may be specified by ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - security group. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group to use. - If ID is provided, the other filters cannot be provided. - Must be in UUID format. - format: uuid - type: string - type: object - type: array - serverGroup: - description: The server group to assign the machine to. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - server group. If provided, it cannot be empty. - minProperties: 1 - properties: - name: - description: Name is the name of a server group to - look for. - type: string - type: object - id: - description: ID is the ID of the server group to use. - format: uuid - type: string - type: object - serverMetadata: - description: Metadata mapping. Allows you to create a map - of key value pairs to add to the server instance. - items: - properties: - key: - description: Key is the server metadata key - maxLength: 255 - type: string - value: - description: Value is the server metadata value - maxLength: 255 - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - sshKeyName: - description: The ssh key to inject in the instance - type: string - tags: - description: |- - Tags which will be added to the machine and all dependent resources - which support them. These are in addition to Tags defined on the - cluster. - Requires Nova api 2.52 minimum! - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Whether the server instance is created on a trunk - port or not. - type: boolean - required: - - flavor - - image - type: object - type: object - x-kubernetes-validations: - - message: spec is required if bastion is enabled - rule: '!self.enabled || has(self.spec)' - controlPlaneAvailabilityZones: - description: |- - ControlPlaneAvailabilityZones is the set of availability zones which - control plane machines may be deployed to. - items: - type: string - type: array - x-kubernetes-list-type: set - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. - It is normally populated automatically by the OpenStackCluster - controller during cluster provisioning. If it is set on creation the - control plane endpoint will use the values set here in preference to - values set elsewhere. - ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneOmitAvailabilityZone: - description: |- - ControlPlaneOmitAvailabilityZone causes availability zone to be - omitted when creating control plane nodes, allowing the Nova - scheduler to make a decision on which availability zone to use based - on other scheduling constraints - type: boolean - disableAPIServerFloatingIP: - description: |- - DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating - IP to the API server. This allows for the creation of clusters when attaching a floating - IP to the API server (and hence, in many cases, exposing the API server to the internet) - is not possible or desirable, e.g. if using a shared VLAN for communication between - management and workload clusters or when the management cluster is inside the - project network. - This option requires that the API server use a VIP on the cluster network so that the - underlying machines can change without changing ControlPlaneEndpoint.Host. - When using a managed load balancer, this VIP will be managed automatically. - If not using a managed load balancer, cluster configuration will fail without additional - configuration to manage the VIP on the control plane machines, which falls outside of - the scope of this controller. - type: boolean - disableExternalNetwork: - description: |- - DisableExternalNetwork specifies whether or not to attempt to connect the cluster - to an external network. This allows for the creation of clusters when connecting - to an external network is not possible or desirable, e.g. if using a provider network. - type: boolean - disablePortSecurity: - description: |- - DisablePortSecurity disables the port security of the network created for the - Kubernetes cluster, which also disables SecurityGroups - type: boolean - externalNetwork: - description: |- - ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. - This option is ignored if DisableExternalNetwork is set to true. - - - If ExternalNetwork is defined it must refer to exactly one external network. - - - If ExternalNetwork is not defined or is empty the controller will use any - existing external network as long as there is only one. It is an - error if ExternalNetwork is not defined and there are multiple - external networks unless DisableExternalNetwork is also set. - - - If ExternalNetwork is not defined and there are no external networks - the controller will proceed as though DisableExternalNetwork was set. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID is provided, - the other filters cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - externalRouterIPs: - description: |- - ExternalRouterIPs is an array of externalIPs on the respective subnets. - This is necessary if the router needs a fixed ip in a specific subnet. - items: - properties: - fixedIP: - description: The FixedIP in the corresponding subnet - type: string - subnet: - description: The subnet in which the FixedIP is used for the - Gateway of this router - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the subnet. - It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not be - validated. - format: uuid - type: string - type: object - required: - - subnet - type: object - type: array - x-kubernetes-list-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this cluster. It is also to reconcile - machines unless overridden in the machine spec. - properties: - cloudName: - description: CloudName specifies the name of the entry in the - clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - managedSecurityGroups: - description: |- - ManagedSecurityGroups determines whether OpenStack security groups for the cluster - will be managed by the OpenStack provider or whether pre-existing security groups will - be specified as part of the configuration. - By default, the managed security groups have rules that allow the Kubelet, etcd, and the - Kubernetes API server to function correctly. - It's possible to add additional rules to the managed security groups. - When defined to an empty struct, the managed security groups will be created with the default rules. - properties: - allNodesSecurityGroupRules: - description: allNodesSecurityGroupRules defines the rules that - should be applied to all nodes. - items: - description: |- - SecurityGroupRuleSpec represent the basic information of the associated OpenStack - Security Group Role. - For now this is only used for the allNodesSecurityGroupRules but when we add - other security groups, we'll need to add a validation because - Remote* fields are mutually exclusive. - properties: - description: - description: description of the security group rule. - type: string - direction: - description: |- - direction in which the security group rule is applied. The only values - allowed are "ingress" or "egress". For a compute instance, an ingress - security group rule is applied to incoming (ingress) traffic for that - instance. An egress rule is applied to traffic leaving the instance. - type: string - etherType: - description: |- - etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the - ingress or egress rules. - type: string - name: - description: |- - name of the security group rule. - It's used to identify the rule so it can be patched and will not be sent to the OpenStack API. - type: string - portRangeMax: - description: |- - portRangeMax is a number in the range that is matched by the security group - rule. The portRangeMin attribute constrains the portRangeMax attribute. - type: integer - portRangeMin: - description: |- - portRangeMin is a number in the range that is matched by the security group - rule. If the protocol is TCP or UDP, this value must be less than or equal - to the value of the portRangeMax attribute. - type: integer - protocol: - description: protocol is the protocol that is matched by - the security group rule. - type: string - remoteGroupID: - description: |- - remoteGroupID is the remote group ID to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - type: string - remoteIPPrefix: - description: |- - remoteIPPrefix is the remote IP prefix to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - type: string - remoteManagedGroups: - description: |- - remoteManagedGroups is the remote managed groups to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - items: - enum: - - bastion - - controlplane - - worker - type: string - type: array - required: - - direction - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - allowAllInClusterTraffic: - default: false - description: AllowAllInClusterTraffic allows all ingress and egress - traffic between cluster nodes when set to true. - type: boolean - required: - - allowAllInClusterTraffic - type: object - managedSubnets: - description: |- - ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, - subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 - subnet is supported. If you leave this empty, no network will be created. - items: - properties: - allocationPools: - description: |- - AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. - If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from - outside of these ranges manually. - items: - properties: - end: - description: End represents the end of the AlloctionPool, - that is the highest IP of the pool. - type: string - start: - description: Start represents the start of the AllocationPool, - that is the lowest IP of the pool. - type: string - required: - - end - - start - type: object - type: array - cidr: - description: |- - CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. - This field is required when defining a subnet. - type: string - dnsNameservers: - description: |- - DNSNameservers holds a list of DNS server addresses that will be provided when creating - the subnet. These addresses need to have the same IP version as CIDR. - items: - type: string - type: array - required: - - cidr - type: object - maxItems: 1 - type: array - x-kubernetes-list-type: atomic - network: - description: |- - Network specifies an existing network to use if no ManagedSubnets - are specified. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID is provided, - the other filters cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - networkMTU: - description: |- - NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. - This value will be used only if the Cluster actuator creates the network. - If left empty, the network will have the default MTU defined in Openstack network service. - To use this field, the Openstack installation requires the net-mtu neutron API extension. - type: integer - router: - description: |- - Router specifies an existing router to be used if ManagedSubnets are - specified. If specified, no new router will be created. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - router. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the router to use. If ID is provided, - the other filters cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - subnets: - description: |- - Subnets specifies existing subnets to use if not ManagedSubnets are - specified. All subnets must be in the network specified by Network. - There can be zero, one, or two subnets. If no subnets are specified, - all subnets in Network will be used. If 2 subnets are specified, one - must be IPv4 and the other IPv6. - items: - description: SubnetParam specifies an OpenStack subnet to use. It - may be specified by either ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the subnet. - It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not be validated. - format: uuid - type: string - type: object - maxItems: 2 - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags to set on all resources in cluster which support - tags - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - identityRef - type: object - status: - description: OpenStackClusterStatus defines the observed state of OpenStackCluster. - properties: - apiServerLoadBalancer: - description: APIServerLoadBalancer describes the api server load balancer - if one exists - properties: - allowedCIDRs: - items: - type: string - type: array - id: - type: string - internalIP: - type: string - ip: - type: string - loadBalancerNetwork: - description: |- - LoadBalancerNetwork contains information about network and/or subnets which the - loadbalancer is allocated on. - If subnets are specified within the LoadBalancerNetwork currently only the first - subnet in the list is taken into account. - properties: - id: - type: string - name: - type: string - subnets: - description: Subnets is a list of subnets associated with - the default cluster network. Machines which use the default - cluster network will get an address from all of these subnets. - items: - description: Subnet represents basic information about the - associated OpenStack Neutron Subnet. - properties: - cidr: - type: string - id: - type: string - name: - type: string - tags: - items: - type: string - type: array - required: - - cidr - - id - - name - type: object - type: array - tags: - items: - type: string - type: array - required: - - id - - name - type: object - name: - type: string - tags: - items: - type: string - type: array - required: - - id - - internalIP - - ip - - name - type: object - bastion: - description: Bastion contains the information about the deployed bastion - host - properties: - floatingIP: - type: string - id: - type: string - ip: - type: string - name: - type: string - resolved: - description: |- - Resolved contains parts of the bastion's machine spec with all - external references fully resolved. - properties: - imageID: - description: ImageID is the ID of the image to use for the - machine and is calculated based on ImageFilter. - type: string - ports: - description: Ports is the fully resolved list of ports to - create for the machine. - items: - description: ResolvedPortSpec is a PortOpts with all contained - references fully resolved. - properties: - adminStateUp: - description: AdminStateUp specifies whether the port - should be created in the up (true) or down (false) - state. The default is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable description - for the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of subnet and/or - IP address to assign to the port. If specified, these - must be subnets of the port's network. - items: - description: ResolvedFixedIP is a FixedIP with the - Subnet resolved to an ID. - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If SubnetID - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: SubnetID is the id of a subnet to - create the fixed IP of a port in. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the host where - the port resides. - type: string - macAddress: - description: MACAddress specifies the MAC address of - the port. If not specified, the MAC address will be - generated. - type: string - name: - description: Name is the name of the port. - type: string - networkID: - description: NetworkID is the ID of the network the - port will be created in. - type: string - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables the - OVS hardware offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables the “trusted - mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or disables - the propagate uplink status on the port. - type: boolean - securityGroups: - description: SecurityGroups is a list of security group - IDs to assign to the port. - items: - type: string - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Trunk specifies whether trunking is enabled - at the port level. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single value_spec - key-value pair. - properties: - key: - description: Key is the key in the key-value pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the key-value - pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - required: - - description - - name - - networkID - type: object - type: array - serverGroupID: - description: ServerGroupID is the ID of the server group the - machine should be added to and is calculated based on ServerGroupFilter. - type: string - type: object - resources: - description: Resources contains references to OpenStack resources - created for the bastion. - properties: - ports: - description: Ports is the status of the ports created for - the machine. - items: - properties: - id: - description: ID is the unique identifier of the port. - type: string - required: - - id - type: object - type: array - type: object - sshKeyName: - type: string - state: - description: InstanceState describes the state of an OpenStack - instance. - type: string - type: object - bastionSecurityGroup: - description: |- - BastionSecurityGroup contains the information about the OpenStack - Security Group that needs to be applied to worker nodes. - properties: - id: - description: id of the security group - type: string - name: - description: name of the security group - type: string - required: - - id - - name - type: object - controlPlaneSecurityGroup: - description: |- - ControlPlaneSecurityGroup contains the information about the - OpenStack Security Group that needs to be applied to control plane - nodes. - properties: - id: - description: id of the security group - type: string - name: - description: name of the security group - type: string - required: - - id - - name - type: object - externalNetwork: - description: ExternalNetwork contains information about the external - network used for default ingress and egress traffic. - properties: - id: - type: string - name: - type: string - tags: - items: - type: string - type: array - required: - - id - - name - type: object - failureDomains: - additionalProperties: - description: |- - FailureDomainSpec is the Schema for Cluster API failure domains. - It allows controllers to understand how many failure domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains represent OpenStack availability zones - type: object - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the OpenStackCluster and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the OpenStackCluster's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of - OpenStackClusters can be added as events to the OpenStackCluster object - and/or logged in the controller's output. - type: string - failureReason: - description: |- - FailureReason will be set in the event that there is a terminal problem - reconciling the OpenStackCluster and will contain a succinct value suitable - for machine interpretation. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the OpenStackCluster's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of - OpenStackClusters can be added as events to the OpenStackCluster object - and/or logged in the controller's output. - type: string - network: - description: Network contains information about the created OpenStack - Network. - properties: - id: - type: string - name: - type: string - subnets: - description: Subnets is a list of subnets associated with the - default cluster network. Machines which use the default cluster - network will get an address from all of these subnets. - items: - description: Subnet represents basic information about the associated - OpenStack Neutron Subnet. - properties: - cidr: - type: string - id: - type: string - name: - type: string - tags: - items: - type: string - type: array - required: - - cidr - - id - - name - type: object - type: array - tags: - items: - type: string - type: array - required: - - id - - name - type: object - ready: - default: false - description: Ready is true when the cluster infrastructure is ready. - type: boolean - router: - description: Router describes the default cluster router - properties: - id: - type: string - ips: - items: - type: string - type: array - name: - type: string - tags: - items: - type: string - type: array - required: - - id - - name - type: object - workerSecurityGroup: - description: |- - WorkerSecurityGroup contains the information about the OpenStack - Security Group that needs to be applied to worker nodes. - properties: - id: - description: id of the security group - type: string - name: - description: name of the security group - type: string - required: - - id - - name - type: object - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclustertemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclustertemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index e2b9831ef..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackclustertemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1830 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: openstackclustertemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: OpenStackClusterTemplate - listKind: OpenStackClusterTemplateList - plural: openstackclustertemplates - shortNames: - - osct - singular: openstackclustertemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: OpenStackClusterTemplate is the Schema for the openstackclustertemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: OpenStackClusterTemplateSpec defines the desired state of - OpenStackClusterTemplate. - properties: - template: - description: OpenStackClusterTemplateResource describes the data needed - to create a OpenStackCluster from a template. - properties: - spec: - description: OpenStackClusterSpec defines the desired state of - OpenStackCluster. - properties: - apiServerFixedIP: - description: |- - APIServerFixedIP is the fixed IP which will be associated with the API server. - In the case where the API server has a floating IP but not a managed load balancer, - this field is not used. - If a managed load balancer is used and this field is not specified, a fixed IP will - be dynamically allocated for the load balancer. - If a managed load balancer is not used AND the API server floating IP is disabled, - this field MUST be specified and should correspond to a pre-allocated port that - holds the fixed IP to be used as a VIP. - type: string - apiServerFloatingIP: - description: |- - APIServerFloatingIP is the floatingIP which will be associated with the API server. - The floatingIP will be created if it does not already exist. - If not specified, a new floatingIP is allocated. - This field is not used if DisableAPIServerFloatingIP is set to true. - type: string - apiServerLoadBalancer: - description: |- - APIServerLoadBalancer configures the optional LoadBalancer for the APIServer. - If not specified, no load balancer will be created for the API server. - properties: - additionalPorts: - description: AdditionalPorts adds additional tcp ports - to the load balancer. - items: - type: integer - type: array - x-kubernetes-list-type: set - allowedCIDRs: - description: AllowedCIDRs restrict access to all API-Server - listeners to the given address CIDRs. - items: - type: string - type: array - x-kubernetes-list-type: set - availabilityZone: - description: AvailabilityZone is the failure domain that - will be used to create the APIServerLoadBalancer Spec. - type: string - enabled: - default: true - description: |- - Enabled defines whether a load balancer should be created. This value - defaults to true if an APIServerLoadBalancer is given. - - - There is no reason to set this to false. To disable creation of the - API server loadbalancer, omit the APIServerLoadBalancer field in the - cluster spec instead. - type: boolean - network: - description: Network defines which network should the - load balancer be allocated on. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an - OpenStack network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If - ID is provided, the other filters cannot be provided. - Must be in UUID format. - format: uuid - type: string - type: object - provider: - description: |- - Provider specifies name of a specific Octavia provider to use for the - API load balancer. The Octavia default will be used if it is not - specified. - type: string - subnets: - description: |- - Subnets define which subnets should the load balancer be allocated on. - It is expected that subnets are located on the network specified in this resource. - Only the first element is taken into account. - kubebuilder:validation:MaxLength:=2 - items: - description: SubnetParam specifies an OpenStack subnet - to use. It may be specified by either ID or filter, - but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select - the subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will - not be validated. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - required: - - enabled - type: object - apiServerPort: - description: |- - APIServerPort is the port on which the listener on the APIServer - will be created - type: integer - bastion: - description: |- - Bastion is the OpenStack instance to login the nodes - - - As a rolling update is not ideal during a bastion host session, we - prevent changes to a running bastion configuration. To make changes, it's required - to first set `enabled: false` which will remove the bastion and then changes can be made. - properties: - availabilityZone: - description: AvailabilityZone is the failure domain that - will be used to create the Bastion Spec. - type: string - enabled: - default: true - description: |- - Enabled means that bastion is enabled. The bastion is enabled by - default if this field is not specified. Set this field to false to disable the - bastion. - - - It is not currently possible to remove the bastion from the cluster - spec without first disabling it by setting this field to false and - waiting until the bastion has been deleted. - type: boolean - floatingIP: - description: |- - FloatingIP which will be associated to the bastion machine. It's the IP address, not UUID. - The floating IP should already exist and should not be associated with a port. If FIP of this address does not - exist, CAPO will try to create it, but by default only OpenStack administrators have privileges to do so. - format: ipv4 - type: string - spec: - description: Spec for the bastion itself - properties: - additionalBlockDevices: - description: AdditionalBlockDevices is a list of specifications - for additional block devices to attach to the server - instance - items: - description: AdditionalBlockDevice is a block device - to attach to the server. - properties: - name: - description: |- - Name of the block device in the context of a machine. - If the block device is a volume, the Cinder volume will be named - as a combination of the machine name and this name. - Also, this name will be used for tagging the block device. - Information about the block device tag can be obtained from the OpenStack - metadata API or the config drive. - Name cannot be 'root', which is reserved for the root volume. - type: string - sizeGiB: - description: SizeGiB is the size of the block - device in gibibytes (GiB). - minimum: 1 - type: integer - storage: - description: |- - Storage specifies the storage type of the block device and - additional storage options. - properties: - type: - description: |- - Type is the type of block device to create. - This can be either "Volume" or "Local". - type: string - volume: - description: Volume contains additional - storage options for a volume block device. - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from - is 'Name' or default - rule: '!has(self.from) || self.from - == ''Name'' ? has(self.name) : !has(self.name)' - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - type: object - required: - - type - type: object - required: - - name - - sizeGiB - - storage - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - configDrive: - description: Config Drive support - type: boolean - flavor: - description: The flavor reference for the flavor for - your server instance. - type: string - floatingIPPoolRef: - description: |- - floatingIPPoolRef is a reference to a IPPool that will be assigned - to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP - will be assigned to the OpenStackMachine. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being - referenced - type: string - name: - description: Name is the name of resource being - referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this machine. If not specified, the - credentials specified in the cluster will be used. - properties: - cloudName: - description: CloudName specifies the name of the - entry in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - image: - description: |- - The image to use for your server instance. - If the rootVolume is specified, this will be used when creating the root volume. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: |- - Filter describes a query for an image. If specified, the combination - of name and tags must return a single matching image or an error will - be raised. - minProperties: 1 - properties: - name: - description: The name of the desired image. - If specified, the combination of name and - tags must return a single matching image - or an error will be raised. - type: string - tags: - description: The tags associated with the - desired image. If specified, the combination - of name and tags must return a single matching - image or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the image. ID will - not be validated before use. - format: uuid - type: string - type: object - ports: - description: |- - Ports to be attached to the server instance. They are created if a port with the given name does not already exist. - If not specified a default port will be added for the default cluster network. - items: - properties: - adminStateUp: - description: AdminStateUp specifies whether - the port should be created in the up (true) - or down (false) state. The default is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable - description for the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of - subnet and/or IP address to assign to the - port. If specified, these must be subnets - of the port's network. - items: - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If Subnet - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: |- - Subnet is an openstack subnet query that will return the id of a subnet to create - the fixed IP of a port in. This query must not return more than one subnet. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter - to select the subnet. It must match - exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the - subnet. It will not be validated. - format: uuid - type: string - type: object - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the - host where the port resides. - type: string - macAddress: - description: MACAddress specifies the MAC address - of the port. If not specified, the MAC address - will be generated. - type: string - nameSuffix: - description: NameSuffix will be appended to - the name of the port if specified. If unspecified, - instead the 0-based index of the port in the - list is used. - type: string - network: - description: |- - Network is a query for an openstack network that the port will be created or discovered on. - This will fail if the query returns more than one network. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to - select an OpenStack network. If provided, - cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network - to use. If ID is provided, the other filters - cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables - the OVS hardware offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables - the “trusted mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or - disables the propagate uplink status on the - port. - type: boolean - securityGroups: - description: SecurityGroups is a list of the - names, uuids, filters or any combination these - of the security groups to assign to the instance. - items: - description: SecurityGroupParam specifies - an OpenStack security group. It may be specified - by ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query - to select an OpenStack security group. - If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security - group to use. If ID is provided, the - other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - tags: - description: |- - Tags applied to the port (and corresponding trunk, if a trunk is configured.) - These tags are applied in addition to the instance's tags, which will also be applied to the port. - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: |- - Trunk specifies whether trunking is enabled at the port level. If not - provided the value is inherited from the machine, or false for a - bastion host. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single - value_spec key-value pair. - properties: - key: - description: Key is the key in the key-value - pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the - key-value pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - type: object - type: array - providerID: - description: ProviderID is the unique identifier as - specified by the cloud provider. - type: string - rootVolume: - description: The volume metadata to boot from - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' - or default - rule: '!has(self.from) || self.from == ''Name'' - ? has(self.name) : !has(self.name)' - sizeGiB: - description: SizeGiB is the size of the block - device in gibibytes (GiB). - minimum: 1 - type: integer - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - required: - - sizeGiB - type: object - securityGroups: - description: The names of the security groups to assign - to the instance - items: - description: SecurityGroupParam specifies an OpenStack - security group. It may be specified by ID or filter, - but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select - an OpenStack security group. If provided, - cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group - to use. If ID is provided, the other filters - cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - type: array - serverGroup: - description: The server group to assign the machine - to. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select - an OpenStack server group. If provided, it cannot - be empty. - minProperties: 1 - properties: - name: - description: Name is the name of a server - group to look for. - type: string - type: object - id: - description: ID is the ID of the server group - to use. - format: uuid - type: string - type: object - serverMetadata: - description: Metadata mapping. Allows you to create - a map of key value pairs to add to the server instance. - items: - properties: - key: - description: Key is the server metadata key - maxLength: 255 - type: string - value: - description: Value is the server metadata value - maxLength: 255 - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - sshKeyName: - description: The ssh key to inject in the instance - type: string - tags: - description: |- - Tags which will be added to the machine and all dependent resources - which support them. These are in addition to Tags defined on the - cluster. - Requires Nova api 2.52 minimum! - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Whether the server instance is created - on a trunk port or not. - type: boolean - required: - - flavor - - image - type: object - type: object - x-kubernetes-validations: - - message: spec is required if bastion is enabled - rule: '!self.enabled || has(self.spec)' - controlPlaneAvailabilityZones: - description: |- - ControlPlaneAvailabilityZones is the set of availability zones which - control plane machines may be deployed to. - items: - type: string - type: array - x-kubernetes-list-type: set - controlPlaneEndpoint: - description: |- - ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. - It is normally populated automatically by the OpenStackCluster - controller during cluster provisioning. If it is set on creation the - control plane endpoint will use the values set here in preference to - values set elsewhere. - ControlPlaneEndpoint cannot be modified after ControlPlaneEndpoint.Host has been set. - properties: - host: - description: The hostname on which the API server is serving. - type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneOmitAvailabilityZone: - description: |- - ControlPlaneOmitAvailabilityZone causes availability zone to be - omitted when creating control plane nodes, allowing the Nova - scheduler to make a decision on which availability zone to use based - on other scheduling constraints - type: boolean - disableAPIServerFloatingIP: - description: |- - DisableAPIServerFloatingIP determines whether or not to attempt to attach a floating - IP to the API server. This allows for the creation of clusters when attaching a floating - IP to the API server (and hence, in many cases, exposing the API server to the internet) - is not possible or desirable, e.g. if using a shared VLAN for communication between - management and workload clusters or when the management cluster is inside the - project network. - This option requires that the API server use a VIP on the cluster network so that the - underlying machines can change without changing ControlPlaneEndpoint.Host. - When using a managed load balancer, this VIP will be managed automatically. - If not using a managed load balancer, cluster configuration will fail without additional - configuration to manage the VIP on the control plane machines, which falls outside of - the scope of this controller. - type: boolean - disableExternalNetwork: - description: |- - DisableExternalNetwork specifies whether or not to attempt to connect the cluster - to an external network. This allows for the creation of clusters when connecting - to an external network is not possible or desirable, e.g. if using a provider network. - type: boolean - disablePortSecurity: - description: |- - DisablePortSecurity disables the port security of the network created for the - Kubernetes cluster, which also disables SecurityGroups - type: boolean - externalNetwork: - description: |- - ExternalNetwork is the OpenStack Network to be used to get public internet to the VMs. - This option is ignored if DisableExternalNetwork is set to true. - - - If ExternalNetwork is defined it must refer to exactly one external network. - - - If ExternalNetwork is not defined or is empty the controller will use any - existing external network as long as there is only one. It is an - error if ExternalNetwork is not defined and there are multiple - external networks unless DisableExternalNetwork is also set. - - - If ExternalNetwork is not defined and there are no external networks - the controller will proceed as though DisableExternalNetwork was set. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - externalRouterIPs: - description: |- - ExternalRouterIPs is an array of externalIPs on the respective subnets. - This is necessary if the router needs a fixed ip in a specific subnet. - items: - properties: - fixedIP: - description: The FixedIP in the corresponding subnet - type: string - subnet: - description: The subnet in which the FixedIP is used - for the Gateway of this router - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select - the subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will - not be validated. - format: uuid - type: string - type: object - required: - - subnet - type: object - type: array - x-kubernetes-list-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this cluster. It is also to reconcile - machines unless overridden in the machine spec. - properties: - cloudName: - description: CloudName specifies the name of the entry - in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - managedSecurityGroups: - description: |- - ManagedSecurityGroups determines whether OpenStack security groups for the cluster - will be managed by the OpenStack provider or whether pre-existing security groups will - be specified as part of the configuration. - By default, the managed security groups have rules that allow the Kubelet, etcd, and the - Kubernetes API server to function correctly. - It's possible to add additional rules to the managed security groups. - When defined to an empty struct, the managed security groups will be created with the default rules. - properties: - allNodesSecurityGroupRules: - description: allNodesSecurityGroupRules defines the rules - that should be applied to all nodes. - items: - description: |- - SecurityGroupRuleSpec represent the basic information of the associated OpenStack - Security Group Role. - For now this is only used for the allNodesSecurityGroupRules but when we add - other security groups, we'll need to add a validation because - Remote* fields are mutually exclusive. - properties: - description: - description: description of the security group rule. - type: string - direction: - description: |- - direction in which the security group rule is applied. The only values - allowed are "ingress" or "egress". For a compute instance, an ingress - security group rule is applied to incoming (ingress) traffic for that - instance. An egress rule is applied to traffic leaving the instance. - type: string - etherType: - description: |- - etherType must be IPv4 or IPv6, and addresses represented in CIDR must match the - ingress or egress rules. - type: string - name: - description: |- - name of the security group rule. - It's used to identify the rule so it can be patched and will not be sent to the OpenStack API. - type: string - portRangeMax: - description: |- - portRangeMax is a number in the range that is matched by the security group - rule. The portRangeMin attribute constrains the portRangeMax attribute. - type: integer - portRangeMin: - description: |- - portRangeMin is a number in the range that is matched by the security group - rule. If the protocol is TCP or UDP, this value must be less than or equal - to the value of the portRangeMax attribute. - type: integer - protocol: - description: protocol is the protocol that is matched - by the security group rule. - type: string - remoteGroupID: - description: |- - remoteGroupID is the remote group ID to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - type: string - remoteIPPrefix: - description: |- - remoteIPPrefix is the remote IP prefix to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - type: string - remoteManagedGroups: - description: |- - remoteManagedGroups is the remote managed groups to be associated with this security group rule. - You can specify either remoteGroupID or remoteIPPrefix or remoteManagedGroups. - items: - enum: - - bastion - - controlplane - - worker - type: string - type: array - required: - - direction - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - allowAllInClusterTraffic: - default: false - description: AllowAllInClusterTraffic allows all ingress - and egress traffic between cluster nodes when set to - true. - type: boolean - required: - - allowAllInClusterTraffic - type: object - managedSubnets: - description: |- - ManagedSubnets describe OpenStack Subnets to be created. Cluster actuator will create a network, - subnets with the defined CIDR, and a router connected to these subnets. Currently only one IPv4 - subnet is supported. If you leave this empty, no network will be created. - items: - properties: - allocationPools: - description: |- - AllocationPools is an array of AllocationPool objects that will be applied to OpenStack Subnet being created. - If set, OpenStack will only allocate these IPs for Machines. It will still be possible to create ports from - outside of these ranges manually. - items: - properties: - end: - description: End represents the end of the AlloctionPool, - that is the highest IP of the pool. - type: string - start: - description: Start represents the start of the - AllocationPool, that is the lowest IP of the - pool. - type: string - required: - - end - - start - type: object - type: array - cidr: - description: |- - CIDR is representing the IP address range used to create the subnet, e.g. 10.0.0.0/24. - This field is required when defining a subnet. - type: string - dnsNameservers: - description: |- - DNSNameservers holds a list of DNS server addresses that will be provided when creating - the subnet. These addresses need to have the same IP version as CIDR. - items: - type: string - type: array - required: - - cidr - type: object - maxItems: 1 - type: array - x-kubernetes-list-type: atomic - network: - description: |- - Network specifies an existing network to use if no ManagedSubnets - are specified. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - networkMTU: - description: |- - NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. - This value will be used only if the Cluster actuator creates the network. - If left empty, the network will have the default MTU defined in Openstack network service. - To use this field, the Openstack installation requires the net-mtu neutron API extension. - type: integer - router: - description: |- - Router specifies an existing router to be used if ManagedSubnets are - specified. If specified, no new router will be created. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - router. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the router to use. If ID - is provided, the other filters cannot be provided. Must - be in UUID format. - format: uuid - type: string - type: object - subnets: - description: |- - Subnets specifies existing subnets to use if not ManagedSubnets are - specified. All subnets must be in the network specified by Network. - There can be zero, one, or two subnets. If no subnets are specified, - all subnets in Network will be used. If 2 subnets are specified, one - must be IPv4 and the other IPv6. - items: - description: SubnetParam specifies an OpenStack subnet to - use. It may be specified by either ID or filter, but not - both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the - subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will not - be validated. - format: uuid - type: string - type: object - maxItems: 2 - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags to set on all resources in cluster which - support tags - items: - type: string - type: array - x-kubernetes-list-type: set - required: - - identityRef - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackfloatingippools.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-openstackfloatingippools.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 180260385..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackfloatingippools.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,258 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1alpha1 - name: openstackfloatingippools.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: OpenStackFloatingIPPool - listKind: OpenStackFloatingIPPoolList - plural: openstackfloatingippools - singular: openstackfloatingippool - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: OpenStackFloatingIPPool is the Schema for the openstackfloatingippools - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: OpenStackFloatingIPPoolSpec defines the desired state of - OpenStackFloatingIPPool. - properties: - floatingIPNetwork: - description: FloatingIPNetwork is the external network to use for - floating ips, if there's only one external network it will be used - by default - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID is provided, - the other filters cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this pool. - properties: - cloudName: - description: CloudName specifies the name of the entry in the - clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - maxIPs: - description: |- - MaxIPs is the maximum number of floating ips that can be allocated from this pool, if nil there is no limit. - If set, the pool will stop allocating floating ips when it reaches this number of ClaimedIPs. - type: integer - preAllocatedFloatingIPs: - description: |- - PreAllocatedFloatingIPs is a list of floating IPs precreated in OpenStack that should be used by this pool. - These are used before allocating new ones and are not deleted from OpenStack when the pool is deleted. - items: - type: string - type: array - reclaimPolicy: - description: The stratergy to use for reclaiming floating ips when - they are released from a machine - enum: - - Retain - - Delete - type: string - required: - - identityRef - - reclaimPolicy - type: object - status: - description: OpenStackFloatingIPPoolStatus defines the observed state - of OpenStackFloatingIPPool. - properties: - availableIPs: - default: [] - items: - type: string - type: array - claimedIPs: - default: [] - items: - type: string - type: array - conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failedIPs: - description: FailedIPs contains a list of floating ips that failed - to be allocated - items: - type: string - type: array - floatingIPNetwork: - description: floatingIPNetwork contains information about the network - used for floating ips - properties: - id: - type: string - name: - type: string - tags: - items: - type: string - type: array - required: - - id - - name - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachines.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachines.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 54cdf2c76..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachines.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,1152 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: openstackmachines.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: OpenStackMachine - listKind: OpenStackMachineList - plural: openstackmachines - shortNames: - - osm - singular: openstackmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this OpenStackMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: OpenStack instance state - jsonPath: .status.instanceState - name: InstanceState - type: string - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: OpenStack instance ID - jsonPath: .spec.providerID - name: ProviderID - type: string - - description: Machine object which owns with this OpenStackMachine - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - type: string - - description: Time duration since creation of OpenStackMachine - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: OpenStackMachine is the Schema for the openstackmachines API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: OpenStackMachineSpec defines the desired state of OpenStackMachine. - properties: - additionalBlockDevices: - description: AdditionalBlockDevices is a list of specifications for - additional block devices to attach to the server instance - items: - description: AdditionalBlockDevice is a block device to attach to - the server. - properties: - name: - description: |- - Name of the block device in the context of a machine. - If the block device is a volume, the Cinder volume will be named - as a combination of the machine name and this name. - Also, this name will be used for tagging the block device. - Information about the block device tag can be obtained from the OpenStack - metadata API or the config drive. - Name cannot be 'root', which is reserved for the root volume. - type: string - sizeGiB: - description: SizeGiB is the size of the block device in gibibytes - (GiB). - minimum: 1 - type: integer - storage: - description: |- - Storage specifies the storage type of the block device and - additional storage options. - properties: - type: - description: |- - Type is the type of block device to create. - This can be either "Volume" or "Local". - type: string - volume: - description: Volume contains additional storage options - for a volume block device. - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' or default - rule: '!has(self.from) || self.from == ''Name'' ? - has(self.name) : !has(self.name)' - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - type: object - required: - - type - type: object - required: - - name - - sizeGiB - - storage - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - configDrive: - description: Config Drive support - type: boolean - flavor: - description: The flavor reference for the flavor for your server instance. - type: string - floatingIPPoolRef: - description: |- - floatingIPPoolRef is a reference to a IPPool that will be assigned - to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP - will be assigned to the OpenStackMachine. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this machine. If not specified, the - credentials specified in the cluster will be used. - properties: - cloudName: - description: CloudName specifies the name of the entry in the - clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - image: - description: |- - The image to use for your server instance. - If the rootVolume is specified, this will be used when creating the root volume. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: |- - Filter describes a query for an image. If specified, the combination - of name and tags must return a single matching image or an error will - be raised. - minProperties: 1 - properties: - name: - description: The name of the desired image. If specified, - the combination of name and tags must return a single matching - image or an error will be raised. - type: string - tags: - description: The tags associated with the desired image. If - specified, the combination of name and tags must return - a single matching image or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the image. ID will not be validated - before use. - format: uuid - type: string - type: object - ports: - description: |- - Ports to be attached to the server instance. They are created if a port with the given name does not already exist. - If not specified a default port will be added for the default cluster network. - items: - properties: - adminStateUp: - description: AdminStateUp specifies whether the port should - be created in the up (true) or down (false) state. The default - is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable description for - the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of subnet and/or IP - address to assign to the port. If specified, these must be - subnets of the port's network. - items: - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If Subnet - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: |- - Subnet is an openstack subnet query that will return the id of a subnet to create - the fixed IP of a port in. This query must not return more than one subnet. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select the - subnet. It must match exactly one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. It will - not be validated. - format: uuid - type: string - type: object - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the host where the port - resides. - type: string - macAddress: - description: MACAddress specifies the MAC address of the port. - If not specified, the MAC address will be generated. - type: string - nameSuffix: - description: NameSuffix will be appended to the name of the - port if specified. If unspecified, instead the 0-based index - of the port in the list is used. - type: string - network: - description: |- - Network is a query for an openstack network that the port will be created or discovered on. - This will fail if the query returns more than one network. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select an OpenStack - network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. If ID is - provided, the other filters cannot be provided. Must be - in UUID format. - format: uuid - type: string - type: object - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables the OVS hardware - offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables the “trusted - mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or disables the propagate - uplink status on the port. - type: boolean - securityGroups: - description: SecurityGroups is a list of the names, uuids, filters - or any combination these of the security groups to assign - to the instance. - items: - description: SecurityGroupParam specifies an OpenStack security - group. It may be specified by ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - security group. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group to use. - If ID is provided, the other filters cannot be provided. - Must be in UUID format. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - tags: - description: |- - Tags applied to the port (and corresponding trunk, if a trunk is configured.) - These tags are applied in addition to the instance's tags, which will also be applied to the port. - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: |- - Trunk specifies whether trunking is enabled at the port level. If not - provided the value is inherited from the machine, or false for a - bastion host. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single value_spec key-value - pair. - properties: - key: - description: Key is the key in the key-value pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the key-value pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - rootVolume: - description: The volume metadata to boot from - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' or default - rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) - : !has(self.name)' - sizeGiB: - description: SizeGiB is the size of the block device in gibibytes - (GiB). - minimum: 1 - type: integer - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - required: - - sizeGiB - type: object - securityGroups: - description: The names of the security groups to assign to the instance - items: - description: SecurityGroupParam specifies an OpenStack security - group. It may be specified by ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - security group. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group to use. If ID - is provided, the other filters cannot be provided. Must be - in UUID format. - format: uuid - type: string - type: object - type: array - serverGroup: - description: The server group to assign the machine to. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack server - group. If provided, it cannot be empty. - minProperties: 1 - properties: - name: - description: Name is the name of a server group to look for. - type: string - type: object - id: - description: ID is the ID of the server group to use. - format: uuid - type: string - type: object - serverMetadata: - description: Metadata mapping. Allows you to create a map of key value - pairs to add to the server instance. - items: - properties: - key: - description: Key is the server metadata key - maxLength: 255 - type: string - value: - description: Value is the server metadata value - maxLength: 255 - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - sshKeyName: - description: The ssh key to inject in the instance - type: string - tags: - description: |- - Tags which will be added to the machine and all dependent resources - which support them. These are in addition to Tags defined on the - cluster. - Requires Nova api 2.52 minimum! - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Whether the server instance is created on a trunk port - or not. - type: boolean - required: - - flavor - - image - type: object - status: - description: OpenStackMachineStatus defines the observed state of OpenStackMachine. - properties: - addresses: - description: Addresses contains the OpenStack instance associated - addresses. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: |- - Last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when - the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - A human readable message indicating details about the transition. - This field may be empty. - type: string - reason: - description: |- - The reason for the condition's last transition in CamelCase. - The specific API may choose whether or not this field is considered a guaranteed API. - This field may not be empty. - type: string - severity: - description: |- - Severity provides an explicit classification of Reason code, so the users or machines can immediately - understand the current situation and act accordingly. - The Severity field MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: |- - Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability to deconflict is important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: |- - FailureMessage will be set in the event that there is a terminal problem - reconciling the Machine and will contain a more verbose string suitable - for logging and human consumption. - - - This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over - time (like service outages), but instead indicate that something is - fundamentally wrong with the Machine's spec or the configuration of - the controller, and that manual intervention is required. Examples - of terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the - responsible controller itself being critically misconfigured. - - - Any transient errors that occur during the reconciliation of Machines - can be added as events to the Machine object and/or logged in the - controller's output. - type: string - failureReason: - description: MachineStatusError defines errors states for Machine - objects. - type: string - instanceID: - description: InstanceID is the OpenStack instance ID for this machine. - type: string - instanceState: - description: InstanceState is the state of the OpenStack instance - for this machine. - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - resolved: - description: |- - Resolved contains parts of the machine spec with all external - references fully resolved. - properties: - imageID: - description: ImageID is the ID of the image to use for the machine - and is calculated based on ImageFilter. - type: string - ports: - description: Ports is the fully resolved list of ports to create - for the machine. - items: - description: ResolvedPortSpec is a PortOpts with all contained - references fully resolved. - properties: - adminStateUp: - description: AdminStateUp specifies whether the port should - be created in the up (true) or down (false) state. The - default is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable description - for the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of subnet and/or - IP address to assign to the port. If specified, these - must be subnets of the port's network. - items: - description: ResolvedFixedIP is a FixedIP with the Subnet - resolved to an ID. - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If SubnetID - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: SubnetID is the id of a subnet to create - the fixed IP of a port in. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the host where the - port resides. - type: string - macAddress: - description: MACAddress specifies the MAC address of the - port. If not specified, the MAC address will be generated. - type: string - name: - description: Name is the name of the port. - type: string - networkID: - description: NetworkID is the ID of the network the port - will be created in. - type: string - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables the OVS - hardware offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables the “trusted - mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or disables the - propagate uplink status on the port. - type: boolean - securityGroups: - description: SecurityGroups is a list of security group - IDs to assign to the port. - items: - type: string - type: array - x-kubernetes-list-type: atomic - tags: - description: Tags applied to the port (and corresponding - trunk, if a trunk is configured.) - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Trunk specifies whether trunking is enabled - at the port level. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single value_spec - key-value pair. - properties: - key: - description: Key is the key in the key-value pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the key-value pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - required: - - description - - name - - networkID - type: object - type: array - serverGroupID: - description: ServerGroupID is the ID of the server group the machine - should be added to and is calculated based on ServerGroupFilter. - type: string - type: object - resources: - description: Resources contains references to OpenStack resources - created for the machine. - properties: - ports: - description: Ports is the status of the ports created for the - machine. - items: - properties: - id: - description: ID is the unique identifier of the port. - type: string - required: - - id - type: object - type: array - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachinetemplates.infrastructure.cluster.x-k8s.io.yaml b/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachinetemplates.infrastructure.cluster.x-k8s.io.yaml deleted file mode 100644 index 7c0b8921a..000000000 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-openstackmachinetemplates.infrastructure.cluster.x-k8s.io.yaml +++ /dev/null @@ -1,848 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.15.0 - creationTimestamp: null - labels: - cluster.x-k8s.io/v1beta1: v1beta1 - name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: OpenStackMachineTemplate - listKind: OpenStackMachineTemplateList - plural: openstackmachinetemplates - shortNames: - - osmt - singular: openstackmachinetemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: OpenStackMachineTemplate is the Schema for the openstackmachinetemplates - API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: OpenStackMachineTemplateSpec defines the desired state of - OpenStackMachineTemplate. - properties: - template: - description: OpenStackMachineTemplateResource describes the data needed - to create a OpenStackMachine from a template. - properties: - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - additionalBlockDevices: - description: AdditionalBlockDevices is a list of specifications - for additional block devices to attach to the server instance - items: - description: AdditionalBlockDevice is a block device to - attach to the server. - properties: - name: - description: |- - Name of the block device in the context of a machine. - If the block device is a volume, the Cinder volume will be named - as a combination of the machine name and this name. - Also, this name will be used for tagging the block device. - Information about the block device tag can be obtained from the OpenStack - metadata API or the config drive. - Name cannot be 'root', which is reserved for the root volume. - type: string - sizeGiB: - description: SizeGiB is the size of the block device - in gibibytes (GiB). - minimum: 1 - type: integer - storage: - description: |- - Storage specifies the storage type of the block device and - additional storage options. - properties: - type: - description: |- - Type is the type of block device to create. - This can be either "Volume" or "Local". - type: string - volume: - description: Volume contains additional storage - options for a volume block device. - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' - or default - rule: '!has(self.from) || self.from == ''Name'' - ? has(self.name) : !has(self.name)' - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - type: object - required: - - type - type: object - required: - - name - - sizeGiB - - storage - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - configDrive: - description: Config Drive support - type: boolean - flavor: - description: The flavor reference for the flavor for your - server instance. - type: string - floatingIPPoolRef: - description: |- - floatingIPPoolRef is a reference to a IPPool that will be assigned - to an IPAddressClaim. Once the IPAddressClaim is fulfilled, the FloatingIP - will be assigned to the OpenStackMachine. - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - identityRef: - description: |- - IdentityRef is a reference to a secret holding OpenStack credentials - to be used when reconciling this machine. If not specified, the - credentials specified in the cluster will be used. - properties: - cloudName: - description: CloudName specifies the name of the entry - in the clouds.yaml file to use. - type: string - name: - description: |- - Name is the name of a secret in the same namespace as the resource being provisioned. - The secret must contain a key named `clouds.yaml` which contains an OpenStack clouds.yaml file. - The secret may optionally contain a key named `cacert` containing a PEM-encoded CA certificate. - type: string - required: - - cloudName - - name - type: object - image: - description: |- - The image to use for your server instance. - If the rootVolume is specified, this will be used when creating the root volume. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: |- - Filter describes a query for an image. If specified, the combination - of name and tags must return a single matching image or an error will - be raised. - minProperties: 1 - properties: - name: - description: The name of the desired image. If specified, - the combination of name and tags must return a single - matching image or an error will be raised. - type: string - tags: - description: The tags associated with the desired - image. If specified, the combination of name and - tags must return a single matching image or an error - will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the image. ID will not - be validated before use. - format: uuid - type: string - type: object - ports: - description: |- - Ports to be attached to the server instance. They are created if a port with the given name does not already exist. - If not specified a default port will be added for the default cluster network. - items: - properties: - adminStateUp: - description: AdminStateUp specifies whether the port - should be created in the up (true) or down (false) - state. The default is up. - type: boolean - allowedAddressPairs: - description: |- - AllowedAddressPairs is a list of address pairs which Neutron will - allow the port to send traffic from in addition to the port's - addresses. If not specified, the MAC Address will be the MAC Address - of the port. Depending on the configuration of Neutron, it may be - supported to specify a CIDR instead of a specific IP address. - items: - properties: - ipAddress: - description: |- - IPAddress is the IP address of the allowed address pair. Depending on - the configuration of Neutron, it may be supported to specify a CIDR - instead of a specific IP address. - type: string - macAddress: - description: |- - MACAddress is the MAC address of the allowed address pair. If not - specified, the MAC address will be the MAC address of the port. - type: string - required: - - ipAddress - type: object - type: array - description: - description: Description is a human-readable description - for the port. - type: string - disablePortSecurity: - description: |- - DisablePortSecurity enables or disables the port security when set. - When not set, it takes the value of the corresponding field at the network level. - type: boolean - fixedIPs: - description: FixedIPs is a list of pairs of subnet and/or - IP address to assign to the port. If specified, these - must be subnets of the port's network. - items: - properties: - ipAddress: - description: |- - IPAddress is a specific IP address to assign to the port. If Subnet - is also specified, IPAddress must be a valid IP address in the - subnet. If Subnet is not specified, IPAddress must be a valid IP - address in any subnet of the port's network. - type: string - subnet: - description: |- - Subnet is an openstack subnet query that will return the id of a subnet to create - the fixed IP of a port in. This query must not return more than one subnet. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to - select the subnet. It must match exactly - one subnet. - minProperties: 1 - properties: - cidr: - type: string - description: - type: string - gatewayIP: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RAMode: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the uuid of the subnet. - It will not be validated. - format: uuid - type: string - type: object - type: object - type: array - x-kubernetes-list-type: atomic - hostID: - description: HostID specifies the ID of the host where - the port resides. - type: string - macAddress: - description: MACAddress specifies the MAC address of - the port. If not specified, the MAC address will be - generated. - type: string - nameSuffix: - description: NameSuffix will be appended to the name - of the port if specified. If unspecified, instead - the 0-based index of the port in the list is used. - type: string - network: - description: |- - Network is a query for an openstack network that the port will be created or discovered on. - This will fail if the query returns more than one network. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a filter to select - an OpenStack network. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the network to use. - If ID is provided, the other filters cannot be - provided. Must be in UUID format. - format: uuid - type: string - type: object - profile: - description: |- - Profile is a set of key-value pairs that are used for binding - details. We intentionally don't expose this as a map[string]string - because we only want to enable the users to set the values of the - keys that are known to work in OpenStack Networking API. See - https://docs.openstack.org/api-ref/network/v2/index.html?expanded=create-port-detail#create-port - To set profiles, your tenant needs permissions rule:create_port, and - rule:create_port:binding:profile - properties: - ovsHWOffload: - description: OVSHWOffload enables or disables the - OVS hardware offload feature. - type: boolean - trustedVF: - description: TrustedVF enables or disables the “trusted - mode” for the VF. - type: boolean - type: object - propagateUplinkStatus: - description: PropageteUplinkStatus enables or disables - the propagate uplink status on the port. - type: boolean - securityGroups: - description: SecurityGroups is a list of the names, - uuids, filters or any combination these of the security - groups to assign to the instance. - items: - description: SecurityGroupParam specifies an OpenStack - security group. It may be specified by ID or filter, - but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select - an OpenStack security group. If provided, cannot - be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group - to use. If ID is provided, the other filters - cannot be provided. Must be in UUID format. - format: uuid - type: string - type: object - type: array - x-kubernetes-list-type: atomic - tags: - description: |- - Tags applied to the port (and corresponding trunk, if a trunk is configured.) - These tags are applied in addition to the instance's tags, which will also be applied to the port. - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: |- - Trunk specifies whether trunking is enabled at the port level. If not - provided the value is inherited from the machine, or false for a - bastion host. - type: boolean - valueSpecs: - description: |- - Value specs are extra parameters to include in the API request with OpenStack. - This is an extension point for the API, so what they do and if they are supported, - depends on the specific OpenStack implementation. - items: - description: ValueSpec represents a single value_spec - key-value pair. - properties: - key: - description: Key is the key in the key-value pair. - type: string - name: - description: |- - Name is the name of the key-value pair. - This is just for identifying the pair and will not be sent to the OpenStack API. - type: string - value: - description: Value is the value in the key-value - pair. - type: string - required: - - key - - name - - value - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - vnicType: - description: |- - VNICType specifies the type of vNIC which this port should be - attached to. This is used to determine which mechanism driver(s) to - be used to bind the port. The valid values are normal, macvtap, - direct, baremetal, direct-physical, virtio-forwarder, smart-nic and - remote-managed, although these values will not be validated in this - API to ensure compatibility with future neutron changes or custom - implementations. What type of vNIC is actually available depends on - deployments. If not specified, the Neutron default value is used. - type: string - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - rootVolume: - description: The volume metadata to boot from - properties: - availabilityZone: - description: |- - AvailabilityZone is the volume availability zone to create the volume - in. If not specified, the volume will be created without an explicit - availability zone. - properties: - from: - default: Name - description: |- - From specifies where we will obtain the availability zone for the - volume. The options are "Name" and "Machine". If "Name" is specified - then the Name field must also be specified. If "Machine" is specified - the volume will use the value of FailureDomain, if any, from the - associated Machine. - enum: - - Name - - Machine - type: string - name: - description: |- - Name is the name of a volume availability zone to use. It is required - if From is "Name". The volume availability zone name may not contain - spaces. - minLength: 1 - pattern: ^[^ ]+$ - type: string - type: object - x-kubernetes-validations: - - message: name is required when from is 'Name' or default - rule: '!has(self.from) || self.from == ''Name'' ? has(self.name) - : !has(self.name)' - sizeGiB: - description: SizeGiB is the size of the block device in - gibibytes (GiB). - minimum: 1 - type: integer - type: - description: |- - Type is the Cinder volume type of the volume. - If omitted, the default Cinder volume type that is configured in the OpenStack cloud - will be used. - type: string - required: - - sizeGiB - type: object - securityGroups: - description: The names of the security groups to assign to - the instance - items: - description: SecurityGroupParam specifies an OpenStack security - group. It may be specified by ID or filter, but not both. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - security group. If provided, cannot be empty. - minProperties: 1 - properties: - description: - type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - type: object - id: - description: ID is the ID of the security group to use. - If ID is provided, the other filters cannot be provided. - Must be in UUID format. - format: uuid - type: string - type: object - type: array - serverGroup: - description: The server group to assign the machine to. - maxProperties: 1 - minProperties: 1 - properties: - filter: - description: Filter specifies a query to select an OpenStack - server group. If provided, it cannot be empty. - minProperties: 1 - properties: - name: - description: Name is the name of a server group to - look for. - type: string - type: object - id: - description: ID is the ID of the server group to use. - format: uuid - type: string - type: object - serverMetadata: - description: Metadata mapping. Allows you to create a map - of key value pairs to add to the server instance. - items: - properties: - key: - description: Key is the server metadata key - maxLength: 255 - type: string - value: - description: Value is the server metadata value - maxLength: 255 - type: string - required: - - key - - value - type: object - type: array - x-kubernetes-list-map-keys: - - key - x-kubernetes-list-type: map - sshKeyName: - description: The ssh key to inject in the instance - type: string - tags: - description: |- - Tags which will be added to the machine and all dependent resources - which support them. These are in addition to Tags defined on the - cluster. - Requires Nova api 2.52 minimum! - items: - type: string - type: array - x-kubernetes-list-type: set - trunk: - description: Whether the server instance is created on a trunk - port or not. - type: boolean - required: - - flavor - - image - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/hypershiftoperator/deploy/crds/kustomization.yml b/hypershiftoperator/deploy/crds/kustomization.yml deleted file mode 100644 index a1d45f367..000000000 --- a/hypershiftoperator/deploy/crds/kustomization.yml +++ /dev/null @@ -1,66 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - customresourcedefinition-hostedclusters.hypershift.openshift.io.yaml - - customresourcedefinition-routes-default.crd.yaml - - customresourcedefinition-machinepools.cluster.x-k8s.io.yaml - - customresourcedefinition-openstackmachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmpowervsmachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedmachinepools.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-agentmachines.capi-provider.agent-install.openshift.io.yaml - - customresourcedefinition-awsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedcontrolplanes.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-awsclusterstaticidentities.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-openstackfloatingippools.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-awsmachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedcontrolplanetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-certificaterevocationrequests.certificates.hypershift.openshift.io.yaml - - customresourcedefinition-clusters.cluster.x-k8s.io.yaml - - customresourcedefinition-machines.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmvpcclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-clustersizingconfigurations.scheduling.hypershift.openshift.io.yaml - - customresourcedefinition-ibmpowervsclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-monitoring.coreos.com_servicemonitors.yaml - - customresourcedefinition-clusterresourcesetbindings.addons.cluster.x-k8s.io.yaml - - customresourcedefinition-azureclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ipaddressclaims.ipam.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-kubevirtmachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-machinesets.cluster.x-k8s.io.yaml - - customresourcedefinition-awsclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-machinedeployments.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmpowervsmachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-kubevirtmachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmvpcclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-openstackclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmpowervsimages.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-agentclusters.capi-provider.agent-install.openshift.io.yaml - - customresourcedefinition-azureclusteridentities.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-nodepools.hypershift.openshift.io.yaml - - customresourcedefinition-agentmachinetemplates.capi-provider.agent-install.openshift.io.yaml - - customresourcedefinition-ibmpowervsclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-machinehealthchecks.cluster.x-k8s.io.yaml - - customresourcedefinition-monitoring.coreos.com_podmonitors.yaml - - customresourcedefinition-clusterresourcesets.addons.cluster.x-k8s.io.yaml - - customresourcedefinition-ipaddresses.ipam.cluster.x-k8s.io.yaml - - customresourcedefinition-awsendpointservices.hypershift.openshift.io.yaml - - customresourcedefinition-azureclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-awsclusterroleidentities.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedmachinepooltemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-certificatesigningrequestapprovals.certificates.hypershift.openshift.io.yaml - - customresourcedefinition-kubevirtclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-openstackmachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-kubevirtclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-monitoring.coreos.com_prometheusrules.yaml - - customresourcedefinition-awsclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmvpcmachines.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-openstackclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-ibmvpcmachinetemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-hostedcontrolplanes.hypershift.openshift.io.yaml - - customresourcedefinition-awsmachinepools.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedclusters.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-clusterclasses.cluster.x-k8s.io.yaml - - customresourcedefinition-azuremanagedclustertemplates.infrastructure.cluster.x-k8s.io.yaml - - customresourcedefinition-certificatesigningrequestapprovals.hypershift.openshift.io.yaml diff --git a/hypershiftoperator/deploy/helm/Chart.yaml b/hypershiftoperator/deploy/helm/Chart.yaml new file mode 100644 index 000000000..29ca2bad1 --- /dev/null +++ b/hypershiftoperator/deploy/helm/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +description: A Helm chart to install the Hypershift Operator and deps for ARO +name: aro-hcp-hypershift-operator +type: application +version: 0.1.0 diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_podmonitors.yaml b/hypershiftoperator/deploy/helm/crds/podmonitors.monitoring.coreos.com.yaml similarity index 100% rename from hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_podmonitors.yaml rename to hypershiftoperator/deploy/helm/crds/podmonitors.monitoring.coreos.com.yaml diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_prometheusrules.yaml b/hypershiftoperator/deploy/helm/crds/prometheusrules.monitoring.coreos.com.yaml similarity index 92% rename from hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_prometheusrules.yaml rename to hypershiftoperator/deploy/helm/crds/prometheusrules.monitoring.coreos.com.yaml index bd15e3a85..8bcf93f7b 100644 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_prometheusrules.yaml +++ b/hypershiftoperator/deploy/helm/crds/prometheusrules.monitoring.coreos.com.yaml @@ -3,8 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - operator.prometheus.io/version: 0.76.1 + controller-gen.kubebuilder.io/version: v0.16.5 + operator.prometheus.io/version: 0.78.1 name: prometheusrules.monitoring.coreos.com spec: group: monitoring.coreos.com @@ -75,6 +75,14 @@ spec: More info: https://github.com/thanos-io/thanos/blob/main/docs/components/rule.md#partial-response pattern: ^(?i)(abort|warn)?$ type: string + query_offset: + description: |- + Defines the offset the rule evaluation timestamp of this particular group by the specified duration into the past. + + It requires Prometheus >= v2.53.0. + It is not supported for ThanosRuler. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string rules: description: List of alerting and recording rules. items: diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-routes-default.crd.yaml b/hypershiftoperator/deploy/helm/crds/routes.route.openshift.io.yaml similarity index 52% rename from hypershiftoperator/deploy/crds/customresourcedefinition-routes-default.crd.yaml rename to hypershiftoperator/deploy/helm/crds/routes.route.openshift.io.yaml index 615e64e46..ed0665f53 100644 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-routes-default.crd.yaml +++ b/hypershiftoperator/deploy/helm/crds/routes.route.openshift.io.yaml @@ -33,38 +33,49 @@ spec: name: v1 schema: openAPIV3Schema: - description: "A route allows developers to expose services through an HTTP(S) - aware load balancing and proxy layer via a public DNS entry. The route may - further specify TLS options and a certificate, or specify a public CNAME - that the router should also accept for HTTP and HTTPS traffic. An administrator - typically configures their router to be visible outside the cluster firewall, - and may also add additional security, caching, or traffic controls on the - service content. Routers usually talk directly to the service endpoints. - \n Once a route is created, the `host` field may not be changed. Generally, - routers use the oldest route with a given host when resolving conflicts. - \n Routers are subject to additional customization and may support additional - controls via the annotations field. \n Because administrators may configure - multiple routers, the route status field is used to return information to - clients about the names and states of the route under each router. If a - client chooses a duplicate name, for instance, the route status conditions - are used to indicate the route cannot be chosen. \n To enable HTTP/2 ALPN - on a route it requires a custom (non-wildcard) certificate. This prevents - connection coalescing by clients, notably web browsers. We do not support - HTTP/2 ALPN on routes that use the default certificate because of the risk - of connection re-use/coalescing. Routes that do not have their own custom - certificate will not be HTTP/2 ALPN-enabled on either the frontend or the - backend. \n Compatibility level 1: Stable within a major release for a minimum - of 12 months or 3 minor releases (whichever is longer)." + description: |- + A route allows developers to expose services through an HTTP(S) aware load balancing and proxy + layer via a public DNS entry. The route may further specify TLS options and a certificate, or + specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An + administrator typically configures their router to be visible outside the cluster firewall, and + may also add additional security, caching, or traffic controls on the service content. Routers + usually talk directly to the service endpoints. + + Once a route is created, the `host` field may not be changed. Generally, routers use the oldest + route with a given host when resolving conflicts. + + Routers are subject to additional customization and may support additional controls via the + annotations field. + + Because administrators may configure multiple routers, the route status field is used to + return information to clients about the names and states of the route under each router. + If a client chooses a duplicate name, for instance, the route status conditions are used + to indicate the route cannot be chosen. + + To enable HTTP/2 ALPN on a route it requires a custom + (non-wildcard) certificate. This prevents connection coalescing by + clients, notably web browsers. We do not support HTTP/2 ALPN on + routes that use the default certificate because of the risk of + connection re-use/coalescing. Routes that do not have their own + custom certificate will not be HTTP/2 ALPN-enabled on either the + frontend or the backend. + + Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). 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' + 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' + 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 @@ -98,14 +109,14 @@ spec: description: spec is the desired state of the route properties: alternateBackends: - description: alternateBackends allows up to 3 additional backends - to be assigned to the route. Only the Service kind is allowed, and - it will be defaulted to Service. Use the weight field in RouteTargetReference - object to specify relative preference. + description: |- + alternateBackends allows up to 3 additional backends to be assigned to the route. + Only the Service kind is allowed, and it will be defaulted to Service. + Use the weight field in RouteTargetReference object to specify relative preference. items: - description: RouteTargetReference specifies the target that resolve - into endpoints. Only the 'Service' kind is allowed. Use 'weight' - field to emphasize one over others. + description: |- + RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service' + kind is allowed. Use 'weight' field to emphasize one over others. properties: kind: default: Service @@ -122,9 +133,9 @@ spec: type: string weight: default: 100 - description: weight as an integer between 0 and 256, default - 100, that specifies the target's relative weight against other - target reference objects. 0 suppresses requests to this backend. + description: |- + weight as an integer between 0 and 256, default 100, that specifies the target's relative weight + against other target reference objects. 0 suppresses requests to this backend. format: int32 maximum: 256 minimum: 0 @@ -140,8 +151,10 @@ spec: - kind x-kubernetes-list-type: map host: - description: host is an alias/DNS that points to the service. Optional. - If not specified a route name will typically be automatically chosen. + description: |- + host is an alias/DNS that points to the service. Optional. + If not specified a route name will typically be automatically + chosen. Must follow DNS952 subdomain conventions. maxLength: 253 pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ @@ -150,55 +163,51 @@ spec: description: httpHeaders defines policy for HTTP headers. properties: actions: - description: 'actions specifies options for modifying headers - and their values. Note that this option only applies to cleartext - HTTP connections and to secure HTTP connections for which the - ingress controller terminates encryption (that is, edge-terminated - or reencrypt connections). Headers cannot be modified for TLS - passthrough connections. Setting the HSTS (`Strict-Transport-Security`) - header is not supported via actions. `Strict-Transport-Security` - may only be configured using the "haproxy.router.openshift.io/hsts_header" - route annotation, and only in accordance with the policy specified - in Ingress.Spec.RequiredHSTSPolicies. In case of HTTP request - headers, the actions specified in spec.httpHeaders.actions on - the Route will be executed after the actions specified in the - IngressController''s spec.httpHeaders.actions field. In case - of HTTP response headers, the actions specified in spec.httpHeaders.actions - on the IngressController will be executed after the actions - specified in the Route''s spec.httpHeaders.actions field. The - headers set via this API will not appear in access logs. Any - actions defined here are applied after any actions related to - the following other fields: cache-control, spec.clientTLS, spec.httpHeaders.forwardedHeaderPolicy, - spec.httpHeaders.uniqueId, and spec.httpHeaders.headerNameCaseAdjustments. - The following header names are reserved and may not be modified - via this API: Strict-Transport-Security, Proxy, Cookie, Set-Cookie. - Note that the total size of all net added headers *after* interpolating - dynamic values must not exceed the value of spec.tuningOptions.headerBufferMaxRewriteBytes - on the IngressController. Please refer to the documentation - for that API field for more details.' + description: |- + actions specifies options for modifying headers and their values. + Note that this option only applies to cleartext HTTP connections + and to secure HTTP connections for which the ingress controller + terminates encryption (that is, edge-terminated or reencrypt + connections). Headers cannot be modified for TLS passthrough + connections. + Setting the HSTS (`Strict-Transport-Security`) header is not supported via actions. + `Strict-Transport-Security` may only be configured using the "haproxy.router.openshift.io/hsts_header" + route annotation, and only in accordance with the policy specified in Ingress.Spec.RequiredHSTSPolicies. + In case of HTTP request headers, the actions specified in spec.httpHeaders.actions on the Route will be executed after + the actions specified in the IngressController's spec.httpHeaders.actions field. + In case of HTTP response headers, the actions specified in spec.httpHeaders.actions on the IngressController will be + executed after the actions specified in the Route's spec.httpHeaders.actions field. + The headers set via this API will not appear in access logs. + Any actions defined here are applied after any actions related to the following other fields: + cache-control, spec.clientTLS, + spec.httpHeaders.forwardedHeaderPolicy, spec.httpHeaders.uniqueId, + and spec.httpHeaders.headerNameCaseAdjustments. + The following header names are reserved and may not be modified via this API: + Strict-Transport-Security, Proxy, Cookie, Set-Cookie. + Note that the total size of all net added headers *after* interpolating dynamic values + must not exceed the value of spec.tuningOptions.headerBufferMaxRewriteBytes on the + IngressController. Please refer to the documentation + for that API field for more details. properties: request: - description: 'request is a list of HTTP request headers to - modify. Currently, actions may define to either `Set` or - `Delete` headers values. Actions defined here will modify - the request headers of all requests made through a route. - These actions are applied to a specific Route defined within - a cluster i.e. connections made through a route. Currently, - actions may define to either `Set` or `Delete` headers values. - Route actions will be executed after IngressController actions - for request headers. Actions are applied in sequence as - defined in this list. A maximum of 20 request header actions - may be configured. You can use this field to specify HTTP - request headers that should be set or deleted when forwarding - connections from the client to your application. Sample - fetchers allowed are "req.hdr" and "ssl_c_der". Converters - allowed are "lower" and "base64". Example header values: - "%[req.hdr(X-target),lower]", "%{+Q}[ssl_c_der,base64]". - Any request header configuration applied directly via a - Route resource using this API will override header configuration - for a header of the same name applied via spec.httpHeaders.actions - on the IngressController or route annotation. Note: This - field cannot be used if your route uses TLS passthrough.' + description: |- + request is a list of HTTP request headers to modify. + Currently, actions may define to either `Set` or `Delete` headers values. + Actions defined here will modify the request headers of all requests made through a route. + These actions are applied to a specific Route defined within a cluster i.e. connections made through a route. + Currently, actions may define to either `Set` or `Delete` headers values. + Route actions will be executed after IngressController actions for request headers. + Actions are applied in sequence as defined in this list. + A maximum of 20 request header actions may be configured. + You can use this field to specify HTTP request headers that should be set or deleted + when forwarding connections from the client to your application. + Sample fetchers allowed are "req.hdr" and "ssl_c_der". + Converters allowed are "lower" and "base64". + Example header values: "%[req.hdr(X-target),lower]", "%{+Q}[ssl_c_der,base64]". + Any request header configuration applied directly via a Route resource using this API + will override header configuration for a header of the same name applied via + spec.httpHeaders.actions on the IngressController or route annotation. + Note: This field cannot be used if your route uses TLS passthrough. items: description: RouteHTTPHeader specifies configuration for setting or deleting an HTTP header. @@ -208,25 +217,20 @@ spec: headers, such as setting or deleting headers. properties: set: - description: 'set defines the HTTP header that should - be set: added if it doesn''t exist or replaced - if it does. This field is required when type is - Set and forbidden otherwise.' + description: |- + set defines the HTTP header that should be set: added if it doesn't exist or replaced if it does. + This field is required when type is Set and forbidden otherwise. properties: value: - description: value specifies a header value. - Dynamic values can be added. The value will - be interpreted as an HAProxy format string - as defined in http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#8.2.6 - and may use HAProxy's %[] syntax and otherwise - must be a valid HTTP header value as defined - in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2. - The value of this field must be no more than - 16384 characters in length. Note that the - total size of all net added headers *after* - interpolating dynamic values must not exceed - the value of spec.tuningOptions.headerBufferMaxRewriteBytes - on the IngressController. + description: |- + value specifies a header value. + Dynamic values can be added. The value will be interpreted as an HAProxy format string as defined in + http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#8.2.6 and may use HAProxy's %[] syntax and + otherwise must be a valid HTTP header value as defined in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2. + The value of this field must be no more than 16384 characters in length. + Note that the total size of all net added headers *after* interpolating dynamic values + must not exceed the value of spec.tuningOptions.headerBufferMaxRewriteBytes on the + IngressController. maxLength: 16384 minLength: 1 type: string @@ -234,11 +238,11 @@ spec: - value type: object type: - description: type defines the type of the action - to be applied on the header. Possible values are - Set or Delete. Set allows you to set HTTP request - and response headers. Delete allows you to delete - HTTP request and response headers. + description: |- + type defines the type of the action to be applied on the header. + Possible values are Set or Delete. + Set allows you to set HTTP request and response headers. + Delete allows you to delete HTTP request and response headers. enum: - Set - Delete @@ -252,15 +256,14 @@ spec: rule: 'has(self.type) && self.type == ''Set'' ? has(self.set) : !has(self.set)' name: - description: 'name specifies the name of a header on - which to perform an action. Its value must be a valid - HTTP header name as defined in RFC 2616 section 4.2. - The name must consist only of alphanumeric and the - following special characters, "-!#$%&''*+.^_`". The - following header names are reserved and may not be - modified via this API: Strict-Transport-Security, - Proxy, Cookie, Set-Cookie. It must be no more than - 255 characters in length. Header name must be unique.' + description: |- + name specifies the name of a header on which to perform an action. Its value must be a valid HTTP header + name as defined in RFC 2616 section 4.2. + The name must consist only of alphanumeric and the following special characters, "-!#$%&'*+.^_`". + The following header names are reserved and may not be modified via this API: + Strict-Transport-Security, Proxy, Cookie, Set-Cookie. + It must be no more than 255 characters in length. + Header name must be unique. maxLength: 255 minLength: 1 pattern: ^[-!#$%&'*+.0-9A-Z^_`a-z|~]+$ @@ -299,22 +302,20 @@ spec: rule: self.all(key, key.action.type == "Delete" || (has(key.action.set) && key.action.set.value.matches('^(?:%(?:%|(?:\\{[-+]?[QXE](?:,[-+]?[QXE])*\\})?\\[(?:req\\.hdr\\([0-9A-Za-z-]+\\)|ssl_c_der)(?:,(?:lower|base64))*\\])|[^%[:cntrl:]])+$'))) response: - description: 'response is a list of HTTP response headers - to modify. Currently, actions may define to either `Set` - or `Delete` headers values. Actions defined here will modify - the response headers of all requests made through a route. - These actions are applied to a specific Route defined within - a cluster i.e. connections made through a route. Route actions - will be executed before IngressController actions for response - headers. Actions are applied in sequence as defined in this - list. A maximum of 20 response header actions may be configured. - You can use this field to specify HTTP response headers - that should be set or deleted when forwarding responses - from your application to the client. Sample fetchers allowed - are "res.hdr" and "ssl_c_der". Converters allowed are "lower" - and "base64". Example header values: "%[res.hdr(X-target),lower]", - "%{+Q}[ssl_c_der,base64]". Note: This field cannot be used - if your route uses TLS passthrough.' + description: |- + response is a list of HTTP response headers to modify. + Currently, actions may define to either `Set` or `Delete` headers values. + Actions defined here will modify the response headers of all requests made through a route. + These actions are applied to a specific Route defined within a cluster i.e. connections made through a route. + Route actions will be executed before IngressController actions for response headers. + Actions are applied in sequence as defined in this list. + A maximum of 20 response header actions may be configured. + You can use this field to specify HTTP response headers that should be set or deleted + when forwarding responses from your application to the client. + Sample fetchers allowed are "res.hdr" and "ssl_c_der". + Converters allowed are "lower" and "base64". + Example header values: "%[res.hdr(X-target),lower]", "%{+Q}[ssl_c_der,base64]". + Note: This field cannot be used if your route uses TLS passthrough. items: description: RouteHTTPHeader specifies configuration for setting or deleting an HTTP header. @@ -324,25 +325,20 @@ spec: headers, such as setting or deleting headers. properties: set: - description: 'set defines the HTTP header that should - be set: added if it doesn''t exist or replaced - if it does. This field is required when type is - Set and forbidden otherwise.' + description: |- + set defines the HTTP header that should be set: added if it doesn't exist or replaced if it does. + This field is required when type is Set and forbidden otherwise. properties: value: - description: value specifies a header value. - Dynamic values can be added. The value will - be interpreted as an HAProxy format string - as defined in http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#8.2.6 - and may use HAProxy's %[] syntax and otherwise - must be a valid HTTP header value as defined - in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2. - The value of this field must be no more than - 16384 characters in length. Note that the - total size of all net added headers *after* - interpolating dynamic values must not exceed - the value of spec.tuningOptions.headerBufferMaxRewriteBytes - on the IngressController. + description: |- + value specifies a header value. + Dynamic values can be added. The value will be interpreted as an HAProxy format string as defined in + http://cbonte.github.io/haproxy-dconv/2.6/configuration.html#8.2.6 and may use HAProxy's %[] syntax and + otherwise must be a valid HTTP header value as defined in https://datatracker.ietf.org/doc/html/rfc7230#section-3.2. + The value of this field must be no more than 16384 characters in length. + Note that the total size of all net added headers *after* interpolating dynamic values + must not exceed the value of spec.tuningOptions.headerBufferMaxRewriteBytes on the + IngressController. maxLength: 16384 minLength: 1 type: string @@ -350,11 +346,11 @@ spec: - value type: object type: - description: type defines the type of the action - to be applied on the header. Possible values are - Set or Delete. Set allows you to set HTTP request - and response headers. Delete allows you to delete - HTTP request and response headers. + description: |- + type defines the type of the action to be applied on the header. + Possible values are Set or Delete. + Set allows you to set HTTP request and response headers. + Delete allows you to delete HTTP request and response headers. enum: - Set - Delete @@ -368,15 +364,14 @@ spec: rule: 'has(self.type) && self.type == ''Set'' ? has(self.set) : !has(self.set)' name: - description: 'name specifies the name of a header on - which to perform an action. Its value must be a valid - HTTP header name as defined in RFC 2616 section 4.2. - The name must consist only of alphanumeric and the - following special characters, "-!#$%&''*+.^_`". The - following header names are reserved and may not be - modified via this API: Strict-Transport-Security, - Proxy, Cookie, Set-Cookie. It must be no more than - 255 characters in length. Header name must be unique.' + description: |- + name specifies the name of a header on which to perform an action. Its value must be a valid HTTP header + name as defined in RFC 2616 section 4.2. + The name must consist only of alphanumeric and the following special characters, "-!#$%&'*+.^_`". + The following header names are reserved and may not be modified via this API: + Strict-Transport-Security, Proxy, Cookie, Set-Cookie. + It must be no more than 255 characters in length. + Header name must be unique. maxLength: 255 minLength: 1 pattern: ^[-!#$%&'*+.0-9A-Z^_`a-z|~]+$ @@ -422,9 +417,10 @@ spec: pattern: ^/ type: string port: - description: If specified, the port to be used by the router. Most - routers will use all endpoints exposed by the service by default - - set this value to instruct routers which port to use. + description: |- + If specified, the port to be used by the router. Most routers will use all + endpoints exposed by the service by default - set this value to instruct routers + which port to use. properties: targetPort: allOf: @@ -443,19 +439,19 @@ spec: - targetPort type: object subdomain: - description: "subdomain is a DNS subdomain that is requested within - the ingress controller's domain (as a subdomain). If host is set - this field is ignored. An ingress controller may choose to ignore - this suggested name, in which case the controller will report the - assigned name in the status.ingress array or refuse to admit the - route. If this value is set and the server does not support this - field host will be populated automatically. Otherwise host is left - empty. The field may have multiple parts separated by a dot, but - not all ingress controllers may honor the request. This field may - not be changed after creation except by a user with the update routes/custom-host - permission. \n Example: subdomain `frontend` automatically receives - the router subdomain `apps.mycluster.com` to have a full hostname - `frontend.apps.mycluster.com`." + description: |- + subdomain is a DNS subdomain that is requested within the ingress controller's + domain (as a subdomain). If host is set this field is ignored. An ingress + controller may choose to ignore this suggested name, in which case the controller + will report the assigned name in the status.ingress array or refuse to admit the + route. If this value is set and the server does not support this field host will + be populated automatically. Otherwise host is left empty. The field may have + multiple parts separated by a dot, but not all ingress controllers may honor + the request. This field may not be changed after creation except by a user with + the update routes/custom-host permission. + + Example: subdomain `frontend` automatically receives the router subdomain + `apps.mycluster.com` to have a full hostname `frontend.apps.mycluster.com`. maxLength: 253 pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ type: string @@ -493,30 +489,30 @@ spec: contents type: string certificate: - description: certificate provides certificate contents. This should - be a single serving certificate, not a certificate chain. Do - not include a CA certificate. + description: |- + certificate provides certificate contents. This should be a single serving certificate, not a certificate + chain. Do not include a CA certificate. type: string destinationCACertificate: - description: destinationCACertificate provides the contents of - the ca certificate of the final destination. When using reencrypt - termination this file should be provided in order to have routers - use it for health checks on the secure connection. If this field - is not specified, the router may provide its own destination - CA and perform hostname validation using the short service name - (service.namespace.svc), which allows infrastructure generated - certificates to automatically verify. + description: |- + destinationCACertificate provides the contents of the ca certificate of the final destination. When using reencrypt + termination this file should be provided in order to have routers use it for health checks on the secure connection. + If this field is not specified, the router may provide its own destination CA and perform hostname validation using + the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically + verify. type: string insecureEdgeTerminationPolicy: - description: "insecureEdgeTerminationPolicy indicates the desired - behavior for insecure connections to a route. While each router - may make its own decisions on which ports to expose, this is - normally port 80. \n If a route does not specify insecureEdgeTerminationPolicy, - then the default behavior is \"None\". \n * Allow - traffic - is sent to the server on the insecure port (edge/reencrypt terminations - only). \n * None - no traffic is allowed on the insecure port - (default). \n * Redirect - clients are redirected to the secure - port." + description: |- + insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While + each router may make its own decisions on which ports to expose, this is normally port 80. + + If a route does not specify insecureEdgeTerminationPolicy, then the default behavior is "None". + + * Allow - traffic is sent to the server on the insecure port (edge/reencrypt terminations only). + + * None - no traffic is allowed on the insecure port (default). + + * Redirect - clients are redirected to the secure port. enum: - Allow - None @@ -527,14 +523,14 @@ spec: description: key provides key file contents type: string termination: - description: "termination indicates termination type. \n * edge - - TLS termination is done by the router and http is used to - communicate with the backend (default) * passthrough - Traffic - is sent straight to the destination without the router providing - TLS termination * reencrypt - TLS termination is done by the - router and https is used to communicate with the backend \n - Note: passthrough termination is incompatible with httpHeader - actions" + description: |- + termination indicates termination type. + + * edge - TLS termination is done by the router and http is used to communicate with the backend (default) + * passthrough - Traffic is sent straight to the destination without the router providing TLS termination + * reencrypt - TLS termination is done by the router and https is used to communicate with the backend + + Note: passthrough termination is incompatible with httpHeader actions enum: - edge - reencrypt @@ -550,10 +546,10 @@ spec: ? !((self.termination==''passthrough'') && (self.insecureEdgeTerminationPolicy==''Allow'')) : true' to: - description: to is an object the route should use as the primary backend. - Only the Service kind is allowed, and it will be defaulted to Service. - If the weight field (0-256 default 100) is set to zero, no traffic - will be sent to this backend. + description: |- + to is an object the route should use as the primary backend. Only the Service kind + is allowed, and it will be defaulted to Service. If the weight field (0-256 default 100) + is set to zero, no traffic will be sent to this backend. properties: kind: default: Service @@ -570,9 +566,9 @@ spec: type: string weight: default: 100 - description: weight as an integer between 0 and 256, default 100, - that specifies the target's relative weight against other target - reference objects. 0 suppresses requests to this backend. + description: |- + weight as an integer between 0 and 256, default 100, that specifies the target's relative weight + against other target reference objects. 0 suppresses requests to this backend. format: int32 maximum: 256 minimum: 0 @@ -583,8 +579,9 @@ spec: type: object wildcardPolicy: default: None - description: Wildcard policy if any for the route. Currently only - 'Subdomain' or 'None' is allowed. + description: |- + Wildcard policy if any for the route. + Currently only 'Subdomain' or 'None' is allowed. enum: - None - Subdomain @@ -601,9 +598,10 @@ spec: description: status is the current state of the route properties: ingress: - description: ingress describes the places where the route may be exposed. - The list of ingress points may contain duplicate Host or RouterName - values. Routes are considered live once they are `Ready` + description: |- + ingress describes the places where the route may be exposed. The list of + ingress points may contain duplicate Host or RouterName values. Routes + are considered live once they are `Ready` items: description: RouteIngress holds information about the places where a route is exposed. @@ -611,8 +609,9 @@ spec: conditions: description: Conditions is the state of the route, may be empty. items: - description: RouteIngressCondition contains details for the - current condition of this route on a particular router. + description: |- + RouteIngressCondition contains details for the current condition of this route on a particular + router. properties: lastTransitionTime: description: RFC 3339 date and time when this condition @@ -624,16 +623,19 @@ spec: about last transition. type: string reason: - description: (brief) reason for the condition's last transition, - and is usually a machine and human readable constant + description: |- + (brief) reason for the condition's last transition, and is usually a machine and human + readable constant type: string status: - description: Status is the status of the condition. Can - be True, False, Unknown. + description: |- + Status is the status of the condition. + Can be True, False, Unknown. type: string type: - description: Type is the type of the condition. Currently - only Admitted or UnservableInFutureVersions. + description: |- + Type is the type of the condition. + Currently only Admitted or UnservableInFutureVersions. type: string required: - status @@ -648,10 +650,9 @@ spec: exposed; this value is required type: string routerCanonicalHostname: - description: CanonicalHostname is the external host name for - the router that can be used as a CNAME for the host requested - for this route. This value is optional and may not be set - in all cases. + description: |- + CanonicalHostname is the external host name for the router that can be used as a CNAME + for the host requested for this route. This value is optional and may not be set in all cases. type: string routerName: description: Name is a name chosen by the router to identify diff --git a/hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_servicemonitors.yaml b/hypershiftoperator/deploy/helm/crds/servicemonitors.monitoring.coreos.com.yaml similarity index 97% rename from hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_servicemonitors.yaml rename to hypershiftoperator/deploy/helm/crds/servicemonitors.monitoring.coreos.com.yaml index 9732e0384..fcd004d9b 100644 --- a/hypershiftoperator/deploy/crds/customresourcedefinition-monitoring.coreos.com_servicemonitors.yaml +++ b/hypershiftoperator/deploy/helm/crds/servicemonitors.monitoring.coreos.com.yaml @@ -3,8 +3,8 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - operator.prometheus.io/version: 0.76.1 + controller-gen.kubebuilder.io/version: v0.16.5 + operator.prometheus.io/version: 0.78.1 name: servicemonitors.monitoring.coreos.com spec: group: monitoring.coreos.com @@ -1068,6 +1068,23 @@ spec: type: string type: array type: object + nativeHistogramBucketLimit: + description: |- + If there are more than this many buckets in a native histogram, + buckets will be merged to stay within the limit. + It requires Prometheus >= v2.45.0. + format: int64 + type: integer + nativeHistogramMinBucketFactor: + anyOf: + - type: integer + - type: string + description: |- + If the growth factor of one bucket to the next is smaller than this, + buckets will be merged to increase the factor sufficiently. + It requires Prometheus >= v2.50.0. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true podTargetLabels: description: |- `podTargetLabels` defines the labels which are transferred from the @@ -1085,6 +1102,11 @@ spec: description: The scrape class to apply. minLength: 1 type: string + scrapeClassicHistograms: + description: |- + Whether to scrape a classic histogram that is also exposed as a native histogram. + It requires Prometheus >= v2.45.0. + type: boolean scrapeProtocols: description: |- `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the diff --git a/hypershiftoperator/deploy/helm/templates/installer.clusterrolebinding.yaml b/hypershiftoperator/deploy/helm/templates/installer.clusterrolebinding.yaml new file mode 100644 index 000000000..7db2139f6 --- /dev/null +++ b/hypershiftoperator/deploy/helm/templates/installer.clusterrolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + creationTimestamp: null + name: hypershift-installer-cluster-role +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: hypershift-installer + namespace: '{{ .Release.Namespace }}' diff --git a/hypershiftoperator/deploy/helm/templates/installer.job.yaml b/hypershiftoperator/deploy/helm/templates/installer.job.yaml new file mode 100644 index 000000000..186772ab5 --- /dev/null +++ b/hypershiftoperator/deploy/helm/templates/installer.job.yaml @@ -0,0 +1,32 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: install-hypershift + namespace: '{{ .Release.Namespace }}' + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + # set deadline to 30min + activeDeadlineSeconds: 1800 + backoffLimit: 1 + template: + spec: + containers: + - name: install + image: "{{ .Values.image }}:{{ .Values.imageTag }}" + command: + - /bin/sh + - -c + - | + hypershift install \ + --enable-conversion-webhook=false \ + --managed-service ARO-HCP \ + --aro-hcp-key-vault-users-client-id {{ .Values.azureKeyVaultClientId }} \ + --registry-overrides "{{ .Values.registryOverrides }}" \ + --hypershift-image {{ .Values.image }}:{{ .Values.imageTag }} \ + --platform-monitoring=None \ + {{ .Values.additionalArgs }} + restartPolicy: Never + serviceAccountName: hypershift-installer diff --git a/hypershiftoperator/deploy/helm/templates/installer.serviceaccount.yaml b/hypershiftoperator/deploy/helm/templates/installer.serviceaccount.yaml new file mode 100644 index 000000000..fa00eb972 --- /dev/null +++ b/hypershiftoperator/deploy/helm/templates/installer.serviceaccount.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: hypershift-installer + namespace: '{{ .Release.Namespace }}' diff --git a/hypershiftoperator/deploy/base/servicemonitor-operator.yaml b/hypershiftoperator/deploy/helm/templates/operator.servicemonitor.yaml similarity index 78% rename from hypershiftoperator/deploy/base/servicemonitor-operator.yaml rename to hypershiftoperator/deploy/helm/templates/operator.servicemonitor.yaml index 72f900814..02ea51015 100644 --- a/hypershiftoperator/deploy/base/servicemonitor-operator.yaml +++ b/hypershiftoperator/deploy/helm/templates/operator.servicemonitor.yaml @@ -1,15 +1,14 @@ -apiVersion: azmonitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - creationTimestamp: null - name: operator - namespace: hypershift -spec: - endpoints: - - interval: 30s - port: metrics - jobLabel: component - namespaceSelector: {} - selector: - matchLabels: +apiVersion: azmonitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: operator + namespace: '{{ .Release.Namespace }}' +spec: + endpoints: + - interval: 30s + port: metrics + jobLabel: component + namespaceSelector: {} + selector: + matchLabels: name: operator diff --git a/hypershiftoperator/deploy/overlays/dev/pull-secret.yaml b/hypershiftoperator/deploy/helm/templates/pull-secret.secret.yaml similarity index 71% rename from hypershiftoperator/deploy/overlays/dev/pull-secret.yaml rename to hypershiftoperator/deploy/helm/templates/pull-secret.secret.yaml index ad60c007c..a79267900 100644 --- a/hypershiftoperator/deploy/overlays/dev/pull-secret.yaml +++ b/hypershiftoperator/deploy/helm/templates/pull-secret.secret.yaml @@ -1,9 +1,8 @@ apiVersion: v1 +data: + .dockerconfigjson: e30K kind: Secret metadata: - creationTimestamp: null name: pull-secret - namespace: hypershift + namespace: '{{ .Release.Namespace }}' type: kubernetes.io/dockerconfigjson -data: - .dockerconfigjson: e30K diff --git a/hypershiftoperator/deploy/helm/values.yaml b/hypershiftoperator/deploy/helm/values.yaml new file mode 100644 index 000000000..178844fd8 --- /dev/null +++ b/hypershiftoperator/deploy/helm/values.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +version: 0.1.0 +description: A Helm chart to manage Hypershift Operator and dependencies for ARO HCP +name: aro-hcp-hypershift-operator + +image: "" +imageTag: "" +registryOverrides: "" +azureKeyVaultClientId: "" +additionalArgs: "" diff --git a/hypershiftoperator/deploy/overlays/dev/kustomization.yml b/hypershiftoperator/deploy/overlays/dev/kustomization.yml deleted file mode 100644 index 5a6ceb360..000000000 --- a/hypershiftoperator/deploy/overlays/dev/kustomization.yml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- ../../base -- pull-secret.yaml -patches: -- target: - version: v1 - kind: ServiceAccount - name: external-dns - path: patch-serviceaccount-external-dns.json -- target: - group: apps - version: v1 - kind: Deployment - name: external-dns - path: patch-deployment-external-dns.json -- target: - group: apps - version: v1 - kind: Deployment - name: operator - path: patch-deployment-operator.json -secretGenerator: -- name: external-dns-azure - namespace: hypershift - type: Opaque - files: - - credentials=edo-azure-credentials.json - - domain=domain.txt - - txt_owner_id=txt_owner_id.txt diff --git a/hypershiftoperator/deploy/overlays/dev/patch-deployment-external-dns.json b/hypershiftoperator/deploy/overlays/dev/patch-deployment-external-dns.json deleted file mode 100644 index 83661df6d..000000000 --- a/hypershiftoperator/deploy/overlays/dev/patch-deployment-external-dns.json +++ /dev/null @@ -1,40 +0,0 @@ -[ - { - "op": "add", - "path": "/spec/template/metadata/labels/azure.workload.identity~1use", - "value": "true" - }, - { - "op": "replace", - "path": "/spec/template/spec/containers/0/command/0", - "value": "/ko-app/external-dns" - }, - { - "op": "add", - "path": "/spec/template/spec/containers/0/env", - "value": [ - { - "name": "DOMAIN", - "valueFrom": { - "secretKeyRef": { - "key": "domain", - "name": "external-dns-azure" - } - } - }, - { - "name": "TXT_OWNER_ID", - "valueFrom": { - "secretKeyRef": { - "key": "txt_owner_id", - "name": "external-dns-azure" - } - } - } - ] - }, - { - "op": "remove", - "path": "/spec/template/spec/imagePullSecrets" - } -] diff --git a/hypershiftoperator/deploy/overlays/dev/patch-deployment-operator.json b/hypershiftoperator/deploy/overlays/dev/patch-deployment-operator.json deleted file mode 100644 index 842571893..000000000 --- a/hypershiftoperator/deploy/overlays/dev/patch-deployment-operator.json +++ /dev/null @@ -1,13 +0,0 @@ - -[ - { - "op": "add", - "path": "/spec/template/spec/containers/0/args/-", - "value": "--registry-overrides" - }, - { - "op": "add", - "path": "/spec/template/spec/containers/0/args/-", - "value": "quay.io/openshift-release-dev/ocp-v4.0-art-dev=arohcpocpdev.azurecr.io/openshift/release,quay.io/openshift-release-dev/ocp-release=arohcpocpdev.azurecr.io/openshift/release-images,registry.redhat.io/ubi8=arohcpocpdev.azurecr.io/ubi8,registry.access.redhat.com/ubi8=arohcpocpdev.azurecr.io/ubi8,registry.redhat.io/redhat=arohcpocpdev.azurecr.io/redhat" - } -] diff --git a/hypershiftoperator/pipeline.yaml b/hypershiftoperator/pipeline.yaml new file mode 100644 index 000000000..96614d062 --- /dev/null +++ b/hypershiftoperator/pipeline.yaml @@ -0,0 +1,30 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.HypershiftOperator +rolloutName: RP HypershiftOperator Rollout +resourceGroups: +- name: {{ .mgmt.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ARO_HCP_SVC_ACR + configRef: svcAcrName + - name: ARO_HCP_OCP_ACR + configRef: ocpAcrName + - name: HO_IMAGE_TAG + configRef: hypershiftOperator.imageTag + - name: RESOURCEGROUP + configRef: mgmt.rg + - name: AKS_NAME + configRef: aksName + - name: HYPERSHIFT_NAMESPACE + configRef: hypershift.namespace + - name: HO_ADDITIONAL_INSTALL_ARG + configRef: hypershift.additionalInstallArg diff --git a/image-sync/oc-mirror/Dockerfile b/image-sync/oc-mirror/Dockerfile index 2fdd71094..8c83de445 100644 --- a/image-sync/oc-mirror/Dockerfile +++ b/image-sync/oc-mirror/Dockerfile @@ -43,4 +43,4 @@ COPY --chown=0:0 --chmod=755 --from=downloader \ /usr/local/bin/yq \ /usr/local/bin/ - ENTRYPOINT ["/usr/local/bin/mirror.sh"] +ENTRYPOINT ["/usr/local/bin/mirror.sh"] diff --git a/image-sync/oc-mirror/Makefile b/image-sync/oc-mirror/Makefile index 598f5af54..9607345df 100644 --- a/image-sync/oc-mirror/Makefile +++ b/image-sync/oc-mirror/Makefile @@ -4,15 +4,44 @@ $(shell ../../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) include config.mk COMMIT = $(shell git rev-parse --short=7 HEAD)$(shell [[ $$(git status --porcelain) = "" ]]) +ifeq ($(shell uname), Darwin) + AUTH_FILE = ${HOME}/.config/containers/auth.json +else + AUTH_FILE = ${HOME}/.docker/config.json +endif + build-push: image push +.PHONY: build-push image: docker build --platform="linux/amd64" -f "./Dockerfile" -t ${OC_MIRROR_IMAGE_TAGGED} . +.PHONY: image push: image az acr login --name ${ARO_HCP_IMAGE_ACR} docker tag ${OC_MIRROR_IMAGE_TAGGED} ${OC_MIRROR_IMAGE}:latest docker push ${OC_MIRROR_IMAGE_TAGGED} docker push ${OC_MIRROR_IMAGE}:latest +.PHONY: push + +acm-dry-run: image + @docker run -it --rm --tmpfs /oc-mirror-workspace \ + -e XDG_RUNTIME_DIR=/ \ + -v ${AUTH_FILE}:/containers/auth.json:z \ + -v ${HOME}/.azure:/root/.azure:z \ + -e IMAGE_SET_CONFIG=$(shell cat ${PWD}/test/acm-image-set-config.yml | base64) \ + -e REGISTRY=${ARO_HCP_IMAGE_ACR} \ + -e REGISTRY_URL=${ARO_HCP_IMAGE_ACR_URL} \ + ${OC_MIRROR_IMAGE_TAGGED} --dry-run +.PHONY: acm-dry-run -.PHONY: image push build-push +ocp-dry-run: image + @docker run -it --rm --tmpfs /oc-mirror-workspace \ + -e XDG_RUNTIME_DIR=/ \ + -v ${AUTH_FILE}:/containers/auth.json:z \ + -v ${HOME}/.azure:/root/.azure:z \ + -e IMAGE_SET_CONFIG=$(shell cat ${PWD}/test/acm-image-set-config.yml | base64) \ + -e REGISTRY=${ARO_HCP_OCP_IMAGE_ACR} \ + -e REGISTRY_URL=${ARO_HCP_OCP_IMAGE_ACR_URL} \ + ${OC_MIRROR_IMAGE_TAGGED} --dry-run +.PHONY: ocp-dry-run diff --git a/image-sync/oc-mirror/README.md b/image-sync/oc-mirror/README.md index 74a4c796b..67dc9e666 100644 --- a/image-sync/oc-mirror/README.md +++ b/image-sync/oc-mirror/README.md @@ -1,42 +1,40 @@ # oc-mirror -This container contains oc-mirror end required dependencies. - -## Example usage for devarohcp - - * Build the container image `podman build -t oc-mirror .` - * Alternatively, use `make image` - * Get credentials for Openshift registries https://console.redhat.com/openshift/install/pull-secret - * Get Azure registry credentials `az acr login -n devarohcp` - * Run the sync using the built container -```BASH -podman run -it --rm --tmpfs /oc-mirror-workspace \ - -e XDG_RUNTIME_DIR=/ \ - -v $PWD/imageset-config.yml:/imageset-config.yml:Z \ - -v $HOME/.docker/config.json:/containers/auth.json:Z \ - oc-mirror \ - oc mirror --config=/imageset-config.yml docker://devarohcp.azurecr.io --dry-run +This tool packages oc-mirror and all dependencies to mirror OCP artifacts and operators to an ACR. + +## Build and push + +To build a container image and push it to the service ACR, run + +```bash +make build-push ``` -Note, the above command will run the sync in dry-run mode. To run the sync, remove the `--dry-run` flag. +## Production deployment -## Example configuration +oc-mirror and the required configurations are deployed as Azure Container App +via the `dev-infrastructure/templates/image-sync.bicep` template. -The following is an example of the configuration file `imageset-config.yml`. +## Local dry-run -This exact configuration was used in the initial testing of the `oc-mirror` tool. +To run oc-mirror locally, you need to have an active Azure CLI session. -```YAML -kind: ImageSetConfiguration -apiVersion: mirror.openshift.io/v1alpha2 -storageConfig: - registry: - imageURL: devarohcp.azurecr.io/mirror/oc-mirror-metadata - skipTLS: false -mirror: - platform: - channels: - - name: stable-4.16 - type: ocp - graph: true +### OCP mirror + +To dry-run the OCP mirror, run + +```bash +make ocp-dry-run ``` + +The test mirror-configuration can be found in the `test` directory. + +### ACM/MCE mirror + +To dry-run the ACM/MCE operator mirror, run + +```bash +make acm-dry-run +``` + +The test mirror-configuration can be found in the `test` directory. diff --git a/image-sync/oc-mirror/config.tmpl.mk b/image-sync/oc-mirror/config.tmpl.mk index 1cbf251e0..bb9899248 100644 --- a/image-sync/oc-mirror/config.tmpl.mk +++ b/image-sync/oc-mirror/config.tmpl.mk @@ -1,4 +1,7 @@ ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} -ARO_HCP_FULL ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io -OC_MIRROR_IMAGE ?= $(ARO_HCP_FULL)/{{ .ocMirrorImageRepo }} +ARO_HCP_IMAGE_ACR_URL ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io +OC_MIRROR_IMAGE ?= $(ARO_HCP_IMAGE_ACR_URL)/{{ .imageSync.ocMirror.imageRepo }} OC_MIRROR_IMAGE_TAGGED ?= $(OC_MIRROR_IMAGE):$(COMMIT) + +ARO_HCP_OCP_IMAGE_ACR ?= {{ .ocpAcrName }} +ARO_HCP_OCP_IMAGE_ACR_URL ?= ${ARO_HCP_OCP_IMAGE_ACR}.azurecr.io diff --git a/image-sync/oc-mirror/docker-login.sh b/image-sync/oc-mirror/docker-login.sh index 7526c7d2e..b87ba5f9c 100755 --- a/image-sync/oc-mirror/docker-login.sh +++ b/image-sync/oc-mirror/docker-login.sh @@ -7,4 +7,4 @@ PLAIN_CREDS="$USERNAME:$PASSWORD" AUTH=$(echo -n $PLAIN_CREDS | base64) jq --arg registry "$REGISTRY_URL" --arg auth "$AUTH" '.auths[$registry] = { "auth": $auth }' ${XDG_RUNTIME_DIR}/containers/auth.json > ${XDG_RUNTIME_DIR}/containers/tmp-auth.json -mv ${XDG_RUNTIME_DIR}/containers/tmp-auth.json ${XDG_RUNTIME_DIR}/containers/auth.json +cp ${XDG_RUNTIME_DIR}/containers/tmp-auth.json ${XDG_RUNTIME_DIR}/containers/auth.json diff --git a/image-sync/oc-mirror/mirror.sh b/image-sync/oc-mirror/mirror.sh index 18e71bd9d..7a96cfc96 100755 --- a/image-sync/oc-mirror/mirror.sh +++ b/image-sync/oc-mirror/mirror.sh @@ -1,5 +1,15 @@ #!/bin/sh az login --identity -u ${AZURE_CLIENT_ID} -echo ${IMAGE_SET_CONFIG} | base64 -d | yq eval -P > /config/imageset-config.yaml DOCKER_COMMAND=/usr/local/bin/docker-login.sh az acr login -n ${REGISTRY} -/usr/local/bin/oc-mirror --continue-on-error --config /config/imageset-config.yaml docker://${REGISTRY_URL} @$ + +IMAGE_SET_CONFIG_FILE="/config/imageset-config.yaml" +echo ${IMAGE_SET_CONFIG} | base64 -d | yq eval -P > ${IMAGE_SET_CONFIG_FILE} +API_VERSION=$(yq eval '.apiVersion' ${IMAGE_SET_CONFIG_FILE}) + +if echo "$API_VERSION" | grep -q "^mirror.openshift.io/v2"; then + ADDITIONAL_FLAGS="--workspace file:///oc-mirror-workspace --v2" +else + ADDITIONAL_FLAGS="--continue-on-error" +fi + +/usr/local/bin/oc-mirror --config ${IMAGE_SET_CONFIG_FILE} ${ADDITIONAL_FLAGS} docker://${REGISTRY_URL} @$ diff --git a/image-sync/oc-mirror/test/acm-image-set-config.yml b/image-sync/oc-mirror/test/acm-image-set-config.yml new file mode 100644 index 000000000..76d0c2426 --- /dev/null +++ b/image-sync/oc-mirror/test/acm-image-set-config.yml @@ -0,0 +1,12 @@ +kind: ImageSetConfiguration +apiVersion: mirror.openshift.io/v2alpha1 +mirror: + operators: + - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.17 + packages: + - name: multicluster-engine + bundles: + - name: multicluster-engine.v2.7.0 + - name: advanced-cluster-management + bundles: + - name: advanced-cluster-management.v2.12.0 diff --git a/image-sync/oc-mirror/test/ocp-image-set-config.yml b/image-sync/oc-mirror/test/ocp-image-set-config.yml new file mode 100644 index 000000000..e711ce74c --- /dev/null +++ b/image-sync/oc-mirror/test/ocp-image-set-config.yml @@ -0,0 +1,22 @@ +kind: ImageSetConfiguration +apiVersion: mirror.openshift.io/v1alpha2 +storageConfig: + registry: + imageURL: arohcpocpdev.azurecr.io/mirror/oc-mirror-metadata + skipTLS: false +mirror: + platform: + architectures: + - multi + - amd64 + channels: + - name: stable-4.17 + minVersion: 4.17.0 + maxVersion: 4.17.0 + type: ocp + graph: true + additionalImages: + - name: registry.redhat.io/redhat/redhat-operator-index:v4.17 + - name: registry.redhat.io/redhat/certified-operator-index:v4.17 + - name: registry.redhat.io/redhat/community-operator-index:v4.17 + - name: registry.redhat.io/redhat/redhat-marketplace-index:v4.17 diff --git a/internal/api/arm/error.go b/internal/api/arm/error.go index 56fb06875..75669597a 100644 --- a/internal/api/arm/error.go +++ b/internal/api/arm/error.go @@ -105,12 +105,8 @@ func WriteError(w http.ResponseWriter, statusCode int, code, target, format stri // WriteCloudError writes a CloudError to the given ResponseWriter func WriteCloudError(w http.ResponseWriter, err *CloudError) { - w.Header()["Content-Type"] = []string{"application/json"} w.Header()[HeaderNameErrorCode] = []string{err.Code} - w.WriteHeader(err.StatusCode) - encoder := json.NewEncoder(w) - encoder.SetIndent("", " ") - _ = encoder.Encode(err) + _, _ = WriteJSONResponse(w, err.StatusCode, err) } // NewInternalServerError creates a CloudError for an internal server error @@ -127,7 +123,7 @@ func WriteInternalServerError(w http.ResponseWriter) { } // NewResourceNotFoundError creates a CloudError for a nonexistent resource error -func NewResourceNotFoundError(resourceID *ResourceID) *CloudError { +func NewResourceNotFoundError(resourceID *azcorearm.ResourceID) *CloudError { var code string var message string @@ -153,7 +149,7 @@ func NewResourceNotFoundError(resourceID *ResourceID) *CloudError { } // WriteResourceNotFoundError writes a nonexistent resource error to the given ResponseWriter -func WriteResourceNotFoundError(w http.ResponseWriter, resourceID *ResourceID) { +func WriteResourceNotFoundError(w http.ResponseWriter, resourceID *azcorearm.ResourceID) { WriteCloudError(w, NewResourceNotFoundError(resourceID)) } diff --git a/internal/api/arm/headers.go b/internal/api/arm/headers.go index 741a5c7c2..170ffc6a3 100644 --- a/internal/api/arm/headers.go +++ b/internal/api/arm/headers.go @@ -18,4 +18,5 @@ const ( HeaderNameCorrelationRequestID = "X-Ms-Correlation-Request-Id" HeaderNameReturnClientRequestID = "X-Ms-Return-Client-Request-Id" HeaderNameARMResourceSystemData = "X-Ms-Arm-Resource-System-Data" + HeaderNameIdentityURL = "X-Ms-Identity-Url" ) diff --git a/internal/api/arm/identity.go b/internal/api/arm/identity.go new file mode 100644 index 000000000..60a7e6e4c --- /dev/null +++ b/internal/api/arm/identity.go @@ -0,0 +1,27 @@ +package arm + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +// Represents to support the ManagedServiceIdentity ARM resource. +type ManagedServiceIdentity struct { + PrincipalID string `json:"principalId,omitempty" visibility:"read"` + TenantID string `json:"tenantId,omitempty" visibility:"read"` + Type ManagedServiceIdentityType `json:"type" validate:"omitempty,enum_managedserviceidentitytype"` + UserAssignedIdentities map[string]*UserAssignedIdentity `json:"userAssignedIdentities,omitempty" validate:"dive,keys,resource_id=Microsoft.ManagedIdentity/userAssignedIdentities,endkeys"` +} + +// UserAssignedIdentity - User assigned identity properties https://azure.github.io/typespec-azure/docs/libraries/azure-resource-manager/reference/data-types/#Azure.ResourceManager.CommonTypes.UserAssignedIdentity +type UserAssignedIdentity struct { + ClientID *string `json:"clientId,omitempty" visibility:"read"` + PrincipalID *string `json:"principalId,omitempty" visibility:"read"` +} + +type ManagedServiceIdentityType string + +const ( + ManagedServiceIdentityTypeNone ManagedServiceIdentityType = "None" + ManagedServiceIdentityTypeSystemAssigned ManagedServiceIdentityType = "SystemAssigned" + ManagedServiceIdentityTypeSystemAssignedUserAssigned ManagedServiceIdentityType = "SystemAssigned,UserAssigned" + ManagedServiceIdentityTypeUserAssigned ManagedServiceIdentityType = "UserAssigned" +) diff --git a/internal/api/arm/operation.go b/internal/api/arm/operation.go index fea03b47f..b06f0fd89 100644 --- a/internal/api/arm/operation.go +++ b/internal/api/arm/operation.go @@ -6,17 +6,19 @@ package arm import ( "encoding/json" "time" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" ) // Operation is an ARM-defined resource returned by operation status endpoints. type Operation struct { - ID *ResourceID `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Status ProvisioningState `json:"status"` - StartTime *time.Time `json:"startTime,omitempty"` - EndTime *time.Time `json:"endTime,omitempty"` - PercentComplete float64 `json:"percentComplete,omitempty"` - Properties json.RawMessage `json:"peroperties,omitempty"` - Error *CloudErrorBody `json:"error,omitempty"` - Operations []Operation `json:"operations,omitempty"` + ID *azcorearm.ResourceID `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Status ProvisioningState `json:"status"` + StartTime *time.Time `json:"startTime,omitempty"` + EndTime *time.Time `json:"endTime,omitempty"` + PercentComplete float64 `json:"percentComplete,omitempty"` + Properties json.RawMessage `json:"properties,omitempty"` + Error *CloudErrorBody `json:"error,omitempty"` + Operations []Operation `json:"operations,omitempty"` } diff --git a/internal/api/arm/preflight.go b/internal/api/arm/preflight.go index a4f01bae1..08cbf749d 100644 --- a/internal/api/arm/preflight.go +++ b/internal/api/arm/preflight.go @@ -89,9 +89,5 @@ func WriteDeploymentPreflightResponse(w http.ResponseWriter, preflightErrors []C } } - w.Header()["Content-Type"] = []string{"application/json"} - w.WriteHeader(http.StatusOK) - encoder := json.NewEncoder(w) - encoder.SetIndent("", " ") - _ = encoder.Encode(response) + _, _ = WriteJSONResponse(w, http.StatusOK, response) } diff --git a/internal/api/arm/resource.go b/internal/api/arm/resource.go index 30a4704b2..1d5acb77d 100644 --- a/internal/api/arm/resource.go +++ b/internal/api/arm/resource.go @@ -4,53 +4,10 @@ package arm // Licensed under the Apache License 2.0. import ( - "encoding/json" "maps" - "net/url" "time" - - azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" ) -// ResourceID is a wrappered ResourceID from azcore with text marshaling and unmarshaling methods. -type ResourceID struct { - azcorearm.ResourceID -} - -// ParseResourceID parses a string to an instance of ResourceID. -func ParseResourceID(id string) (*ResourceID, error) { - newId, err := azcorearm.ParseResourceID(id) - if err != nil { - return nil, err - } - return &ResourceID{ResourceID: *newId}, nil -} - -// GetParent returns the parent resource ID, if any. Handles the -// type-casting necessary to access the parent as a wrapper type. -func (id *ResourceID) GetParent() *ResourceID { - var parent *ResourceID - if id.Parent != nil { - parent = &ResourceID{ResourceID: *id.Parent} - } - return parent -} - -// MarshalText returns a textual representation of the ResourceID. -func (id *ResourceID) MarshalText() ([]byte, error) { - return []byte(id.String()), nil -} - -// UnmarshalText decodes the textual representation of a ResourceID. -func (id *ResourceID) UnmarshalText(text []byte) error { - newId, err := azcorearm.ParseResourceID(string(text)) - if err != nil { - return err - } - id.ResourceID = *newId - return nil -} - // Resource represents a basic ARM resource type Resource struct { ID string `json:"id,omitempty"` @@ -156,34 +113,3 @@ func (s ProvisioningState) IsTerminal() bool { return false } } - -// PagedResponse is the response format for resource collection requests. -type PagedResponse struct { - Value []json.RawMessage `json:"value"` - NextLink string `json:"nextLink,omitempty"` -} - -// AddValue adds a JSON encoded value to a PagedResponse. -func (r *PagedResponse) AddValue(value json.RawMessage) { - r.Value = append(r.Value, value) -} - -// SetNextLink sets NextLink to a URL with a $skipToken parameter. -// If skipToken is empty, the function does nothing and returns nil. -func (r *PagedResponse) SetNextLink(baseURL, skipToken string) error { - if skipToken == "" { - return nil - } - - u, err := url.ParseRequestURI(baseURL) - if err != nil { - return err - } - - values := u.Query() - values.Set("$skipToken", skipToken) - u.RawQuery = values.Encode() - - r.NextLink = u.String() - return nil -} diff --git a/internal/api/arm/response.go b/internal/api/arm/response.go new file mode 100644 index 000000000..5c07391c8 --- /dev/null +++ b/internal/api/arm/response.go @@ -0,0 +1,88 @@ +package arm + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "encoding/json" + "net/http" + "net/url" +) + +const ( + prefix string = "" // no prefix + indent string = " " // 4 spaces +) + +// Marshal returns the JSON encoding of v. +// +// Call this function instead of the marshal functions in "encoding/json" for +// HTTP responses to ensure the formatting is consistent. +// +// Note, there is nothing ARM-specific about this function other than all ARM +// response bodies are JSON-formatted. But the "arm" package is currently the +// lowest layer insofar as it has no dependencies on other ARO-HCP packages. +func Marshal(v any) ([]byte, error) { + return json.MarshalIndent(v, prefix, indent) +} + +// WriteJSONResponse writes a JSON response body to the http.ResponseWriter in +// the proper sequence: first setting Content-Type to "application/json", then +// setting the HTTP status code, and finally writing a JSON encoding of body. +// +// The function accepts anything for the body argument that can be marshalled +// to JSON. One special case, however, is a byte slice. A byte slice will be +// written verbatim with the expectation that it was produced by Marshal. +// +// Note, there is nothing ARM-specific about this function other than all ARM +// response bodies are JSON-formatted. But the "arm" package is currently the +// lowest layer insofar as it has no dependencies on other ARO-HCP packages. +func WriteJSONResponse(writer http.ResponseWriter, statusCode int, body any) (int, error) { + var data []byte + + switch v := body.(type) { + case []byte: + data = v // write a byte slice verbatim + default: + var err error + data, err = Marshal(body) + if err != nil { + return 0, err + } + } + + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(statusCode) + return writer.Write(data) +} + +// PagedResponse is the response format for resource collection requests. +type PagedResponse struct { + Value []json.RawMessage `json:"value"` + NextLink string `json:"nextLink,omitempty"` +} + +// AddValue adds a JSON encoded value to a PagedResponse. +func (r *PagedResponse) AddValue(value json.RawMessage) { + r.Value = append(r.Value, value) +} + +// SetNextLink sets NextLink to a URL with a $skipToken parameter. +// If skipToken is empty, the function does nothing and returns nil. +func (r *PagedResponse) SetNextLink(baseURL, skipToken string) error { + if skipToken == "" { + return nil + } + + u, err := url.ParseRequestURI(baseURL) + if err != nil { + return err + } + + values := u.Query() + values.Set("$skipToken", skipToken) + u.RawQuery = values.Encode() + + r.NextLink = u.String() + return nil +} diff --git a/internal/api/arm/response_test.go b/internal/api/arm/response_test.go new file mode 100644 index 000000000..0d2f3e018 --- /dev/null +++ b/internal/api/arm/response_test.go @@ -0,0 +1,87 @@ +package arm + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestWriteJSONResponse(t *testing.T) { + resourceStruct := &TrackedResource{ + Resource: Resource{ + ID: "00000000-0000-0000-0000-000000000000", + Name: "testCluster", + Type: "Microsoft.RedHatOpenShift/hcpOpenShiftClusters", + }, + Location: "eastus1", + Tags: map[string]string{ + "nameA": "valueA", + "nameB": "valueB", + }, + } + + resourceBytes, err := Marshal(resourceStruct) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + statusCode int + body any + }{ + { + name: "Write structured data", + statusCode: http.StatusAccepted, + body: resourceStruct, + }, + { + name: "Write byte slice", + statusCode: http.StatusCreated, + body: resourceBytes, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + recorder := httptest.NewRecorder() + + _, err := WriteJSONResponse(recorder, tt.statusCode, tt.body) + if err != nil { + t.Fatal(err) + } + + result := recorder.Result() + + if result.StatusCode != tt.statusCode { + t.Errorf("Got status code %d, expected %d", result.StatusCode, tt.statusCode) + } + + contentType := result.Header.Get("Content-Type") + if contentType == "" { + t.Errorf("Response is missing a Content-Type header") + } else if contentType != "application/json" { + t.Errorf("Got Content-Type %s, expected application/json", contentType) + } + + expectBody, err := Marshal(resourceStruct) + if err != nil { + t.Fatal(err) + } + actualBody, err := io.ReadAll(result.Body) + if err != nil { + t.Fatal(err) + } + if string(actualBody) != string(expectBody) { + t.Error("Response body had unexpected variations:\n" + cmp.Diff(string(expectBody), string(actualBody))) + } + + }) + } +} diff --git a/internal/api/hcpopenshiftcluster.go b/internal/api/hcpopenshiftcluster.go index 0bc56c1a7..6b3f64780 100644 --- a/internal/api/hcpopenshiftcluster.go +++ b/internal/api/hcpopenshiftcluster.go @@ -13,6 +13,7 @@ import ( type HCPOpenShiftCluster struct { arm.TrackedResource Properties HCPOpenShiftClusterProperties `json:"properties,omitempty" validate:"required_for_put"` + Identity arm.ManagedServiceIdentity `json:"identity,omitempty"` } // HCPOpenShiftClusterProperties represents the property bag of a HCPOpenShiftCluster resource. @@ -84,12 +85,26 @@ type ProxyProfile struct { // PlatformProfile represents the Azure platform configuration. // Visibility for the entire struct is "read create". type PlatformProfile struct { - ManagedResourceGroup string `json:"managedResourceGroup,omitempty"` - SubnetID string `json:"subnetId,omitempty" validate:"required_for_put"` - OutboundType OutboundType `json:"outboundType,omitempty" validate:"omitempty,enum_outboundtype"` - //TODO: Is nsg required for PUT, or will we create if not specified? - NetworkSecurityGroupID string `json:"networkSecurityGroupId,omitempty" validate:"required_for_put"` - EtcdEncryptionSetID string `json:"etcdEncryptionSetId,omitempty"` + ManagedResourceGroup string `json:"managedResourceGroup,omitempty"` + SubnetID string `json:"subnetId,omitempty" validate:"required_for_put"` + OutboundType OutboundType `json:"outboundType,omitempty" validate:"omitempty,enum_outboundtype"` + NetworkSecurityGroupID string `json:"networkSecurityGroupId,omitempty"` + EtcdEncryptionSetID string `json:"etcdEncryptionSetId,omitempty"` + OperatorsAuthentication OperatorsAuthenticationProfile `json:"operatorsAuthentication,omitempty"` +} + +// OperatorsAuthenticationProfile represents authentication configuration for +// OpenShift operators. +type OperatorsAuthenticationProfile struct { + UserAssignedIdentities UserAssignedIdentitiesProfile `json:"userAssignedIdentities,omitempty"` +} + +// UserAssignedIdentitiesProfile represents authentication configuration for +// OpenShift operators using user-assigned managed identities. +type UserAssignedIdentitiesProfile struct { + ControlPlaneOperators map[string]string `json:"controlPlaneOperators,omitempty" validate:"dive,resource_id=Microsoft.ManagedIdentity/userAssignedIdentities"` + DataPlaneOperators map[string]string `json:"dataPlaneOperators,omitempty" validate:"dive,resource_id=Microsoft.ManagedIdentity/userAssignedIdentities"` + ServiceManagedIdentity string `json:"serviceManagedIdentity,omitempty" validate:"omitempty,resource_id=Microsoft.ManagedIdentity/userAssignedIdentities"` } // ExternalAuthConfigProfile represents the external authentication configuration. @@ -101,6 +116,9 @@ type ExternalAuthConfigProfile struct { // Creates an HCPOpenShiftCluster with any non-zero default values. func NewDefaultHCPOpenShiftCluster() *HCPOpenShiftCluster { return &HCPOpenShiftCluster{ + Identity: arm.ManagedServiceIdentity{ + Type: arm.ManagedServiceIdentityTypeNone, + }, Properties: HCPOpenShiftClusterProperties{ Spec: ClusterSpec{ Network: NetworkProfile{ diff --git a/internal/api/hcpopenshiftcluster_test.go b/internal/api/hcpopenshiftcluster_test.go index 925e3c158..fe5720224 100644 --- a/internal/api/hcpopenshiftcluster_test.go +++ b/internal/api/hcpopenshiftcluster_test.go @@ -20,6 +20,11 @@ func newTestValidator() *validator.Validate { validate.RegisterAlias("enum_outboundtype", EnumValidateTag("loadBalancer")) validate.RegisterAlias("enum_visibility", EnumValidateTag("private", "public")) + validate.RegisterAlias("enum_managedserviceidentitytype", EnumValidateTag( + arm.ManagedServiceIdentityTypeNone, + arm.ManagedServiceIdentityTypeSystemAssigned, + arm.ManagedServiceIdentityTypeSystemAssignedUserAssigned, + arm.ManagedServiceIdentityTypeUserAssigned)) return validate } @@ -48,11 +53,39 @@ func minimumValidCluster() *HCPOpenShiftCluster { Visibility: "public", }, Platform: PlatformProfile{ - SubnetID: "/something/something/virtualNetworks/subnets", - NetworkSecurityGroupID: "/something/something/networkSecurityGroups", + SubnetID: "/something/something/virtualNetworks/subnets", + OperatorsAuthentication: OperatorsAuthenticationProfile{UserAssignedIdentities: UserAssignedIdentitiesProfile{ControlPlaneOperators: map[string]string{"operatorX": "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/MyResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/MyManagedIdentity"}}}, }, }, }, + Identity: arm.ManagedServiceIdentity{UserAssignedIdentities: map[string]*arm.UserAssignedIdentity{"/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/MyResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/MyManagedIdentity": &arm.UserAssignedIdentity{}}}, + } +} + +func minimumValidClusterwithBrokenIdentityAndOperatorsAuthentication() *HCPOpenShiftCluster { + // Values are meaningless but need to pass validation. + return &HCPOpenShiftCluster{ + Properties: HCPOpenShiftClusterProperties{ + Spec: ClusterSpec{ + Version: VersionProfile{ + ID: "openshift-v4.16.0", + ChannelGroup: "stable", + }, + Network: NetworkProfile{ + PodCIDR: "10.128.0.0/14", + ServiceCIDR: "172.30.0.0/16", + MachineCIDR: "10.0.0.0/16", + }, + API: APIProfile{ + Visibility: "public", + }, + Platform: PlatformProfile{ + SubnetID: "/something/something/virtualNetworks/subnets", + OperatorsAuthentication: OperatorsAuthenticationProfile{UserAssignedIdentities: UserAssignedIdentitiesProfile{ControlPlaneOperators: map[string]string{"operatorX": "wrong/Pattern/Of/ResourceID"}}}, + }, + }, + }, + Identity: arm.ManagedServiceIdentity{UserAssignedIdentities: map[string]*arm.UserAssignedIdentity{"wrong/Pattern/Of/ResourceID": &arm.UserAssignedIdentity{}}}, } } @@ -104,9 +137,20 @@ func TestClusterRequiredForPut(t *testing.T) { Message: "Missing required field 'subnetId'", Target: "properties.spec.platform.subnetId", }, + }, + }, + { + name: "Minimum valid cluster with Broken Identity", + resource: minimumValidClusterwithBrokenIdentityAndOperatorsAuthentication(), + expectErrors: []arm.CloudErrorBody{ + { + Message: "Invalid value 'wrong/Pattern/Of/ResourceID' for field 'controlPlaneOperators[operatorX]' (must be a valid 'Microsoft.ManagedIdentity/userAssignedIdentities' resource ID)", + Target: "properties.spec.platform.operatorsAuthentication.userAssignedIdentities.controlPlaneOperators[operatorX]", + Details: nil, + }, { - Message: "Missing required field 'networkSecurityGroupId'", - Target: "properties.spec.platform.networkSecurityGroupId", + Message: "Invalid value 'wrong/Pattern/Of/ResourceID' for field 'userAssignedIdentities[wrong/Pattern/Of/ResourceID]' (must be a valid 'Microsoft.ManagedIdentity/userAssignedIdentities' resource ID)", + Target: "identity.userAssignedIdentities[wrong/Pattern/Of/ResourceID]", }, }, }, @@ -246,6 +290,18 @@ func TestClusterValidateTags(t *testing.T) { }, }, }, + { + name: "Bad enum_managedserviceidentitytype", + tweaks: &HCPOpenShiftCluster{ + Identity: arm.ManagedServiceIdentity{Type: "brokenServiceType"}, + }, + expectErrors: []arm.CloudErrorBody{ + { + Message: "Invalid value 'brokenServiceType' for field 'type' (must be one of: None SystemAssigned SystemAssigned,UserAssigned UserAssigned)", + Target: "identity.type", + }, + }, + }, } validate := newTestValidator() diff --git a/internal/api/utils.go b/internal/api/utils.go index 791d4a241..e929b85a4 100644 --- a/internal/api/utils.go +++ b/internal/api/utils.go @@ -63,3 +63,23 @@ func StringPtrMapToStringMap(m map[string]*string) map[string]string { } return out } + +// MergeStringPtrMap merges a map of string pointers into a map of strings +// following the rules of JSON merge-patch (RFC 7396). In particular, if a +// key in src has a nil value, that entry is deleted from dst. The function +// takes a pointer to the dst map in case the dst map is nil and needs to be +// initialized. +func MergeStringPtrMap(src map[string]*string, dst *map[string]string) { + if src != nil && dst != nil { + for key, val := range src { + if val == nil { + delete(*dst, key) + } else { + if *dst == nil { + *dst = make(map[string]string) + } + (*dst)[key] = *val + } + } + } +} diff --git a/internal/api/utils_test.go b/internal/api/utils_test.go new file mode 100644 index 000000000..c1c8baf50 --- /dev/null +++ b/internal/api/utils_test.go @@ -0,0 +1,129 @@ +package api + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestMergeStringPtrMap(t *testing.T) { + tests := []struct { + name string + src map[string]*string + dst map[string]string + expect map[string]string + }{ + { + name: "No source map and no destination map", + src: nil, + dst: nil, + expect: nil, + }, + { + name: "No source map but existing destination map", + src: nil, + dst: map[string]string{ + "Blinky": "Shadow", + }, + expect: map[string]string{ + "Blinky": "Shadow", + }, + }, + { + name: "Add entry to a new map", + src: map[string]*string{ + "Blinky": Ptr("Shadow"), + }, + dst: nil, + expect: map[string]string{ + "Blinky": "Shadow", + }, + }, + { + name: "Add entry to an existing map", + src: map[string]*string{ + "Blinky": Ptr("Shadow"), + }, + dst: map[string]string{ + "Pinky": "Speedy", + "Inky": "Bashful", + "Clyde": "Pokey", + }, + expect: map[string]string{ + "Blinky": "Shadow", + "Pinky": "Speedy", + "Inky": "Bashful", + "Clyde": "Pokey", + }, + }, + { + name: "Delete entry from a non-existent map", + src: map[string]*string{ + "Blinky": nil, + }, + dst: nil, + expect: nil, + }, + { + name: "Delete entry from an existing map", + src: map[string]*string{ + "Blinky": nil, + }, + dst: map[string]string{ + "Blinky": "Shadow", + "Pinky": "Speedy", + "Inky": "Bashful", + "Clyde": "Pokey", + }, + expect: map[string]string{ + "Pinky": "Speedy", + "Inky": "Bashful", + "Clyde": "Pokey", + }, + }, + { + name: "Both add and delete entries from an existing map", + src: map[string]*string{ + "Blinky": nil, + "Pinky": nil, + "Inky": Ptr("Bashful"), + "Clyde": Ptr("Pokey"), + }, + dst: map[string]string{ + "Blinky": "Shadow", + "Inky": "Bashful", + }, + expect: map[string]string{ + "Inky": "Bashful", + "Clyde": "Pokey", + }, + }, + { + name: "Modify an entry in an existing map", + src: map[string]*string{ + "Blinky": Ptr("Oikake"), + }, + dst: map[string]string{ + "Blinky": "Shadow", + "Inky": "Bashful", + }, + expect: map[string]string{ + "Blinky": "Oikake", + "Inky": "Bashful", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + MergeStringPtrMap(tt.src, &tt.dst) + if !reflect.DeepEqual(tt.expect, tt.dst) { + t.Error(cmp.Diff(tt.expect, tt.dst)) + } + }) + } +} diff --git a/internal/api/v20240610preview/generated/client_factory.go b/internal/api/v20240610preview/generated/client_factory.go index d18146791..69184a2f6 100644 --- a/internal/api/v20240610preview/generated/client_factory.go +++ b/internal/api/v20240610preview/generated/client_factory.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -16,7 +16,7 @@ import ( // Don't use this type directly, use NewClientFactory instead. type ClientFactory struct { subscriptionID string - internal *arm.Client + internal *arm.Client } // NewClientFactory creates a new instance of ClientFactory with the specified values. @@ -31,7 +31,7 @@ func NewClientFactory(subscriptionID string, credential azcore.TokenCredential, } return &ClientFactory{ subscriptionID: subscriptionID, - internal: internal, + internal: internal, }, nil } @@ -39,7 +39,7 @@ func NewClientFactory(subscriptionID string, credential azcore.TokenCredential, func (c *ClientFactory) NewHcpClusterVersionsClient() *HcpClusterVersionsClient { return &HcpClusterVersionsClient{ subscriptionID: c.subscriptionID, - internal: c.internal, + internal: c.internal, } } @@ -47,7 +47,7 @@ func (c *ClientFactory) NewHcpClusterVersionsClient() *HcpClusterVersionsClient func (c *ClientFactory) NewHcpOpenShiftClustersClient() *HcpOpenShiftClustersClient { return &HcpOpenShiftClustersClient{ subscriptionID: c.subscriptionID, - internal: c.internal, + internal: c.internal, } } @@ -55,7 +55,7 @@ func (c *ClientFactory) NewHcpOpenShiftClustersClient() *HcpOpenShiftClustersCli func (c *ClientFactory) NewNodePoolsClient() *NodePoolsClient { return &NodePoolsClient{ subscriptionID: c.subscriptionID, - internal: c.internal, + internal: c.internal, } } @@ -65,3 +65,4 @@ func (c *ClientFactory) NewOperationsClient() *OperationsClient { internal: c.internal, } } + diff --git a/internal/api/v20240610preview/generated/constants.go b/internal/api/v20240610preview/generated/constants.go index ea58e12cb..c3af8c49c 100644 --- a/internal/api/v20240610preview/generated/constants.go +++ b/internal/api/v20240610preview/generated/constants.go @@ -1,14 +1,14 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. package generated const ( - moduleName = "undefined" + moduleName = "undefined" moduleVersion = "v0.0.1" ) @@ -21,7 +21,7 @@ const ( // PossibleActionTypeValues returns the possible values for the ActionType const type. func PossibleActionTypeValues() []ActionType { - return []ActionType{ + return []ActionType{ ActionTypeInternal, } } @@ -30,15 +30,15 @@ func PossibleActionTypeValues() []ActionType { type CreatedByType string const ( - CreatedByTypeApplication CreatedByType = "Application" - CreatedByTypeKey CreatedByType = "Key" + CreatedByTypeApplication CreatedByType = "Application" + CreatedByTypeKey CreatedByType = "Key" CreatedByTypeManagedIdentity CreatedByType = "ManagedIdentity" - CreatedByTypeUser CreatedByType = "User" + CreatedByTypeUser CreatedByType = "User" ) // PossibleCreatedByTypeValues returns the possible values for the CreatedByType const type. func PossibleCreatedByTypeValues() []CreatedByType { - return []CreatedByType{ + return []CreatedByType{ CreatedByTypeApplication, CreatedByTypeKey, CreatedByTypeManagedIdentity, @@ -60,7 +60,7 @@ const ( // PossibleEffectValues returns the possible values for the Effect const type. func PossibleEffectValues() []Effect { - return []Effect{ + return []Effect{ EffectNoExecute, EffectNoSchedule, EffectPreferNoSchedule, @@ -71,15 +71,15 @@ func PossibleEffectValues() []Effect { type ManagedServiceIdentityType string const ( - ManagedServiceIdentityTypeNone ManagedServiceIdentityType = "None" - ManagedServiceIdentityTypeSystemAssigned ManagedServiceIdentityType = "SystemAssigned" + ManagedServiceIdentityTypeNone ManagedServiceIdentityType = "None" + ManagedServiceIdentityTypeSystemAssigned ManagedServiceIdentityType = "SystemAssigned" ManagedServiceIdentityTypeSystemAssignedUserAssigned ManagedServiceIdentityType = "SystemAssigned,UserAssigned" - ManagedServiceIdentityTypeUserAssigned ManagedServiceIdentityType = "UserAssigned" + ManagedServiceIdentityTypeUserAssigned ManagedServiceIdentityType = "UserAssigned" ) // PossibleManagedServiceIdentityTypeValues returns the possible values for the ManagedServiceIdentityType const type. func PossibleManagedServiceIdentityTypeValues() []ManagedServiceIdentityType { - return []ManagedServiceIdentityType{ + return []ManagedServiceIdentityType{ ManagedServiceIdentityTypeNone, ManagedServiceIdentityTypeSystemAssigned, ManagedServiceIdentityTypeSystemAssignedUserAssigned, @@ -99,7 +99,7 @@ const ( // PossibleNetworkTypeValues returns the possible values for the NetworkType const type. func PossibleNetworkTypeValues() []NetworkType { - return []NetworkType{ + return []NetworkType{ NetworkTypeOVNKubernetes, NetworkTypeOther, } @@ -110,14 +110,14 @@ func PossibleNetworkTypeValues() []NetworkType { type Origin string const ( - OriginSystem Origin = "system" - OriginUser Origin = "user" + OriginSystem Origin = "system" + OriginUser Origin = "user" OriginUserSystem Origin = "user,system" ) // PossibleOriginValues returns the possible values for the Origin const type. func PossibleOriginValues() []Origin { - return []Origin{ + return []Origin{ OriginSystem, OriginUser, OriginUserSystem, @@ -134,7 +134,7 @@ const ( // PossibleOutboundTypeValues returns the possible values for the OutboundType const type. func PossibleOutboundTypeValues() []OutboundType { - return []OutboundType{ + return []OutboundType{ OutboundTypeLoadBalancer, } } @@ -161,7 +161,7 @@ const ( // PossibleProvisioningStateValues returns the possible values for the ProvisioningState const type. func PossibleProvisioningStateValues() []ProvisioningState { - return []ProvisioningState{ + return []ProvisioningState{ ProvisioningStateAccepted, ProvisioningStateCanceled, ProvisioningStateDeleting, @@ -186,7 +186,7 @@ const ( // PossibleResourceProvisioningStateValues returns the possible values for the ResourceProvisioningState const type. func PossibleResourceProvisioningStateValues() []ResourceProvisioningState { - return []ResourceProvisioningState{ + return []ResourceProvisioningState{ ResourceProvisioningStateCanceled, ResourceProvisioningStateFailed, ResourceProvisioningStateSucceeded, @@ -205,8 +205,9 @@ const ( // PossibleVisibilityValues returns the possible values for the Visibility const type. func PossibleVisibilityValues() []Visibility { - return []Visibility{ + return []Visibility{ VisibilityPrivate, VisibilityPublic, } } + diff --git a/internal/api/v20240610preview/generated/fake/hcpclusterversions_server.go b/internal/api/v20240610preview/generated/fake/hcpclusterversions_server.go index b6dc49fd4..bc708efab 100644 --- a/internal/api/v20240610preview/generated/fake/hcpclusterversions_server.go +++ b/internal/api/v20240610preview/generated/fake/hcpclusterversions_server.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,23 +10,22 @@ package fake import ( "errors" "fmt" - "net/http" - "net/url" - "regexp" - + "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" azfake "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - - "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" + "net/http" + "net/url" + "regexp" ) // HcpClusterVersionsServer is a fake server for instances of the generated.HcpClusterVersionsClient type. -type HcpClusterVersionsServer struct { +type HcpClusterVersionsServer struct{ // NewListPager is the fake for method HcpClusterVersionsClient.NewListPager // HTTP status codes to indicate success: http.StatusOK NewListPager func(location string, options *generated.HcpClusterVersionsClientListOptions) (resp azfake.PagerResponder[generated.HcpClusterVersionsClientListResponse]) + } // NewHcpClusterVersionsServerTransport creates a new instance of HcpClusterVersionsServerTransport with the provided implementation. @@ -34,7 +33,7 @@ type HcpClusterVersionsServer struct { // azcore.ClientOptions.Transporter field in the client's constructor parameters. func NewHcpClusterVersionsServerTransport(srv *HcpClusterVersionsServer) *HcpClusterVersionsServerTransport { return &HcpClusterVersionsServerTransport{ - srv: srv, + srv: srv, newListPager: newTracker[azfake.PagerResponder[generated.HcpClusterVersionsClientListResponse]](), } } @@ -42,7 +41,7 @@ func NewHcpClusterVersionsServerTransport(srv *HcpClusterVersionsServer) *HcpClu // HcpClusterVersionsServerTransport connects instances of generated.HcpClusterVersionsClient to instances of HcpClusterVersionsServer. // Don't use this type directly, use NewHcpClusterVersionsServerTransport instead. type HcpClusterVersionsServerTransport struct { - srv *HcpClusterVersionsServer + srv *HcpClusterVersionsServer newListPager *tracker[azfake.PagerResponder[generated.HcpClusterVersionsClientListResponse]] } @@ -77,17 +76,17 @@ func (h *HcpClusterVersionsServerTransport) dispatchNewListPager(req *http.Reque } newListPager := h.newListPager.get(req) if newListPager == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/locations/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftVersions` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 2 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - locationParam, err := url.PathUnescape(matches[regex.SubexpIndex("location")]) - if err != nil { - return nil, err - } - resp := h.srv.NewListPager(locationParam, nil) + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/locations/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftVersions` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 2 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + locationParam, err := url.PathUnescape(matches[regex.SubexpIndex("location")]) + if err != nil { + return nil, err + } +resp := h.srv.NewListPager(locationParam, nil) newListPager = &resp h.newListPager.add(req, newListPager) server.PagerResponderInjectNextLinks(newListPager, req, func(page *generated.HcpClusterVersionsClientListResponse, createLink func() string) { @@ -107,3 +106,4 @@ func (h *HcpClusterVersionsServerTransport) dispatchNewListPager(req *http.Reque } return resp, nil } + diff --git a/internal/api/v20240610preview/generated/fake/hcpopenshiftclusters_server.go b/internal/api/v20240610preview/generated/fake/hcpopenshiftclusters_server.go index 4e60df8cb..e8e6e6c15 100644 --- a/internal/api/v20240610preview/generated/fake/hcpopenshiftclusters_server.go +++ b/internal/api/v20240610preview/generated/fake/hcpopenshiftclusters_server.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -11,20 +11,18 @@ import ( "context" "errors" "fmt" - "net/http" - "net/url" - "regexp" - + "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" azfake "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - - "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" + "net/http" + "net/url" + "regexp" ) // HcpOpenShiftClustersServer is a fake server for instances of the generated.HcpOpenShiftClustersClient type. -type HcpOpenShiftClustersServer struct { +type HcpOpenShiftClustersServer struct{ // AdminCredentials is the fake for method HcpOpenShiftClustersClient.AdminCredentials // HTTP status codes to indicate success: http.StatusOK AdminCredentials func(ctx context.Context, resourceGroupName string, hcpOpenShiftClusterName string, options *generated.HcpOpenShiftClustersClientAdminCredentialsOptions) (resp azfake.Responder[generated.HcpOpenShiftClustersClientAdminCredentialsResponse], errResp azfake.ErrorResponder) @@ -56,6 +54,7 @@ type HcpOpenShiftClustersServer struct { // BeginUpdate is the fake for method HcpOpenShiftClustersClient.BeginUpdate // HTTP status codes to indicate success: http.StatusOK, http.StatusAccepted BeginUpdate func(ctx context.Context, resourceGroupName string, hcpOpenShiftClusterName string, properties generated.HcpOpenShiftClusterPatch, options *generated.HcpOpenShiftClustersClientBeginUpdateOptions) (resp azfake.PollerResponder[generated.HcpOpenShiftClustersClientUpdateResponse], errResp azfake.ErrorResponder) + } // NewHcpOpenShiftClustersServerTransport creates a new instance of HcpOpenShiftClustersServerTransport with the provided implementation. @@ -63,24 +62,24 @@ type HcpOpenShiftClustersServer struct { // azcore.ClientOptions.Transporter field in the client's constructor parameters. func NewHcpOpenShiftClustersServerTransport(srv *HcpOpenShiftClustersServer) *HcpOpenShiftClustersServerTransport { return &HcpOpenShiftClustersServerTransport{ - srv: srv, - beginCreateOrUpdate: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientCreateOrUpdateResponse]](), - beginDelete: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientDeleteResponse]](), + srv: srv, + beginCreateOrUpdate: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientCreateOrUpdateResponse]](), + beginDelete: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientDeleteResponse]](), newListByResourceGroupPager: newTracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListByResourceGroupResponse]](), - newListBySubscriptionPager: newTracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListBySubscriptionResponse]](), - beginUpdate: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientUpdateResponse]](), + newListBySubscriptionPager: newTracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListBySubscriptionResponse]](), + beginUpdate: newTracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientUpdateResponse]](), } } // HcpOpenShiftClustersServerTransport connects instances of generated.HcpOpenShiftClustersClient to instances of HcpOpenShiftClustersServer. // Don't use this type directly, use NewHcpOpenShiftClustersServerTransport instead. type HcpOpenShiftClustersServerTransport struct { - srv *HcpOpenShiftClustersServer - beginCreateOrUpdate *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientCreateOrUpdateResponse]] - beginDelete *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientDeleteResponse]] + srv *HcpOpenShiftClustersServer + beginCreateOrUpdate *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientCreateOrUpdateResponse]] + beginDelete *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientDeleteResponse]] newListByResourceGroupPager *tracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListByResourceGroupResponse]] - newListBySubscriptionPager *tracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListBySubscriptionResponse]] - beginUpdate *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientUpdateResponse]] + newListBySubscriptionPager *tracker[azfake.PagerResponder[generated.HcpOpenShiftClustersClientListBySubscriptionResponse]] + beginUpdate *tracker[azfake.PollerResponder[generated.HcpOpenShiftClustersClientUpdateResponse]] } // Do implements the policy.Transporter interface for HcpOpenShiftClustersServerTransport. @@ -161,28 +160,28 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchBeginCreateOrUpdate(req *h } beginCreateOrUpdate := h.beginCreateOrUpdate.get(req) if beginCreateOrUpdate == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 3 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterResource](req) - if err != nil { - return nil, err - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - respr, errRespr := h.srv.BeginCreateOrUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, body, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 3 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterResource](req) + if err != nil { + return nil, err + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + respr, errRespr := h.srv.BeginCreateOrUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, body, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginCreateOrUpdate = &respr h.beginCreateOrUpdate.add(req, beginCreateOrUpdate) } @@ -209,24 +208,24 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchBeginDelete(req *http.Requ } beginDelete := h.beginDelete.get(req) if beginDelete == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 3 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - respr, errRespr := h.srv.BeginDelete(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 3 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + respr, errRespr := h.srv.BeginDelete(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginDelete = &respr h.beginDelete.add(req, beginDelete) } @@ -319,17 +318,17 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchNewListByResourceGroupPage } newListByResourceGroupPager := h.newListByResourceGroupPager.get(req) if newListByResourceGroupPager == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 2 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - resp := h.srv.NewListByResourceGroupPager(resourceGroupNameParam, nil) + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 2 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } +resp := h.srv.NewListByResourceGroupPager(resourceGroupNameParam, nil) newListByResourceGroupPager = &resp h.newListByResourceGroupPager.add(req, newListByResourceGroupPager) server.PagerResponderInjectNextLinks(newListByResourceGroupPager, req, func(page *generated.HcpOpenShiftClustersClientListByResourceGroupResponse, createLink func() string) { @@ -356,13 +355,13 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchNewListBySubscriptionPager } newListBySubscriptionPager := h.newListBySubscriptionPager.get(req) if newListBySubscriptionPager == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 1 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - resp := h.srv.NewListBySubscriptionPager(nil) + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 1 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } +resp := h.srv.NewListBySubscriptionPager(nil) newListBySubscriptionPager = &resp h.newListBySubscriptionPager.add(req, newListBySubscriptionPager) server.PagerResponderInjectNextLinks(newListBySubscriptionPager, req, func(page *generated.HcpOpenShiftClustersClientListBySubscriptionResponse, createLink func() string) { @@ -389,28 +388,28 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchBeginUpdate(req *http.Requ } beginUpdate := h.beginUpdate.get(req) if beginUpdate == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 3 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterPatch](req) - if err != nil { - return nil, err - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - respr, errRespr := h.srv.BeginUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, body, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 3 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterPatch](req) + if err != nil { + return nil, err + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + respr, errRespr := h.srv.BeginUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, body, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginUpdate = &respr h.beginUpdate.add(req, beginUpdate) } @@ -430,3 +429,4 @@ func (h *HcpOpenShiftClustersServerTransport) dispatchBeginUpdate(req *http.Requ return resp, nil } + diff --git a/internal/api/v20240610preview/generated/fake/internal.go b/internal/api/v20240610preview/generated/fake/internal.go index 20d9a0b32..1b914a3c8 100644 --- a/internal/api/v20240610preview/generated/fake/internal.go +++ b/internal/api/v20240610preview/generated/fake/internal.go @@ -1,19 +1,19 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. package fake import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "net/http" "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" ) + type nonRetriableError struct { error } @@ -39,7 +39,7 @@ func newTracker[T any]() *tracker[T] { type tracker[T any] struct { items map[string]*T - mu sync.Mutex + mu sync.Mutex } func (p *tracker[T]) get(req *http.Request) *T { diff --git a/internal/api/v20240610preview/generated/fake/nodepools_server.go b/internal/api/v20240610preview/generated/fake/nodepools_server.go index fa9df3d04..22cf05f07 100644 --- a/internal/api/v20240610preview/generated/fake/nodepools_server.go +++ b/internal/api/v20240610preview/generated/fake/nodepools_server.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -11,20 +11,18 @@ import ( "context" "errors" "fmt" - "net/http" - "net/url" - "regexp" - + "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" azfake "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - - "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" + "net/http" + "net/url" + "regexp" ) // NodePoolsServer is a fake server for instances of the generated.NodePoolsClient type. -type NodePoolsServer struct { +type NodePoolsServer struct{ // BeginCreateOrUpdate is the fake for method NodePoolsClient.BeginCreateOrUpdate // HTTP status codes to indicate success: http.StatusOK, http.StatusCreated BeginCreateOrUpdate func(ctx context.Context, resourceGroupName string, hcpOpenShiftClusterName string, nodePoolName string, resource generated.HcpOpenShiftClusterNodePoolResource, options *generated.NodePoolsClientBeginCreateOrUpdateOptions) (resp azfake.PollerResponder[generated.NodePoolsClientCreateOrUpdateResponse], errResp azfake.ErrorResponder) @@ -44,6 +42,7 @@ type NodePoolsServer struct { // BeginUpdate is the fake for method NodePoolsClient.BeginUpdate // HTTP status codes to indicate success: http.StatusOK, http.StatusAccepted BeginUpdate func(ctx context.Context, resourceGroupName string, hcpOpenShiftClusterName string, nodePoolName string, properties generated.HcpOpenShiftClusterNodePoolPatch, options *generated.NodePoolsClientBeginUpdateOptions) (resp azfake.PollerResponder[generated.NodePoolsClientUpdateResponse], errResp azfake.ErrorResponder) + } // NewNodePoolsServerTransport creates a new instance of NodePoolsServerTransport with the provided implementation. @@ -51,22 +50,22 @@ type NodePoolsServer struct { // azcore.ClientOptions.Transporter field in the client's constructor parameters. func NewNodePoolsServerTransport(srv *NodePoolsServer) *NodePoolsServerTransport { return &NodePoolsServerTransport{ - srv: srv, - beginCreateOrUpdate: newTracker[azfake.PollerResponder[generated.NodePoolsClientCreateOrUpdateResponse]](), - beginDelete: newTracker[azfake.PollerResponder[generated.NodePoolsClientDeleteResponse]](), + srv: srv, + beginCreateOrUpdate: newTracker[azfake.PollerResponder[generated.NodePoolsClientCreateOrUpdateResponse]](), + beginDelete: newTracker[azfake.PollerResponder[generated.NodePoolsClientDeleteResponse]](), newListByParentPager: newTracker[azfake.PagerResponder[generated.NodePoolsClientListByParentResponse]](), - beginUpdate: newTracker[azfake.PollerResponder[generated.NodePoolsClientUpdateResponse]](), + beginUpdate: newTracker[azfake.PollerResponder[generated.NodePoolsClientUpdateResponse]](), } } // NodePoolsServerTransport connects instances of generated.NodePoolsClient to instances of NodePoolsServer. // Don't use this type directly, use NewNodePoolsServerTransport instead. type NodePoolsServerTransport struct { - srv *NodePoolsServer - beginCreateOrUpdate *tracker[azfake.PollerResponder[generated.NodePoolsClientCreateOrUpdateResponse]] - beginDelete *tracker[azfake.PollerResponder[generated.NodePoolsClientDeleteResponse]] + srv *NodePoolsServer + beginCreateOrUpdate *tracker[azfake.PollerResponder[generated.NodePoolsClientCreateOrUpdateResponse]] + beginDelete *tracker[azfake.PollerResponder[generated.NodePoolsClientDeleteResponse]] newListByParentPager *tracker[azfake.PagerResponder[generated.NodePoolsClientListByParentResponse]] - beginUpdate *tracker[azfake.PollerResponder[generated.NodePoolsClientUpdateResponse]] + beginUpdate *tracker[azfake.PollerResponder[generated.NodePoolsClientUpdateResponse]] } // Do implements the policy.Transporter interface for NodePoolsServerTransport. @@ -108,32 +107,32 @@ func (n *NodePoolsServerTransport) dispatchBeginCreateOrUpdate(req *http.Request } beginCreateOrUpdate := n.beginCreateOrUpdate.get(req) if beginCreateOrUpdate == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 4 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterNodePoolResource](req) - if err != nil { - return nil, err - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) - if err != nil { - return nil, err - } - respr, errRespr := n.srv.BeginCreateOrUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, body, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 4 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterNodePoolResource](req) + if err != nil { + return nil, err + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) + if err != nil { + return nil, err + } + respr, errRespr := n.srv.BeginCreateOrUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, body, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginCreateOrUpdate = &respr n.beginCreateOrUpdate.add(req, beginCreateOrUpdate) } @@ -160,28 +159,28 @@ func (n *NodePoolsServerTransport) dispatchBeginDelete(req *http.Request) (*http } beginDelete := n.beginDelete.get(req) if beginDelete == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 4 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) - if err != nil { - return nil, err - } - respr, errRespr := n.srv.BeginDelete(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 4 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) + if err != nil { + return nil, err + } + respr, errRespr := n.srv.BeginDelete(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginDelete = &respr n.beginDelete.add(req, beginDelete) } @@ -245,21 +244,21 @@ func (n *NodePoolsServerTransport) dispatchNewListByParentPager(req *http.Reques } newListByParentPager := n.newListByParentPager.get(req) if newListByParentPager == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 3 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - resp := n.srv.NewListByParentPager(resourceGroupNameParam, hcpOpenShiftClusterNameParam, nil) + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 3 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } +resp := n.srv.NewListByParentPager(resourceGroupNameParam, hcpOpenShiftClusterNameParam, nil) newListByParentPager = &resp n.newListByParentPager.add(req, newListByParentPager) server.PagerResponderInjectNextLinks(newListByParentPager, req, func(page *generated.NodePoolsClientListByParentResponse, createLink func() string) { @@ -286,32 +285,32 @@ func (n *NodePoolsServerTransport) dispatchBeginUpdate(req *http.Request) (*http } beginUpdate := n.beginUpdate.get(req) if beginUpdate == nil { - const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` - regex := regexp.MustCompile(regexStr) - matches := regex.FindStringSubmatch(req.URL.EscapedPath()) - if matches == nil || len(matches) < 4 { - return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) - } - body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterNodePoolPatch](req) - if err != nil { - return nil, err - } - resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) - if err != nil { - return nil, err - } - hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) - if err != nil { - return nil, err - } - nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) - if err != nil { - return nil, err - } - respr, errRespr := n.srv.BeginUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, body, nil) - if respErr := server.GetError(errRespr, req); respErr != nil { - return nil, respErr - } + const regexStr = `/subscriptions/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/resourceGroups/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/providers/Microsoft\.RedHatOpenShift/hcpOpenShiftClusters/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)/nodePools/(?P[!#&$-;=?-\[\]_a-zA-Z0-9~%@]+)` + regex := regexp.MustCompile(regexStr) + matches := regex.FindStringSubmatch(req.URL.EscapedPath()) + if matches == nil || len(matches) < 4 { + return nil, fmt.Errorf("failed to parse path %s", req.URL.Path) + } + body, err := server.UnmarshalRequestAsJSON[generated.HcpOpenShiftClusterNodePoolPatch](req) + if err != nil { + return nil, err + } + resourceGroupNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("resourceGroupName")]) + if err != nil { + return nil, err + } + hcpOpenShiftClusterNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("hcpOpenShiftClusterName")]) + if err != nil { + return nil, err + } + nodePoolNameParam, err := url.PathUnescape(matches[regex.SubexpIndex("nodePoolName")]) + if err != nil { + return nil, err + } + respr, errRespr := n.srv.BeginUpdate(req.Context(), resourceGroupNameParam, hcpOpenShiftClusterNameParam, nodePoolNameParam, body, nil) + if respErr := server.GetError(errRespr, req); respErr != nil { + return nil, respErr + } beginUpdate = &respr n.beginUpdate.add(req, beginUpdate) } @@ -331,3 +330,4 @@ func (n *NodePoolsServerTransport) dispatchBeginUpdate(req *http.Request) (*http return resp, nil } + diff --git a/internal/api/v20240610preview/generated/fake/operations_server.go b/internal/api/v20240610preview/generated/fake/operations_server.go index e02368bbc..6208f5b0b 100644 --- a/internal/api/v20240610preview/generated/fake/operations_server.go +++ b/internal/api/v20240610preview/generated/fake/operations_server.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,21 +10,20 @@ package fake import ( "errors" "fmt" - "net/http" - + "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" azfake "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake/server" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - - "github.com/Azure/ARO-HCP/internal/api/v20240610preview/generated" + "net/http" ) // OperationsServer is a fake server for instances of the generated.OperationsClient type. -type OperationsServer struct { +type OperationsServer struct{ // NewListPager is the fake for method OperationsClient.NewListPager // HTTP status codes to indicate success: http.StatusOK NewListPager func(options *generated.OperationsClientListOptions) (resp azfake.PagerResponder[generated.OperationsClientListResponse]) + } // NewOperationsServerTransport creates a new instance of OperationsServerTransport with the provided implementation. @@ -32,7 +31,7 @@ type OperationsServer struct { // azcore.ClientOptions.Transporter field in the client's constructor parameters. func NewOperationsServerTransport(srv *OperationsServer) *OperationsServerTransport { return &OperationsServerTransport{ - srv: srv, + srv: srv, newListPager: newTracker[azfake.PagerResponder[generated.OperationsClientListResponse]](), } } @@ -40,7 +39,7 @@ func NewOperationsServerTransport(srv *OperationsServer) *OperationsServerTransp // OperationsServerTransport connects instances of generated.OperationsClient to instances of OperationsServer. // Don't use this type directly, use NewOperationsServerTransport instead. type OperationsServerTransport struct { - srv *OperationsServer + srv *OperationsServer newListPager *tracker[azfake.PagerResponder[generated.OperationsClientListResponse]] } @@ -75,7 +74,7 @@ func (o *OperationsServerTransport) dispatchNewListPager(req *http.Request) (*ht } newListPager := o.newListPager.get(req) if newListPager == nil { - resp := o.srv.NewListPager(nil) +resp := o.srv.NewListPager(nil) newListPager = &resp o.newListPager.add(req, newListPager) server.PagerResponderInjectNextLinks(newListPager, req, func(page *generated.OperationsClientListResponse, createLink func() string) { @@ -95,3 +94,4 @@ func (o *OperationsServerTransport) dispatchNewListPager(req *http.Request) (*ht } return resp, nil } + diff --git a/internal/api/v20240610preview/generated/fake/server_factory.go b/internal/api/v20240610preview/generated/fake/server_factory.go index 1b0355bd4..767fdb2d3 100644 --- a/internal/api/v20240610preview/generated/fake/server_factory.go +++ b/internal/api/v20240610preview/generated/fake/server_factory.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,19 +10,18 @@ package fake import ( "errors" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "net/http" "strings" "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" ) // ServerFactory is a fake server for instances of the generated.ClientFactory type. type ServerFactory struct { - HcpClusterVersionsServer HcpClusterVersionsServer + HcpClusterVersionsServer HcpClusterVersionsServer HcpOpenShiftClustersServer HcpOpenShiftClustersServer - NodePoolsServer NodePoolsServer - OperationsServer OperationsServer + NodePoolsServer NodePoolsServer + OperationsServer OperationsServer } // NewServerFactoryTransport creates a new instance of ServerFactoryTransport with the provided implementation. @@ -37,12 +36,12 @@ func NewServerFactoryTransport(srv *ServerFactory) *ServerFactoryTransport { // ServerFactoryTransport connects instances of generated.ClientFactory to instances of ServerFactory. // Don't use this type directly, use NewServerFactoryTransport instead. type ServerFactoryTransport struct { - srv *ServerFactory - trMu sync.Mutex - trHcpClusterVersionsServer *HcpClusterVersionsServerTransport + srv *ServerFactory + trMu sync.Mutex + trHcpClusterVersionsServer *HcpClusterVersionsServerTransport trHcpOpenShiftClustersServer *HcpOpenShiftClustersServerTransport - trNodePoolsServer *NodePoolsServerTransport - trOperationsServer *OperationsServerTransport + trNodePoolsServer *NodePoolsServerTransport + trOperationsServer *OperationsServerTransport } // Do implements the policy.Transporter interface for ServerFactoryTransport. @@ -59,14 +58,10 @@ func (s *ServerFactoryTransport) Do(req *http.Request) (*http.Response, error) { switch client { case "HcpClusterVersionsClient": - initServer(s, &s.trHcpClusterVersionsServer, func() *HcpClusterVersionsServerTransport { - return NewHcpClusterVersionsServerTransport(&s.srv.HcpClusterVersionsServer) - }) + initServer(s, &s.trHcpClusterVersionsServer, func() *HcpClusterVersionsServerTransport { return NewHcpClusterVersionsServerTransport(&s.srv.HcpClusterVersionsServer) }) resp, err = s.trHcpClusterVersionsServer.Do(req) case "HcpOpenShiftClustersClient": - initServer(s, &s.trHcpOpenShiftClustersServer, func() *HcpOpenShiftClustersServerTransport { - return NewHcpOpenShiftClustersServerTransport(&s.srv.HcpOpenShiftClustersServer) - }) + initServer(s, &s.trHcpOpenShiftClustersServer, func() *HcpOpenShiftClustersServerTransport { return NewHcpOpenShiftClustersServerTransport(&s.srv.HcpOpenShiftClustersServer) }) resp, err = s.trHcpOpenShiftClustersServer.Do(req) case "NodePoolsClient": initServer(s, &s.trNodePoolsServer, func() *NodePoolsServerTransport { return NewNodePoolsServerTransport(&s.srv.NodePoolsServer) }) diff --git a/internal/api/v20240610preview/generated/fake/time_rfc3339.go b/internal/api/v20240610preview/generated/fake/time_rfc3339.go index f2c4f2034..e48ebd541 100644 --- a/internal/api/v20240610preview/generated/fake/time_rfc3339.go +++ b/internal/api/v20240610preview/generated/fake/time_rfc3339.go @@ -1,23 +1,26 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. package fake + + import ( "encoding/json" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "reflect" "regexp" "strings" "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" ) + + // Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. var tzOffsetRegex = regexp.MustCompile(`(?:Z|z|\+|-)(?:\d+:\d+)*"*$`) @@ -59,7 +62,7 @@ func (t *dateTimeRFC3339) UnmarshalJSON(data []byte) error { return t.Parse(layout, string(data)) } -func (t *dateTimeRFC3339) UnmarshalText(data []byte) error { +func (t *dateTimeRFC3339) UnmarshalText(data []byte) (error) { tzOffset := tzOffsetRegex.Match(data) hasT := strings.Contains(string(data), "T") || strings.Contains(string(data), "t") var layout string @@ -85,6 +88,7 @@ func (t dateTimeRFC3339) String() string { return time.Time(t).Format(time.RFC3339Nano) } + func populateDateTimeRFC3339(m map[string]any, k string, t *time.Time) { if t == nil { return diff --git a/internal/api/v20240610preview/generated/hcpclusterversions_client.go b/internal/api/v20240610preview/generated/hcpclusterversions_client.go index 9e1ca9b67..d147d9f97 100644 --- a/internal/api/v20240610preview/generated/hcpclusterversions_client.go +++ b/internal/api/v20240610preview/generated/hcpclusterversions_client.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,20 +10,19 @@ package generated import ( "context" "errors" - "net/http" - "net/url" - "strings" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" ) // HcpClusterVersionsClient contains the methods for the HcpClusterVersions group. // Don't use this type directly, use NewHcpClusterVersionsClient() instead. type HcpClusterVersionsClient struct { - internal *arm.Client + internal *arm.Client subscriptionID string } @@ -38,7 +37,7 @@ func NewHcpClusterVersionsClient(subscriptionID string, credential azcore.TokenC } client := &HcpClusterVersionsClient{ subscriptionID: subscriptionID, - internal: cl, + internal: cl, } return client, nil } @@ -49,13 +48,13 @@ func NewHcpClusterVersionsClient(subscriptionID string, credential azcore.TokenC // - location - The name of the Azure region. // - options - HcpClusterVersionsClientListOptions contains the optional parameters for the HcpClusterVersionsClient.NewListPager // method. -func (client *HcpClusterVersionsClient) NewListPager(location string, options *HcpClusterVersionsClientListOptions) *runtime.Pager[HcpClusterVersionsClientListResponse] { +func (client *HcpClusterVersionsClient) NewListPager(location string, options *HcpClusterVersionsClientListOptions) (*runtime.Pager[HcpClusterVersionsClientListResponse]) { return runtime.NewPager(runtime.PagingHandler[HcpClusterVersionsClientListResponse]{ More: func(page HcpClusterVersionsClientListResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *HcpClusterVersionsClientListResponse) (HcpClusterVersionsClientListResponse, error) { - ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpClusterVersionsClient.NewListPager") + ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpClusterVersionsClient.NewListPager") nextLink := "" if page != nil { nextLink = *page.NextLink @@ -67,7 +66,7 @@ func (client *HcpClusterVersionsClient) NewListPager(location string, options *H return HcpClusterVersionsClientListResponse{}, err } return client.listHandleResponse(resp) - }, + }, Tracer: client.internal.Tracer(), }) } @@ -102,3 +101,4 @@ func (client *HcpClusterVersionsClient) listHandleResponse(resp *http.Response) } return result, nil } + diff --git a/internal/api/v20240610preview/generated/hcpopenshiftclusters_client.go b/internal/api/v20240610preview/generated/hcpopenshiftclusters_client.go index 677206231..67aa5d5a2 100644 --- a/internal/api/v20240610preview/generated/hcpopenshiftclusters_client.go +++ b/internal/api/v20240610preview/generated/hcpopenshiftclusters_client.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,20 +10,19 @@ package generated import ( "context" "errors" - "net/http" - "net/url" - "strings" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" ) // HcpOpenShiftClustersClient contains the methods for the HcpOpenShiftClusters group. // Don't use this type directly, use NewHcpOpenShiftClustersClient() instead. type HcpOpenShiftClustersClient struct { - internal *arm.Client + internal *arm.Client subscriptionID string } @@ -38,7 +37,7 @@ func NewHcpOpenShiftClustersClient(subscriptionID string, credential azcore.Toke } client := &HcpOpenShiftClustersClient{ subscriptionID: subscriptionID, - internal: cl, + internal: cl, } return client, nil } @@ -125,7 +124,7 @@ func (client *HcpOpenShiftClustersClient) BeginCreateOrUpdate(ctx context.Contex } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[HcpOpenShiftClustersClientCreateOrUpdateResponse]{ FinalStateVia: runtime.FinalStateViaAzureAsyncOp, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -184,8 +183,8 @@ func (client *HcpOpenShiftClustersClient) createOrUpdateCreateRequest(ctx contex req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, resource); err != nil { - return nil, err - } + return nil, err +} return req, nil } @@ -205,7 +204,7 @@ func (client *HcpOpenShiftClustersClient) BeginDelete(ctx context.Context, resou } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[HcpOpenShiftClustersClientDeleteResponse]{ FinalStateVia: runtime.FinalStateViaLocation, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -402,13 +401,13 @@ func (client *HcpOpenShiftClustersClient) kubeConfigHandleResponse(resp *http.Re // - resourceGroupName - The name of the resource group. The name is case insensitive. // - options - HcpOpenShiftClustersClientListByResourceGroupOptions contains the optional parameters for the HcpOpenShiftClustersClient.NewListByResourceGroupPager // method. -func (client *HcpOpenShiftClustersClient) NewListByResourceGroupPager(resourceGroupName string, options *HcpOpenShiftClustersClientListByResourceGroupOptions) *runtime.Pager[HcpOpenShiftClustersClientListByResourceGroupResponse] { +func (client *HcpOpenShiftClustersClient) NewListByResourceGroupPager(resourceGroupName string, options *HcpOpenShiftClustersClientListByResourceGroupOptions) (*runtime.Pager[HcpOpenShiftClustersClientListByResourceGroupResponse]) { return runtime.NewPager(runtime.PagingHandler[HcpOpenShiftClustersClientListByResourceGroupResponse]{ More: func(page HcpOpenShiftClustersClientListByResourceGroupResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *HcpOpenShiftClustersClientListByResourceGroupResponse) (HcpOpenShiftClustersClientListByResourceGroupResponse, error) { - ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpOpenShiftClustersClient.NewListByResourceGroupPager") + ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpOpenShiftClustersClient.NewListByResourceGroupPager") nextLink := "" if page != nil { nextLink = *page.NextLink @@ -420,7 +419,7 @@ func (client *HcpOpenShiftClustersClient) NewListByResourceGroupPager(resourceGr return HcpOpenShiftClustersClientListByResourceGroupResponse{}, err } return client.listByResourceGroupHandleResponse(resp) - }, + }, Tracer: client.internal.Tracer(), }) } @@ -461,13 +460,13 @@ func (client *HcpOpenShiftClustersClient) listByResourceGroupHandleResponse(resp // Generated from API version 2024-06-10-preview // - options - HcpOpenShiftClustersClientListBySubscriptionOptions contains the optional parameters for the HcpOpenShiftClustersClient.NewListBySubscriptionPager // method. -func (client *HcpOpenShiftClustersClient) NewListBySubscriptionPager(options *HcpOpenShiftClustersClientListBySubscriptionOptions) *runtime.Pager[HcpOpenShiftClustersClientListBySubscriptionResponse] { +func (client *HcpOpenShiftClustersClient) NewListBySubscriptionPager(options *HcpOpenShiftClustersClientListBySubscriptionOptions) (*runtime.Pager[HcpOpenShiftClustersClientListBySubscriptionResponse]) { return runtime.NewPager(runtime.PagingHandler[HcpOpenShiftClustersClientListBySubscriptionResponse]{ More: func(page HcpOpenShiftClustersClientListBySubscriptionResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *HcpOpenShiftClustersClientListBySubscriptionResponse) (HcpOpenShiftClustersClientListBySubscriptionResponse, error) { - ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpOpenShiftClustersClient.NewListBySubscriptionPager") + ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "HcpOpenShiftClustersClient.NewListBySubscriptionPager") nextLink := "" if page != nil { nextLink = *page.NextLink @@ -479,7 +478,7 @@ func (client *HcpOpenShiftClustersClient) NewListBySubscriptionPager(options *Hc return HcpOpenShiftClustersClientListBySubscriptionResponse{}, err } return client.listBySubscriptionHandleResponse(resp) - }, + }, Tracer: client.internal.Tracer(), }) } @@ -528,7 +527,7 @@ func (client *HcpOpenShiftClustersClient) BeginUpdate(ctx context.Context, resou } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[HcpOpenShiftClustersClientUpdateResponse]{ FinalStateVia: runtime.FinalStateViaLocation, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -587,7 +586,8 @@ func (client *HcpOpenShiftClustersClient) updateCreateRequest(ctx context.Contex req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, properties); err != nil { - return nil, err - } + return nil, err +} return req, nil } + diff --git a/internal/api/v20240610preview/generated/models.go b/internal/api/v20240610preview/generated/models.go index ef14dc733..c74e04368 100644 --- a/internal/api/v20240610preview/generated/models.go +++ b/internal/api/v20240610preview/generated/models.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -57,7 +57,7 @@ type ClusterSpec struct { EtcdEncryption *bool // Configuration to override the openshift-oauth-apiserver inside cluster This changes user login into the cluster to external - // provider +// provider ExternalAuth *ExternalAuthConfigProfile // Enable FIPS mode for the cluster When set to true, etcdEncryption must be set to true @@ -96,7 +96,7 @@ type ConsoleProfile struct { // DNSProfile - DNS contains the DNS settings of the cluster type DNSProfile struct { // BaseDomainPrefix is the unique name of the cluster representing the OpenShift's cluster name. BaseDomainPrefix is the name - // that will appear in the cluster's DNS, provisioned cloud providers resources +// that will appear in the cluster's DNS, provisioned cloud providers resources BaseDomainPrefix *string // READ-ONLY; BaseDomain is the base DNS domain of the cluster. @@ -372,14 +372,14 @@ type ManagedServiceIdentity struct { Type *ManagedServiceIdentityType // The set of user assigned identities associated with the resource. The userAssignedIdentities dictionary keys will be ARM - // resource ids in the form: - // '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}. - // The dictionary values can be empty objects ({}) in - // requests. +// resource ids in the form: +// '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}. +// The dictionary values can be empty objects ({}) in +// requests. UserAssignedIdentities map[string]*UserAssignedIdentity // READ-ONLY; The service principal ID of the system assigned identity. This property will only be provided for a system assigned - // identity. +// identity. PrincipalID *string // READ-ONLY; The tenant ID of the system assigned identity. This property will only be provided for a system assigned identity. @@ -446,32 +446,32 @@ type NodePoolPatchSpec struct { Taints []*Taint // Tuning configs, TODO provide meaningful explanation TuningConfig is a list of references to ConfigMaps containing serialized - // Tuned resources to define the tuning configuration to be applied to nodes - // in the NodePool. Each ConfigMap must have a single key named "tuned" whose value is the JSON or YAML of a serialized Tuned - // or PerformanceProfile. +// Tuned resources to define the tuning configuration to be applied to nodes +// in the NodePool. Each ConfigMap must have a single key named "tuned" whose value is the JSON or YAML of a serialized Tuned +// or PerformanceProfile. TuningConfigs []*string } // NodePoolPlatformProfile - Azure node pool platform configuration type NodePoolPlatformProfile struct { // REQUIRED; The VM size according to the documentation: - // * https://learn.microsoft.com/en-us/azure/virtual-machines/sizes +// * https://learn.microsoft.com/en-us/azure/virtual-machines/sizes VMSize *string // The availability zone for the node pool. Please read the documentation to see which regions support availability zones - // * https://learn.microsoft.com/en-us/azure/availability-zones/az-overview +// * https://learn.microsoft.com/en-us/azure/availability-zones/az-overview AvailabilityZone *string // Disk Encryption Set ID that will be used for encryption the Nodes disks - // * https://learn.microsoft.com/en-us/azure/virtual-machines/disk-encryption-overview - // * https://learn.microsoft.com/en-us/azure/virtual-machines/disk-encryption +// * https://learn.microsoft.com/en-us/azure/virtual-machines/disk-encryption-overview +// * https://learn.microsoft.com/en-us/azure/virtual-machines/disk-encryption DiskEncryptionSetID *string // The OS disk size in GiB DiskSizeGiB *int32 // The type of the disk storage account - // * https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types +// * https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types DiskStorageAccountType *string // Whether the worker machines should be encrypted at host @@ -517,9 +517,9 @@ type NodePoolSpec struct { Taints []*Taint // Tuning configs, TODO provide meaningful explanation TuningConfig is a list of references to ConfigMaps containing serialized - // Tuned resources to define the tuning configuration to be applied to nodes - // in the NodePool. Each ConfigMap must have a single key named "tuned" whose value is the JSON or YAML of a serialized Tuned - // or PerformanceProfile. +// Tuned resources to define the tuning configuration to be applied to nodes +// in the NodePool. Each ConfigMap must have a single key named "tuned" whose value is the JSON or YAML of a serialized Tuned +// or PerformanceProfile. TuningConfigs []*string } @@ -532,15 +532,15 @@ type Operation struct { ActionType *ActionType // READ-ONLY; Whether the operation applies to data-plane. This is "true" for data-plane operations and "false" for ARM/control-plane - // operations. +// operations. IsDataAction *bool // READ-ONLY; The name of the operation, as per Resource-Based Access Control (RBAC). Examples: "Microsoft.Compute/virtualMachines/write", - // "Microsoft.Compute/virtualMachines/capture/action" +// "Microsoft.Compute/virtualMachines/capture/action" Name *string // READ-ONLY; The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default - // value is "user,system" +// value is "user,system" Origin *Origin } @@ -550,15 +550,15 @@ type OperationDisplay struct { Description *string // READ-ONLY; The concise, localized friendly name for the operation; suitable for dropdowns. E.g. "Create or Update Virtual - // Machine", "Restart Virtual Machine". +// Machine", "Restart Virtual Machine". Operation *string // READ-ONLY; The localized friendly form of the resource provider name, e.g. "Microsoft Monitoring Insights" or "Microsoft - // Compute". +// Compute". Provider *string // READ-ONLY; The localized friendly name of the resource type related to this operation. E.g. "Virtual Machines" or "Job - // Schedule Collections". +// Schedule Collections". Resource *string } @@ -572,21 +572,31 @@ type OperationListResult struct { Value []*Operation } +// OperatorsAuthenticationProfile - The configuration that the operators of the cluster have to authenticate to Azure. +type OperatorsAuthenticationProfile struct { + // REQUIRED; Represents the information related to Azure User-Assigned managed identities needed to perform Operators authentication +// based on Azure User-Assigned Managed Identities + UserAssignedIdentities *UserAssignedIdentitiesProfile +} + // PlatformProfile - Azure specific configuration type PlatformProfile struct { - // REQUIRED; ResourceId for the network security group attached to the cluster subnet - NetworkSecurityGroupID *string + // REQUIRED; The configuration that the operators of the cluster have to authenticate to Azure + OperatorsAuthentication *OperatorsAuthenticationProfile // REQUIRED; ResourceId for the subnet used by the control plane SubnetID *string // The id of the disk encryption set to be used for etcd. Configure this when etcdEncryption is set to true Is used the - // https://learn.microsoft.com/en-us/azure/storage/common/customer-managed-keys-overview +// https://learn.microsoft.com/en-us/azure/storage/common/customer-managed-keys-overview EtcdEncryptionSetID *string // Resource group to put cluster resources ManagedResourceGroup *string + // ResourceId for the network security group attached to the cluster subnet + NetworkSecurityGroupID *string + // The core outgoing configuration OutboundType *OutboundType } @@ -722,6 +732,22 @@ type TrackedResource struct { Type *string } +// UserAssignedIdentitiesProfile - Represents the information related to Azure User-Assigned managed identities needed to +// perform Operators authentication based on Azure User-Assigned Managed Identities +type UserAssignedIdentitiesProfile struct { + // REQUIRED; The set of Azure User-Assigned Managed Identities leveraged for the Control Plane operators of the cluster. The +// set of required managed identities is dependent on the Cluster's OpenShift version. + ControlPlaneOperators map[string]*string + + // REQUIRED; The set of Azure User-Assigned Managed Identities leveraged for the Data Plane operators of the cluster. The +// set of required managed identities is dependent on the Cluster's OpenShift version. + DataPlaneOperators map[string]*string + + // REQUIRED; Represents the information associated to an Azure User-Assigned Managed Identity whose purpose is to perform +// service level actions. + ServiceManagedIdentity *string +} + // UserAssignedIdentity - User assigned identity properties type UserAssignedIdentity struct { // READ-ONLY; The client ID of the assigned identity. @@ -742,3 +768,4 @@ type VersionProfile struct { // READ-ONLY; AvailableUpgrades is a list of version names the current version can be upgraded to. AvailableUpgrades []*string } + diff --git a/internal/api/v20240610preview/generated/models_serde.go b/internal/api/v20240610preview/generated/models_serde.go index 2573c28c2..4b3e11bf8 100644 --- a/internal/api/v20240610preview/generated/models_serde.go +++ b/internal/api/v20240610preview/generated/models_serde.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,9 +10,8 @@ package generated import ( "encoding/json" "fmt" - "reflect" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "reflect" ) // MarshalJSON implements the json.Marshaller interface for type APIProfile. @@ -33,10 +32,10 @@ func (a *APIProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "url": - err = unpopulate(val, "URL", &a.URL) + err = unpopulate(val, "URL", &a.URL) delete(rawMsg, key) case "visibility": - err = unpopulate(val, "Visibility", &a.Visibility) + err = unpopulate(val, "Visibility", &a.Visibility) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", a, key) @@ -67,13 +66,13 @@ func (c *ClaimProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "claim": - err = unpopulate(val, "Claim", &c.Claim) + err = unpopulate(val, "Claim", &c.Claim) delete(rawMsg, key) case "prefix": - err = unpopulate(val, "Prefix", &c.Prefix) + err = unpopulate(val, "Prefix", &c.Prefix) delete(rawMsg, key) case "prefixPolicy": - err = unpopulate(val, "PrefixPolicy", &c.PrefixPolicy) + err = unpopulate(val, "PrefixPolicy", &c.PrefixPolicy) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", c, key) @@ -103,10 +102,10 @@ func (c *ClusterPatchSpec) UnmarshalJSON(data []byte) error { var err error switch key { case "disableUserWorkloadMonitoring": - err = unpopulate(val, "DisableUserWorkloadMonitoring", &c.DisableUserWorkloadMonitoring) + err = unpopulate(val, "DisableUserWorkloadMonitoring", &c.DisableUserWorkloadMonitoring) delete(rawMsg, key) case "proxy": - err = unpopulate(val, "Proxy", &c.Proxy) + err = unpopulate(val, "Proxy", &c.Proxy) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", c, key) @@ -146,40 +145,40 @@ func (c *ClusterSpec) UnmarshalJSON(data []byte) error { var err error switch key { case "api": - err = unpopulate(val, "API", &c.API) + err = unpopulate(val, "API", &c.API) delete(rawMsg, key) case "console": - err = unpopulate(val, "Console", &c.Console) + err = unpopulate(val, "Console", &c.Console) delete(rawMsg, key) case "dns": - err = unpopulate(val, "DNS", &c.DNS) + err = unpopulate(val, "DNS", &c.DNS) delete(rawMsg, key) case "disableUserWorkloadMonitoring": - err = unpopulate(val, "DisableUserWorkloadMonitoring", &c.DisableUserWorkloadMonitoring) + err = unpopulate(val, "DisableUserWorkloadMonitoring", &c.DisableUserWorkloadMonitoring) delete(rawMsg, key) case "etcdEncryption": - err = unpopulate(val, "EtcdEncryption", &c.EtcdEncryption) + err = unpopulate(val, "EtcdEncryption", &c.EtcdEncryption) delete(rawMsg, key) case "externalAuth": - err = unpopulate(val, "ExternalAuth", &c.ExternalAuth) + err = unpopulate(val, "ExternalAuth", &c.ExternalAuth) delete(rawMsg, key) case "fips": - err = unpopulate(val, "Fips", &c.Fips) + err = unpopulate(val, "Fips", &c.Fips) delete(rawMsg, key) case "issuerUrl": - err = unpopulate(val, "IssuerURL", &c.IssuerURL) + err = unpopulate(val, "IssuerURL", &c.IssuerURL) delete(rawMsg, key) case "network": - err = unpopulate(val, "Network", &c.Network) + err = unpopulate(val, "Network", &c.Network) delete(rawMsg, key) case "platform": - err = unpopulate(val, "Platform", &c.Platform) + err = unpopulate(val, "Platform", &c.Platform) delete(rawMsg, key) case "proxy": - err = unpopulate(val, "Proxy", &c.Proxy) + err = unpopulate(val, "Proxy", &c.Proxy) delete(rawMsg, key) case "version": - err = unpopulate(val, "Version", &c.Version) + err = unpopulate(val, "Version", &c.Version) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", c, key) @@ -209,10 +208,10 @@ func (c *ComponentsQjfoe3SchemasManagedserviceidentityupdatePropertiesUserassign var err error switch key { case "clientId": - err = unpopulate(val, "ClientID", &c.ClientID) + err = unpopulate(val, "ClientID", &c.ClientID) delete(rawMsg, key) case "principalId": - err = unpopulate(val, "PrincipalID", &c.PrincipalID) + err = unpopulate(val, "PrincipalID", &c.PrincipalID) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", c, key) @@ -241,7 +240,7 @@ func (c *ConsoleProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "url": - err = unpopulate(val, "URL", &c.URL) + err = unpopulate(val, "URL", &c.URL) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", c, key) @@ -271,10 +270,10 @@ func (d *DNSProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "baseDomain": - err = unpopulate(val, "BaseDomain", &d.BaseDomain) + err = unpopulate(val, "BaseDomain", &d.BaseDomain) delete(rawMsg, key) case "baseDomainPrefix": - err = unpopulate(val, "BaseDomainPrefix", &d.BaseDomainPrefix) + err = unpopulate(val, "BaseDomainPrefix", &d.BaseDomainPrefix) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", d, key) @@ -304,10 +303,10 @@ func (e *ErrorAdditionalInfo) UnmarshalJSON(data []byte) error { var err error switch key { case "info": - err = unpopulate(val, "Info", &e.Info) + err = unpopulate(val, "Info", &e.Info) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &e.Type) + err = unpopulate(val, "Type", &e.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -340,19 +339,19 @@ func (e *ErrorDetail) UnmarshalJSON(data []byte) error { var err error switch key { case "additionalInfo": - err = unpopulate(val, "AdditionalInfo", &e.AdditionalInfo) + err = unpopulate(val, "AdditionalInfo", &e.AdditionalInfo) delete(rawMsg, key) case "code": - err = unpopulate(val, "Code", &e.Code) + err = unpopulate(val, "Code", &e.Code) delete(rawMsg, key) case "details": - err = unpopulate(val, "Details", &e.Details) + err = unpopulate(val, "Details", &e.Details) delete(rawMsg, key) case "message": - err = unpopulate(val, "Message", &e.Message) + err = unpopulate(val, "Message", &e.Message) delete(rawMsg, key) case "target": - err = unpopulate(val, "Target", &e.Target) + err = unpopulate(val, "Target", &e.Target) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -381,7 +380,7 @@ func (e *ErrorResponse) UnmarshalJSON(data []byte) error { var err error switch key { case "error": - err = unpopulate(val, "Error", &e.Error) + err = unpopulate(val, "Error", &e.Error) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -411,10 +410,10 @@ func (e *ExternalAuthClaimProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "mappings": - err = unpopulate(val, "Mappings", &e.Mappings) + err = unpopulate(val, "Mappings", &e.Mappings) delete(rawMsg, key) case "validationRules": - err = unpopulate(val, "ValidationRules", &e.ValidationRules) + err = unpopulate(val, "ValidationRules", &e.ValidationRules) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -444,10 +443,10 @@ func (e *ExternalAuthClientComponentProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "authClientNamespace": - err = unpopulate(val, "AuthClientNamespace", &e.AuthClientNamespace) + err = unpopulate(val, "AuthClientNamespace", &e.AuthClientNamespace) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &e.Name) + err = unpopulate(val, "Name", &e.Name) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -479,16 +478,16 @@ func (e *ExternalAuthClientProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "component": - err = unpopulate(val, "Component", &e.Component) + err = unpopulate(val, "Component", &e.Component) delete(rawMsg, key) case "extraScopes": - err = unpopulate(val, "ExtraScopes", &e.ExtraScopes) + err = unpopulate(val, "ExtraScopes", &e.ExtraScopes) delete(rawMsg, key) case "id": - err = unpopulate(val, "ID", &e.ID) + err = unpopulate(val, "ID", &e.ID) delete(rawMsg, key) case "secret": - err = unpopulate(val, "Secret", &e.Secret) + err = unpopulate(val, "Secret", &e.Secret) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -518,10 +517,10 @@ func (e *ExternalAuthConfigProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "enabled": - err = unpopulate(val, "Enabled", &e.Enabled) + err = unpopulate(val, "Enabled", &e.Enabled) delete(rawMsg, key) case "externalAuths": - err = unpopulate(val, "ExternalAuths", &e.ExternalAuths) + err = unpopulate(val, "ExternalAuths", &e.ExternalAuths) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -552,13 +551,13 @@ func (e *ExternalAuthProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "claim": - err = unpopulate(val, "Claim", &e.Claim) + err = unpopulate(val, "Claim", &e.Claim) delete(rawMsg, key) case "clients": - err = unpopulate(val, "Clients", &e.Clients) + err = unpopulate(val, "Clients", &e.Clients) delete(rawMsg, key) case "issuer": - err = unpopulate(val, "Issuer", &e.Issuer) + err = unpopulate(val, "Issuer", &e.Issuer) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", e, key) @@ -588,10 +587,10 @@ func (h *HcpOpenShiftClusterCredentials) UnmarshalJSON(data []byte) error { var err error switch key { case "kubeadminPassword": - err = unpopulate(val, "KubeadminPassword", &h.KubeadminPassword) + err = unpopulate(val, "KubeadminPassword", &h.KubeadminPassword) delete(rawMsg, key) case "kubeadminUsername": - err = unpopulate(val, "KubeadminUsername", &h.KubeadminUsername) + err = unpopulate(val, "KubeadminUsername", &h.KubeadminUsername) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -620,7 +619,7 @@ func (h *HcpOpenShiftClusterKubeconfig) UnmarshalJSON(data []byte) error { var err error switch key { case "kubeconfig": - err = unpopulate(val, "Kubeconfig", &h.Kubeconfig) + err = unpopulate(val, "Kubeconfig", &h.Kubeconfig) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -651,13 +650,13 @@ func (h *HcpOpenShiftClusterNodePoolPatch) UnmarshalJSON(data []byte) error { var err error switch key { case "identity": - err = unpopulate(val, "Identity", &h.Identity) + err = unpopulate(val, "Identity", &h.Identity) delete(rawMsg, key) case "properties": - err = unpopulate(val, "Properties", &h.Properties) + err = unpopulate(val, "Properties", &h.Properties) delete(rawMsg, key) case "tags": - err = unpopulate(val, "Tags", &h.Tags) + err = unpopulate(val, "Tags", &h.Tags) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -693,28 +692,28 @@ func (h *HcpOpenShiftClusterNodePoolResource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &h.ID) + err = unpopulate(val, "ID", &h.ID) delete(rawMsg, key) case "identity": - err = unpopulate(val, "Identity", &h.Identity) + err = unpopulate(val, "Identity", &h.Identity) delete(rawMsg, key) case "location": - err = unpopulate(val, "Location", &h.Location) + err = unpopulate(val, "Location", &h.Location) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &h.Name) + err = unpopulate(val, "Name", &h.Name) delete(rawMsg, key) case "properties": - err = unpopulate(val, "Properties", &h.Properties) + err = unpopulate(val, "Properties", &h.Properties) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &h.SystemData) + err = unpopulate(val, "SystemData", &h.SystemData) delete(rawMsg, key) case "tags": - err = unpopulate(val, "Tags", &h.Tags) + err = unpopulate(val, "Tags", &h.Tags) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &h.Type) + err = unpopulate(val, "Type", &h.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -744,10 +743,10 @@ func (h *HcpOpenShiftClusterNodePoolResourceListResult) UnmarshalJSON(data []byt var err error switch key { case "nextLink": - err = unpopulate(val, "NextLink", &h.NextLink) + err = unpopulate(val, "NextLink", &h.NextLink) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &h.Value) + err = unpopulate(val, "Value", &h.Value) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -778,13 +777,13 @@ func (h *HcpOpenShiftClusterPatch) UnmarshalJSON(data []byte) error { var err error switch key { case "identity": - err = unpopulate(val, "Identity", &h.Identity) + err = unpopulate(val, "Identity", &h.Identity) delete(rawMsg, key) case "properties": - err = unpopulate(val, "Properties", &h.Properties) + err = unpopulate(val, "Properties", &h.Properties) delete(rawMsg, key) case "tags": - err = unpopulate(val, "Tags", &h.Tags) + err = unpopulate(val, "Tags", &h.Tags) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -814,10 +813,10 @@ func (h *HcpOpenShiftClusterPatchProperties) UnmarshalJSON(data []byte) error { var err error switch key { case "provisioningState": - err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) + err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) delete(rawMsg, key) case "spec": - err = unpopulate(val, "Spec", &h.Spec) + err = unpopulate(val, "Spec", &h.Spec) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -847,10 +846,10 @@ func (h *HcpOpenShiftClusterProperties) UnmarshalJSON(data []byte) error { var err error switch key { case "provisioningState": - err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) + err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) delete(rawMsg, key) case "spec": - err = unpopulate(val, "Spec", &h.Spec) + err = unpopulate(val, "Spec", &h.Spec) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -886,28 +885,28 @@ func (h *HcpOpenShiftClusterResource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &h.ID) + err = unpopulate(val, "ID", &h.ID) delete(rawMsg, key) case "identity": - err = unpopulate(val, "Identity", &h.Identity) + err = unpopulate(val, "Identity", &h.Identity) delete(rawMsg, key) case "location": - err = unpopulate(val, "Location", &h.Location) + err = unpopulate(val, "Location", &h.Location) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &h.Name) + err = unpopulate(val, "Name", &h.Name) delete(rawMsg, key) case "properties": - err = unpopulate(val, "Properties", &h.Properties) + err = unpopulate(val, "Properties", &h.Properties) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &h.SystemData) + err = unpopulate(val, "SystemData", &h.SystemData) delete(rawMsg, key) case "tags": - err = unpopulate(val, "Tags", &h.Tags) + err = unpopulate(val, "Tags", &h.Tags) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &h.Type) + err = unpopulate(val, "Type", &h.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -937,10 +936,10 @@ func (h *HcpOpenShiftClusterResourceListResult) UnmarshalJSON(data []byte) error var err error switch key { case "nextLink": - err = unpopulate(val, "NextLink", &h.NextLink) + err = unpopulate(val, "NextLink", &h.NextLink) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &h.Value) + err = unpopulate(val, "Value", &h.Value) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -973,19 +972,19 @@ func (h *HcpOpenShiftVersionResource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &h.ID) + err = unpopulate(val, "ID", &h.ID) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &h.Name) + err = unpopulate(val, "Name", &h.Name) delete(rawMsg, key) case "properties": - err = unpopulate(val, "Properties", &h.Properties) + err = unpopulate(val, "Properties", &h.Properties) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &h.SystemData) + err = unpopulate(val, "SystemData", &h.SystemData) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &h.Type) + err = unpopulate(val, "Type", &h.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -1015,10 +1014,10 @@ func (h *HcpOpenShiftVersionResourceListResult) UnmarshalJSON(data []byte) error var err error switch key { case "nextLink": - err = unpopulate(val, "NextLink", &h.NextLink) + err = unpopulate(val, "NextLink", &h.NextLink) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &h.Value) + err = unpopulate(val, "Value", &h.Value) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -1048,10 +1047,10 @@ func (h *HcpOpenShiftVersionsProperties) UnmarshalJSON(data []byte) error { var err error switch key { case "clusterVersion": - err = unpopulate(val, "ClusterVersion", &h.ClusterVersion) + err = unpopulate(val, "ClusterVersion", &h.ClusterVersion) delete(rawMsg, key) case "provisioningState": - err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) + err = unpopulate(val, "ProvisioningState", &h.ProvisioningState) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", h, key) @@ -1081,10 +1080,10 @@ func (l *Label) UnmarshalJSON(data []byte) error { var err error switch key { case "key": - err = unpopulate(val, "Key", &l.Key) + err = unpopulate(val, "Key", &l.Key) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &l.Value) + err = unpopulate(val, "Value", &l.Value) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", l, key) @@ -1116,16 +1115,16 @@ func (m *ManagedServiceIdentity) UnmarshalJSON(data []byte) error { var err error switch key { case "principalId": - err = unpopulate(val, "PrincipalID", &m.PrincipalID) + err = unpopulate(val, "PrincipalID", &m.PrincipalID) delete(rawMsg, key) case "tenantId": - err = unpopulate(val, "TenantID", &m.TenantID) + err = unpopulate(val, "TenantID", &m.TenantID) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &m.Type) + err = unpopulate(val, "Type", &m.Type) delete(rawMsg, key) case "userAssignedIdentities": - err = unpopulate(val, "UserAssignedIdentities", &m.UserAssignedIdentities) + err = unpopulate(val, "UserAssignedIdentities", &m.UserAssignedIdentities) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", m, key) @@ -1155,10 +1154,10 @@ func (m *ManagedServiceIdentityUpdate) UnmarshalJSON(data []byte) error { var err error switch key { case "type": - err = unpopulate(val, "Type", &m.Type) + err = unpopulate(val, "Type", &m.Type) delete(rawMsg, key) case "userAssignedIdentities": - err = unpopulate(val, "UserAssignedIdentities", &m.UserAssignedIdentities) + err = unpopulate(val, "UserAssignedIdentities", &m.UserAssignedIdentities) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", m, key) @@ -1191,19 +1190,19 @@ func (n *NetworkProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "hostPrefix": - err = unpopulate(val, "HostPrefix", &n.HostPrefix) + err = unpopulate(val, "HostPrefix", &n.HostPrefix) delete(rawMsg, key) case "machineCidr": - err = unpopulate(val, "MachineCidr", &n.MachineCidr) + err = unpopulate(val, "MachineCidr", &n.MachineCidr) delete(rawMsg, key) case "networkType": - err = unpopulate(val, "NetworkType", &n.NetworkType) + err = unpopulate(val, "NetworkType", &n.NetworkType) delete(rawMsg, key) case "podCidr": - err = unpopulate(val, "PodCidr", &n.PodCidr) + err = unpopulate(val, "PodCidr", &n.PodCidr) delete(rawMsg, key) case "serviceCidr": - err = unpopulate(val, "ServiceCidr", &n.ServiceCidr) + err = unpopulate(val, "ServiceCidr", &n.ServiceCidr) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1233,10 +1232,10 @@ func (n *NodePoolAutoScaling) UnmarshalJSON(data []byte) error { var err error switch key { case "max": - err = unpopulate(val, "Max", &n.Max) + err = unpopulate(val, "Max", &n.Max) delete(rawMsg, key) case "min": - err = unpopulate(val, "Min", &n.Min) + err = unpopulate(val, "Min", &n.Min) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1266,10 +1265,10 @@ func (n *NodePoolPatchProperties) UnmarshalJSON(data []byte) error { var err error switch key { case "provisioningState": - err = unpopulate(val, "ProvisioningState", &n.ProvisioningState) + err = unpopulate(val, "ProvisioningState", &n.ProvisioningState) delete(rawMsg, key) case "spec": - err = unpopulate(val, "Spec", &n.Spec) + err = unpopulate(val, "Spec", &n.Spec) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1302,19 +1301,19 @@ func (n *NodePoolPatchSpec) UnmarshalJSON(data []byte) error { var err error switch key { case "autoScaling": - err = unpopulate(val, "AutoScaling", &n.AutoScaling) + err = unpopulate(val, "AutoScaling", &n.AutoScaling) delete(rawMsg, key) case "labels": - err = unpopulate(val, "Labels", &n.Labels) + err = unpopulate(val, "Labels", &n.Labels) delete(rawMsg, key) case "replicas": - err = unpopulate(val, "Replicas", &n.Replicas) + err = unpopulate(val, "Replicas", &n.Replicas) delete(rawMsg, key) case "taints": - err = unpopulate(val, "Taints", &n.Taints) + err = unpopulate(val, "Taints", &n.Taints) delete(rawMsg, key) case "tuningConfigs": - err = unpopulate(val, "TuningConfigs", &n.TuningConfigs) + err = unpopulate(val, "TuningConfigs", &n.TuningConfigs) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1350,28 +1349,28 @@ func (n *NodePoolPlatformProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "availabilityZone": - err = unpopulate(val, "AvailabilityZone", &n.AvailabilityZone) + err = unpopulate(val, "AvailabilityZone", &n.AvailabilityZone) delete(rawMsg, key) case "diskEncryptionSetId": - err = unpopulate(val, "DiskEncryptionSetID", &n.DiskEncryptionSetID) + err = unpopulate(val, "DiskEncryptionSetID", &n.DiskEncryptionSetID) delete(rawMsg, key) case "diskSizeGiB": - err = unpopulate(val, "DiskSizeGiB", &n.DiskSizeGiB) + err = unpopulate(val, "DiskSizeGiB", &n.DiskSizeGiB) delete(rawMsg, key) case "diskStorageAccountType": - err = unpopulate(val, "DiskStorageAccountType", &n.DiskStorageAccountType) + err = unpopulate(val, "DiskStorageAccountType", &n.DiskStorageAccountType) delete(rawMsg, key) case "encryptionAtHost": - err = unpopulate(val, "EncryptionAtHost", &n.EncryptionAtHost) + err = unpopulate(val, "EncryptionAtHost", &n.EncryptionAtHost) delete(rawMsg, key) case "ephemeralOsDisk": - err = unpopulate(val, "EphemeralOsDisk", &n.EphemeralOsDisk) + err = unpopulate(val, "EphemeralOsDisk", &n.EphemeralOsDisk) delete(rawMsg, key) case "subnetId": - err = unpopulate(val, "SubnetID", &n.SubnetID) + err = unpopulate(val, "SubnetID", &n.SubnetID) delete(rawMsg, key) case "vmSize": - err = unpopulate(val, "VMSize", &n.VMSize) + err = unpopulate(val, "VMSize", &n.VMSize) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1401,10 +1400,10 @@ func (n *NodePoolProperties) UnmarshalJSON(data []byte) error { var err error switch key { case "provisioningState": - err = unpopulate(val, "ProvisioningState", &n.ProvisioningState) + err = unpopulate(val, "ProvisioningState", &n.ProvisioningState) delete(rawMsg, key) case "spec": - err = unpopulate(val, "Spec", &n.Spec) + err = unpopulate(val, "Spec", &n.Spec) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1440,28 +1439,28 @@ func (n *NodePoolSpec) UnmarshalJSON(data []byte) error { var err error switch key { case "autoRepair": - err = unpopulate(val, "AutoRepair", &n.AutoRepair) + err = unpopulate(val, "AutoRepair", &n.AutoRepair) delete(rawMsg, key) case "autoScaling": - err = unpopulate(val, "AutoScaling", &n.AutoScaling) + err = unpopulate(val, "AutoScaling", &n.AutoScaling) delete(rawMsg, key) case "labels": - err = unpopulate(val, "Labels", &n.Labels) + err = unpopulate(val, "Labels", &n.Labels) delete(rawMsg, key) case "platform": - err = unpopulate(val, "Platform", &n.Platform) + err = unpopulate(val, "Platform", &n.Platform) delete(rawMsg, key) case "replicas": - err = unpopulate(val, "Replicas", &n.Replicas) + err = unpopulate(val, "Replicas", &n.Replicas) delete(rawMsg, key) case "taints": - err = unpopulate(val, "Taints", &n.Taints) + err = unpopulate(val, "Taints", &n.Taints) delete(rawMsg, key) case "tuningConfigs": - err = unpopulate(val, "TuningConfigs", &n.TuningConfigs) + err = unpopulate(val, "TuningConfigs", &n.TuningConfigs) delete(rawMsg, key) case "version": - err = unpopulate(val, "Version", &n.Version) + err = unpopulate(val, "Version", &n.Version) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", n, key) @@ -1494,19 +1493,19 @@ func (o *Operation) UnmarshalJSON(data []byte) error { var err error switch key { case "actionType": - err = unpopulate(val, "ActionType", &o.ActionType) + err = unpopulate(val, "ActionType", &o.ActionType) delete(rawMsg, key) case "display": - err = unpopulate(val, "Display", &o.Display) + err = unpopulate(val, "Display", &o.Display) delete(rawMsg, key) case "isDataAction": - err = unpopulate(val, "IsDataAction", &o.IsDataAction) + err = unpopulate(val, "IsDataAction", &o.IsDataAction) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &o.Name) + err = unpopulate(val, "Name", &o.Name) delete(rawMsg, key) case "origin": - err = unpopulate(val, "Origin", &o.Origin) + err = unpopulate(val, "Origin", &o.Origin) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", o, key) @@ -1538,16 +1537,16 @@ func (o *OperationDisplay) UnmarshalJSON(data []byte) error { var err error switch key { case "description": - err = unpopulate(val, "Description", &o.Description) + err = unpopulate(val, "Description", &o.Description) delete(rawMsg, key) case "operation": - err = unpopulate(val, "Operation", &o.Operation) + err = unpopulate(val, "Operation", &o.Operation) delete(rawMsg, key) case "provider": - err = unpopulate(val, "Provider", &o.Provider) + err = unpopulate(val, "Provider", &o.Provider) delete(rawMsg, key) case "resource": - err = unpopulate(val, "Resource", &o.Resource) + err = unpopulate(val, "Resource", &o.Resource) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", o, key) @@ -1577,10 +1576,39 @@ func (o *OperationListResult) UnmarshalJSON(data []byte) error { var err error switch key { case "nextLink": - err = unpopulate(val, "NextLink", &o.NextLink) + err = unpopulate(val, "NextLink", &o.NextLink) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &o.Value) + err = unpopulate(val, "Value", &o.Value) + delete(rawMsg, key) + default: + err = fmt.Errorf("unmarshalling type %T, unknown field %q", o, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type OperatorsAuthenticationProfile. +func (o OperatorsAuthenticationProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "userAssignedIdentities", o.UserAssignedIdentities) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type OperatorsAuthenticationProfile. +func (o *OperatorsAuthenticationProfile) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "userAssignedIdentities": + err = unpopulate(val, "UserAssignedIdentities", &o.UserAssignedIdentities) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", o, key) @@ -1598,6 +1626,7 @@ func (p PlatformProfile) MarshalJSON() ([]byte, error) { populate(objectMap, "etcdEncryptionSetId", p.EtcdEncryptionSetID) populate(objectMap, "managedResourceGroup", p.ManagedResourceGroup) populate(objectMap, "networkSecurityGroupId", p.NetworkSecurityGroupID) + populate(objectMap, "operatorsAuthentication", p.OperatorsAuthentication) populate(objectMap, "outboundType", p.OutboundType) populate(objectMap, "subnetId", p.SubnetID) return json.Marshal(objectMap) @@ -1613,19 +1642,22 @@ func (p *PlatformProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "etcdEncryptionSetId": - err = unpopulate(val, "EtcdEncryptionSetID", &p.EtcdEncryptionSetID) + err = unpopulate(val, "EtcdEncryptionSetID", &p.EtcdEncryptionSetID) delete(rawMsg, key) case "managedResourceGroup": - err = unpopulate(val, "ManagedResourceGroup", &p.ManagedResourceGroup) + err = unpopulate(val, "ManagedResourceGroup", &p.ManagedResourceGroup) delete(rawMsg, key) case "networkSecurityGroupId": - err = unpopulate(val, "NetworkSecurityGroupID", &p.NetworkSecurityGroupID) + err = unpopulate(val, "NetworkSecurityGroupID", &p.NetworkSecurityGroupID) + delete(rawMsg, key) + case "operatorsAuthentication": + err = unpopulate(val, "OperatorsAuthentication", &p.OperatorsAuthentication) delete(rawMsg, key) case "outboundType": - err = unpopulate(val, "OutboundType", &p.OutboundType) + err = unpopulate(val, "OutboundType", &p.OutboundType) delete(rawMsg, key) case "subnetId": - err = unpopulate(val, "SubnetID", &p.SubnetID) + err = unpopulate(val, "SubnetID", &p.SubnetID) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", p, key) @@ -1657,16 +1689,16 @@ func (p *ProxyProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "httpProxy": - err = unpopulate(val, "HTTPProxy", &p.HTTPProxy) + err = unpopulate(val, "HTTPProxy", &p.HTTPProxy) delete(rawMsg, key) case "httpsProxy": - err = unpopulate(val, "HTTPSProxy", &p.HTTPSProxy) + err = unpopulate(val, "HTTPSProxy", &p.HTTPSProxy) delete(rawMsg, key) case "noProxy": - err = unpopulate(val, "NoProxy", &p.NoProxy) + err = unpopulate(val, "NoProxy", &p.NoProxy) delete(rawMsg, key) case "trustedCa": - err = unpopulate(val, "TrustedCa", &p.TrustedCa) + err = unpopulate(val, "TrustedCa", &p.TrustedCa) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", p, key) @@ -1698,16 +1730,16 @@ func (p *ProxyResource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &p.ID) + err = unpopulate(val, "ID", &p.ID) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &p.Name) + err = unpopulate(val, "Name", &p.Name) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &p.SystemData) + err = unpopulate(val, "SystemData", &p.SystemData) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &p.Type) + err = unpopulate(val, "Type", &p.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", p, key) @@ -1739,16 +1771,16 @@ func (r *Resource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &r.ID) + err = unpopulate(val, "ID", &r.ID) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &r.Name) + err = unpopulate(val, "Name", &r.Name) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &r.SystemData) + err = unpopulate(val, "SystemData", &r.SystemData) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &r.Type) + err = unpopulate(val, "Type", &r.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", r, key) @@ -1782,22 +1814,22 @@ func (s *SystemData) UnmarshalJSON(data []byte) error { var err error switch key { case "createdAt": - err = unpopulateDateTimeRFC3339(val, "CreatedAt", &s.CreatedAt) + err = unpopulateDateTimeRFC3339(val, "CreatedAt", &s.CreatedAt) delete(rawMsg, key) case "createdBy": - err = unpopulate(val, "CreatedBy", &s.CreatedBy) + err = unpopulate(val, "CreatedBy", &s.CreatedBy) delete(rawMsg, key) case "createdByType": - err = unpopulate(val, "CreatedByType", &s.CreatedByType) + err = unpopulate(val, "CreatedByType", &s.CreatedByType) delete(rawMsg, key) case "lastModifiedAt": - err = unpopulateDateTimeRFC3339(val, "LastModifiedAt", &s.LastModifiedAt) + err = unpopulateDateTimeRFC3339(val, "LastModifiedAt", &s.LastModifiedAt) delete(rawMsg, key) case "lastModifiedBy": - err = unpopulate(val, "LastModifiedBy", &s.LastModifiedBy) + err = unpopulate(val, "LastModifiedBy", &s.LastModifiedBy) delete(rawMsg, key) case "lastModifiedByType": - err = unpopulate(val, "LastModifiedByType", &s.LastModifiedByType) + err = unpopulate(val, "LastModifiedByType", &s.LastModifiedByType) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", s, key) @@ -1828,13 +1860,13 @@ func (t *Taint) UnmarshalJSON(data []byte) error { var err error switch key { case "effect": - err = unpopulate(val, "Effect", &t.Effect) + err = unpopulate(val, "Effect", &t.Effect) delete(rawMsg, key) case "key": - err = unpopulate(val, "Key", &t.Key) + err = unpopulate(val, "Key", &t.Key) delete(rawMsg, key) case "value": - err = unpopulate(val, "Value", &t.Value) + err = unpopulate(val, "Value", &t.Value) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", t, key) @@ -1864,10 +1896,10 @@ func (t *TokenClaimMappingsProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "groups": - err = unpopulate(val, "Groups", &t.Groups) + err = unpopulate(val, "Groups", &t.Groups) delete(rawMsg, key) case "username": - err = unpopulate(val, "Username", &t.Username) + err = unpopulate(val, "Username", &t.Username) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", t, key) @@ -1897,10 +1929,10 @@ func (t *TokenClaimValidationRuleProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "claim": - err = unpopulate(val, "Claim", &t.Claim) + err = unpopulate(val, "Claim", &t.Claim) delete(rawMsg, key) case "requiredValue": - err = unpopulate(val, "RequiredValue", &t.RequiredValue) + err = unpopulate(val, "RequiredValue", &t.RequiredValue) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", t, key) @@ -1931,13 +1963,13 @@ func (t *TokenIssuerProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "audiences": - err = unpopulate(val, "Audiences", &t.Audiences) + err = unpopulate(val, "Audiences", &t.Audiences) delete(rawMsg, key) case "ca": - err = unpopulate(val, "Ca", &t.Ca) + err = unpopulate(val, "Ca", &t.Ca) delete(rawMsg, key) case "url": - err = unpopulate(val, "URL", &t.URL) + err = unpopulate(val, "URL", &t.URL) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", t, key) @@ -1971,22 +2003,22 @@ func (t *TrackedResource) UnmarshalJSON(data []byte) error { var err error switch key { case "id": - err = unpopulate(val, "ID", &t.ID) + err = unpopulate(val, "ID", &t.ID) delete(rawMsg, key) case "location": - err = unpopulate(val, "Location", &t.Location) + err = unpopulate(val, "Location", &t.Location) delete(rawMsg, key) case "name": - err = unpopulate(val, "Name", &t.Name) + err = unpopulate(val, "Name", &t.Name) delete(rawMsg, key) case "systemData": - err = unpopulate(val, "SystemData", &t.SystemData) + err = unpopulate(val, "SystemData", &t.SystemData) delete(rawMsg, key) case "tags": - err = unpopulate(val, "Tags", &t.Tags) + err = unpopulate(val, "Tags", &t.Tags) delete(rawMsg, key) case "type": - err = unpopulate(val, "Type", &t.Type) + err = unpopulate(val, "Type", &t.Type) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", t, key) @@ -1998,6 +2030,43 @@ func (t *TrackedResource) UnmarshalJSON(data []byte) error { return nil } +// MarshalJSON implements the json.Marshaller interface for type UserAssignedIdentitiesProfile. +func (u UserAssignedIdentitiesProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "controlPlaneOperators", u.ControlPlaneOperators) + populate(objectMap, "dataPlaneOperators", u.DataPlaneOperators) + populate(objectMap, "serviceManagedIdentity", u.ServiceManagedIdentity) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type UserAssignedIdentitiesProfile. +func (u *UserAssignedIdentitiesProfile) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", u, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "controlPlaneOperators": + err = unpopulate(val, "ControlPlaneOperators", &u.ControlPlaneOperators) + delete(rawMsg, key) + case "dataPlaneOperators": + err = unpopulate(val, "DataPlaneOperators", &u.DataPlaneOperators) + delete(rawMsg, key) + case "serviceManagedIdentity": + err = unpopulate(val, "ServiceManagedIdentity", &u.ServiceManagedIdentity) + delete(rawMsg, key) + default: + err = fmt.Errorf("unmarshalling type %T, unknown field %q", u, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", u, err) + } + } + return nil +} + // MarshalJSON implements the json.Marshaller interface for type UserAssignedIdentity. func (u UserAssignedIdentity) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) @@ -2016,10 +2085,10 @@ func (u *UserAssignedIdentity) UnmarshalJSON(data []byte) error { var err error switch key { case "clientId": - err = unpopulate(val, "ClientID", &u.ClientID) + err = unpopulate(val, "ClientID", &u.ClientID) delete(rawMsg, key) case "principalId": - err = unpopulate(val, "PrincipalID", &u.PrincipalID) + err = unpopulate(val, "PrincipalID", &u.PrincipalID) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", u, key) @@ -2050,13 +2119,13 @@ func (v *VersionProfile) UnmarshalJSON(data []byte) error { var err error switch key { case "availableUpgrades": - err = unpopulate(val, "AvailableUpgrades", &v.AvailableUpgrades) + err = unpopulate(val, "AvailableUpgrades", &v.AvailableUpgrades) delete(rawMsg, key) case "channelGroup": - err = unpopulate(val, "ChannelGroup", &v.ChannelGroup) + err = unpopulate(val, "ChannelGroup", &v.ChannelGroup) delete(rawMsg, key) case "id": - err = unpopulate(val, "ID", &v.ID) + err = unpopulate(val, "ID", &v.ID) delete(rawMsg, key) default: err = fmt.Errorf("unmarshalling type %T, unknown field %q", v, key) @@ -2097,3 +2166,4 @@ func unpopulate(data json.RawMessage, fn string, v any) error { } return nil } + diff --git a/internal/api/v20240610preview/generated/nodepools_client.go b/internal/api/v20240610preview/generated/nodepools_client.go index c34a34572..fe348ccfc 100644 --- a/internal/api/v20240610preview/generated/nodepools_client.go +++ b/internal/api/v20240610preview/generated/nodepools_client.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -10,20 +10,19 @@ package generated import ( "context" "errors" - "net/http" - "net/url" - "strings" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" ) // NodePoolsClient contains the methods for the NodePools group. // Don't use this type directly, use NewNodePoolsClient() instead. type NodePoolsClient struct { - internal *arm.Client + internal *arm.Client subscriptionID string } @@ -38,7 +37,7 @@ func NewNodePoolsClient(subscriptionID string, credential azcore.TokenCredential } client := &NodePoolsClient{ subscriptionID: subscriptionID, - internal: cl, + internal: cl, } return client, nil } @@ -61,7 +60,7 @@ func (client *NodePoolsClient) BeginCreateOrUpdate(ctx context.Context, resource } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[NodePoolsClientCreateOrUpdateResponse]{ FinalStateVia: runtime.FinalStateViaAzureAsyncOp, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -124,8 +123,8 @@ func (client *NodePoolsClient) createOrUpdateCreateRequest(ctx context.Context, req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, resource); err != nil { - return nil, err - } + return nil, err +} return req, nil } @@ -145,7 +144,7 @@ func (client *NodePoolsClient) BeginDelete(ctx context.Context, resourceGroupNam } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[NodePoolsClientDeleteResponse]{ FinalStateVia: runtime.FinalStateViaLocation, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -286,13 +285,13 @@ func (client *NodePoolsClient) getHandleResponse(resp *http.Response) (NodePools // - hcpOpenShiftClusterName - Name of HCP cluster // - options - NodePoolsClientListByParentOptions contains the optional parameters for the NodePoolsClient.NewListByParentPager // method. -func (client *NodePoolsClient) NewListByParentPager(resourceGroupName string, hcpOpenShiftClusterName string, options *NodePoolsClientListByParentOptions) *runtime.Pager[NodePoolsClientListByParentResponse] { +func (client *NodePoolsClient) NewListByParentPager(resourceGroupName string, hcpOpenShiftClusterName string, options *NodePoolsClientListByParentOptions) (*runtime.Pager[NodePoolsClientListByParentResponse]) { return runtime.NewPager(runtime.PagingHandler[NodePoolsClientListByParentResponse]{ More: func(page NodePoolsClientListByParentResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *NodePoolsClientListByParentResponse) (NodePoolsClientListByParentResponse, error) { - ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "NodePoolsClient.NewListByParentPager") + ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "NodePoolsClient.NewListByParentPager") nextLink := "" if page != nil { nextLink = *page.NextLink @@ -304,7 +303,7 @@ func (client *NodePoolsClient) NewListByParentPager(resourceGroupName string, hc return NodePoolsClientListByParentResponse{}, err } return client.listByParentHandleResponse(resp) - }, + }, Tracer: client.internal.Tracer(), }) } @@ -361,7 +360,7 @@ func (client *NodePoolsClient) BeginUpdate(ctx context.Context, resourceGroupNam } poller, err := runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[NodePoolsClientUpdateResponse]{ FinalStateVia: runtime.FinalStateViaLocation, - Tracer: client.internal.Tracer(), + Tracer: client.internal.Tracer(), }) return poller, err } else { @@ -424,7 +423,8 @@ func (client *NodePoolsClient) updateCreateRequest(ctx context.Context, resource req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, properties); err != nil { - return nil, err - } + return nil, err +} return req, nil } + diff --git a/internal/api/v20240610preview/generated/operations_client.go b/internal/api/v20240610preview/generated/operations_client.go index 46e57d814..85b8e798c 100644 --- a/internal/api/v20240610preview/generated/operations_client.go +++ b/internal/api/v20240610preview/generated/operations_client.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -9,12 +9,11 @@ package generated import ( "context" - "net/http" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" ) // OperationsClient contains the methods for the Operations group. @@ -32,7 +31,7 @@ func NewOperationsClient(credential azcore.TokenCredential, options *arm.ClientO return nil, err } client := &OperationsClient{ - internal: cl, + internal: cl, } return client, nil } @@ -41,13 +40,13 @@ func NewOperationsClient(credential azcore.TokenCredential, options *arm.ClientO // // Generated from API version 2024-06-10-preview // - options - OperationsClientListOptions contains the optional parameters for the OperationsClient.NewListPager method. -func (client *OperationsClient) NewListPager(options *OperationsClientListOptions) *runtime.Pager[OperationsClientListResponse] { +func (client *OperationsClient) NewListPager(options *OperationsClientListOptions) (*runtime.Pager[OperationsClientListResponse]) { return runtime.NewPager(runtime.PagingHandler[OperationsClientListResponse]{ More: func(page OperationsClientListResponse) bool { return page.NextLink != nil && len(*page.NextLink) > 0 }, Fetcher: func(ctx context.Context, page *OperationsClientListResponse) (OperationsClientListResponse, error) { - ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "OperationsClient.NewListPager") + ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "OperationsClient.NewListPager") nextLink := "" if page != nil { nextLink = *page.NextLink @@ -59,7 +58,7 @@ func (client *OperationsClient) NewListPager(options *OperationsClientListOption return OperationsClientListResponse{}, err } return client.listHandleResponse(resp) - }, + }, Tracer: client.internal.Tracer(), }) } @@ -86,3 +85,4 @@ func (client *OperationsClient) listHandleResponse(resp *http.Response) (Operati } return result, nil } + diff --git a/internal/api/v20240610preview/generated/options.go b/internal/api/v20240610preview/generated/options.go index b946d66c4..c278a1bf4 100644 --- a/internal/api/v20240610preview/generated/options.go +++ b/internal/api/v20240610preview/generated/options.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -95,3 +95,4 @@ type NodePoolsClientListByParentOptions struct { type OperationsClientListOptions struct { // placeholder for future optional parameters } + diff --git a/internal/api/v20240610preview/generated/responses.go b/internal/api/v20240610preview/generated/responses.go index 73d751f0f..f423354d9 100644 --- a/internal/api/v20240610preview/generated/responses.go +++ b/internal/api/v20240610preview/generated/responses.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. @@ -94,3 +94,4 @@ type OperationsClientListResponse struct { // A list of REST API operations supported by an Azure Resource Provider. It contains an URL link to get the next set of results. OperationListResult } + diff --git a/internal/api/v20240610preview/generated/time_rfc3339.go b/internal/api/v20240610preview/generated/time_rfc3339.go index 2008988d2..a4bf0e975 100644 --- a/internal/api/v20240610preview/generated/time_rfc3339.go +++ b/internal/api/v20240610preview/generated/time_rfc3339.go @@ -1,23 +1,26 @@ //go:build go1.18 // +build go1.18 -// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/go@4.0.0-preview.63) +// Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.3, generator: @autorest/go@4.0.0-preview.63) // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Code generated by @autorest/go. DO NOT EDIT. package generated + + import ( "encoding/json" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "reflect" "regexp" "strings" "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" ) + + // Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. var tzOffsetRegex = regexp.MustCompile(`(?:Z|z|\+|-)(?:\d+:\d+)*"*$`) @@ -59,7 +62,7 @@ func (t *dateTimeRFC3339) UnmarshalJSON(data []byte) error { return t.Parse(layout, string(data)) } -func (t *dateTimeRFC3339) UnmarshalText(data []byte) error { +func (t *dateTimeRFC3339) UnmarshalText(data []byte) (error) { tzOffset := tzOffsetRegex.Match(data) hasT := strings.Contains(string(data), "T") || strings.Contains(string(data), "t") var layout string @@ -85,6 +88,7 @@ func (t dateTimeRFC3339) String() string { return time.Time(t).Format(time.RFC3339Nano) } + func populateDateTimeRFC3339(m map[string]any, k string, t *time.Time) { if t == nil { return diff --git a/internal/api/v20240610preview/hcpopenshiftclusters_methods.go b/internal/api/v20240610preview/hcpopenshiftclusters_methods.go index ac4e3defe..c8f2a26c1 100644 --- a/internal/api/v20240610preview/hcpopenshiftclusters_methods.go +++ b/internal/api/v20240610preview/hcpopenshiftclusters_methods.go @@ -4,7 +4,9 @@ package v20240610preview // Licensed under the Apache License 2.0. import ( + "fmt" "net/http" + "slices" configv1 "github.com/openshift/api/config/v1" @@ -17,38 +19,6 @@ type HcpOpenShiftClusterResource struct { generated.HcpOpenShiftClusterResource } -type VersionProfile struct { - generated.VersionProfile -} - -type DNSProfile struct { - generated.DNSProfile -} - -type NetworkProfile struct { - generated.NetworkProfile -} - -type ConsoleProfile struct { - generated.ConsoleProfile -} - -type APIProfile struct { - generated.APIProfile -} - -type ProxyProfile struct { - generated.ProxyProfile -} - -type PlatformProfile struct { - generated.PlatformProfile -} - -type ExternalAuthConfigProfile struct { - generated.ExternalAuthConfigProfile -} - func newVersionProfile(from *api.VersionProfile) *generated.VersionProfile { return &generated.VersionProfile{ ID: api.Ptr(from.ID), @@ -98,11 +68,26 @@ func newProxyProfile(from *api.ProxyProfile) *generated.ProxyProfile { func newPlatformProfile(from *api.PlatformProfile) *generated.PlatformProfile { return &generated.PlatformProfile{ - ManagedResourceGroup: api.Ptr(from.ManagedResourceGroup), - SubnetID: api.Ptr(from.SubnetID), - OutboundType: api.Ptr(generated.OutboundType(from.OutboundType)), - NetworkSecurityGroupID: api.Ptr(from.NetworkSecurityGroupID), - EtcdEncryptionSetID: api.Ptr(from.EtcdEncryptionSetID), + ManagedResourceGroup: api.Ptr(from.ManagedResourceGroup), + SubnetID: api.Ptr(from.SubnetID), + OutboundType: api.Ptr(generated.OutboundType(from.OutboundType)), + NetworkSecurityGroupID: api.Ptr(from.NetworkSecurityGroupID), + EtcdEncryptionSetID: api.Ptr(from.EtcdEncryptionSetID), + OperatorsAuthentication: newOperatorsAuthenticationProfile(&from.OperatorsAuthentication), + } +} + +func newOperatorsAuthenticationProfile(from *api.OperatorsAuthenticationProfile) *generated.OperatorsAuthenticationProfile { + return &generated.OperatorsAuthenticationProfile{ + UserAssignedIdentities: newUserAssignedIdentitiesProfile(&from.UserAssignedIdentities), + } +} + +func newUserAssignedIdentitiesProfile(from *api.UserAssignedIdentitiesProfile) *generated.UserAssignedIdentitiesProfile { + return &generated.UserAssignedIdentitiesProfile{ + ControlPlaneOperators: api.StringMapToStringPtrMap(from.ControlPlaneOperators), + DataPlaneOperators: api.StringMapToStringPtrMap(from.DataPlaneOperators), + ServiceManagedIdentity: api.Ptr(from.ServiceManagedIdentity), } } @@ -184,7 +169,13 @@ func (v version) NewHCPOpenShiftCluster(from *api.HCPOpenShiftCluster) api.Versi Type: api.Ptr(from.Resource.Type), Location: api.Ptr(from.TrackedResource.Location), Tags: api.StringMapToStringPtrMap(from.TrackedResource.Tags), - // FIXME Skipping ManagedServiceIdentity + Identity: &generated.ManagedServiceIdentity{ + Type: api.Ptr(generated.ManagedServiceIdentityType(from.Identity.Type)), + PrincipalID: api.Ptr(from.Identity.PrincipalID), + TenantID: api.Ptr(from.Identity.TenantID), + //as UserAssignedIdentities is of a different type so using convertUserAssignedIdentities instead of StringMapToStringPtrMap + UserAssignedIdentities: convertUserAssignedIdentities(from.Identity.UserAssignedIdentities), + }, Properties: &generated.HcpOpenShiftClusterProperties{ ProvisioningState: api.Ptr(generated.ProvisioningState(from.Properties.ProvisioningState)), Spec: &generated.ClusterSpec{ @@ -254,10 +245,29 @@ func (c *HcpOpenShiftClusterResource) Normalize(out *api.HCPOpenShiftCluster) { out.Resource.SystemData.LastModifiedByType = arm.CreatedByType(*c.SystemData.LastModifiedByType) } } - // FIXME Skipping ManagedServiceIdentity if c.Location != nil { out.TrackedResource.Location = *c.Location } + if c.Identity != nil { + if c.Identity.PrincipalID != nil { + out.Identity.PrincipalID = *c.Identity.PrincipalID + } + if c.Identity.TenantID != nil { + out.Identity.TenantID = *c.Identity.TenantID + } + if c.Identity.Type != nil { + out.Identity.Type = (arm.ManagedServiceIdentityType)(*c.Identity.Type) + } + if c.Identity.UserAssignedIdentities != nil { + normalizeIdentityUserAssignedIdentities(c.Identity.UserAssignedIdentities, &out.Identity.UserAssignedIdentities) + } + } + // Per RPC-Patch-V1-04, the Tags field does NOT follow + // JSON merge-patch (RFC 7396) semantics: + // + // When Tags are patched, the tags from the request + // replace all existing tags for the resource + // out.Tags = api.StringPtrMapToStringMap(c.Tags) if c.Properties != nil { if c.Properties.ProvisioningState != nil { @@ -304,6 +314,54 @@ func (c *HcpOpenShiftClusterResource) Normalize(out *api.HCPOpenShiftCluster) { } } +// validateStaticComplex performs more complex, multi-field validations than +// are possible with struct tag validation. The returned CloudErrorBody slice +// contains structured but user-friendly details for all discovered errors. +func validateStaticComplex(normalized *api.HCPOpenShiftCluster) []arm.CloudErrorBody { + var errorDetails []arm.CloudErrorBody + //Generate a slice of Resource IDs of ControlplaneOperators MI only , disregard the DataPlaneOperators. + var cpmiResourceIDs []string + if normalized.Identity.UserAssignedIdentities != nil { + for _, operatorResourceID := range normalized.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ControlPlaneOperators { + cpmiResourceIDs = append(cpmiResourceIDs, operatorResourceID) + } + smiResourceID := normalized.Properties.Spec.Platform.OperatorsAuthentication.UserAssignedIdentities.ServiceManagedIdentity + miCount := len(normalized.Identity.UserAssignedIdentities) + for resourceID, _ := range normalized.Identity.UserAssignedIdentities { + + if slices.Contains(cpmiResourceIDs, resourceID) || resourceID == smiResourceID { + //Duplicated Identity Validation + if slices.Contains(cpmiResourceIDs, resourceID) && resourceID == smiResourceID { + errorDetails = append(errorDetails, arm.CloudErrorBody{ + Message: fmt.Sprintf( + "%s can not be used in both controlPlaneOperators and serviceManagedIdentity", + resourceID), + Target: "properties.spec.platform.operatorsAuthentication.userAssignedIdentities", + }) + } + } else { + errorDetails = append(errorDetails, arm.CloudErrorBody{ + Message: fmt.Sprintf( + "%s must be used in either controlPlaneOperators or serviceManagedIdentity", + resourceID), + Target: "properties.spec.platform.operatorsAuthentication.userAssignedIdentities"}) + } + } + // Ensure that if User-assigned managed identity count is always equal to count of ControlPlaneOperator MIs and Service Managed Identity.count. + var smiCount int + if smiResourceID != "" { + smiCount = 1 + } + if miCount < (len(cpmiResourceIDs) + smiCount) { + errorDetails = append(errorDetails, arm.CloudErrorBody{ + Message: "must be same as count of OperatorsAuthentication Managed Identities", + Target: "identity.userAssignedIdentities", + }) + } + } + return errorDetails +} + func (c *HcpOpenShiftClusterResource) ValidateStatic(current api.VersionedHCPOpenShiftCluster, updating bool, method string) *arm.CloudError { var normalized api.HCPOpenShiftCluster var errorDetails []arm.CloudErrorBody @@ -331,6 +389,17 @@ func (c *HcpOpenShiftClusterResource) ValidateStatic(current api.VersionedHCPOpe cloudError.Details = append(cloudError.Details, errorDetails...) } + // Proceed with complex, multi-field validation only if single-field + // validation has passed. This avoids running further checks on data + // we already know to be invalid and prevents the response body from + // becoming overwhelming. + if len(cloudError.Details) == 0 { + errorDetails = validateStaticComplex(&normalized) + if errorDetails != nil { + cloudError.Details = append(cloudError.Details, errorDetails...) + } + } + switch len(cloudError.Details) { case 0: cloudError = nil @@ -342,10 +411,6 @@ func (c *HcpOpenShiftClusterResource) ValidateStatic(current api.VersionedHCPOpe return cloudError } -func (p *VersionProfile) Normalize(out *api.VersionProfile) { - normalizeVersion(&p.VersionProfile, out) -} - func normalizeVersion(p *generated.VersionProfile, out *api.VersionProfile) { if p.ID != nil { out.ID = *p.ID @@ -356,10 +421,6 @@ func normalizeVersion(p *generated.VersionProfile, out *api.VersionProfile) { out.AvailableUpgrades = api.StringPtrSliceToStringSlice(p.AvailableUpgrades) } -func (p *DNSProfile) Normalize(out *api.DNSProfile) { - normailzeDNS(&p.DNSProfile, out) -} - func normailzeDNS(p *generated.DNSProfile, out *api.DNSProfile) { if p.BaseDomain != nil { out.BaseDomain = *p.BaseDomain @@ -369,10 +430,6 @@ func normailzeDNS(p *generated.DNSProfile, out *api.DNSProfile) { } } -func (p *NetworkProfile) Normalize(out *api.NetworkProfile) { - normalizeNetwork(&p.NetworkProfile, out) -} - func normalizeNetwork(p *generated.NetworkProfile, out *api.NetworkProfile) { if p.NetworkType != nil { out.NetworkType = api.NetworkType(*p.NetworkType) @@ -391,20 +448,12 @@ func normalizeNetwork(p *generated.NetworkProfile, out *api.NetworkProfile) { } } -func (p *ConsoleProfile) Normalize(out *api.ConsoleProfile) { - normalizeConsole(&p.ConsoleProfile, out) -} - func normalizeConsole(p *generated.ConsoleProfile, out *api.ConsoleProfile) { if p.URL != nil { out.URL = *p.URL } } -func (p *APIProfile) Normalize(out *api.APIProfile) { - normalizeAPI(&p.APIProfile, out) -} - func normalizeAPI(p *generated.APIProfile, out *api.APIProfile) { if p.URL != nil { out.URL = *p.URL @@ -414,10 +463,6 @@ func normalizeAPI(p *generated.APIProfile, out *api.APIProfile) { } } -func (p *ProxyProfile) Normalize(out *api.ProxyProfile) { - normalizeProxy(&p.ProxyProfile, out) -} - func normalizeProxy(p *generated.ProxyProfile, out *api.ProxyProfile) { if p.HTTPProxy != nil { out.HTTPProxy = *p.HTTPProxy @@ -433,10 +478,6 @@ func normalizeProxy(p *generated.ProxyProfile, out *api.ProxyProfile) { } } -func (p *PlatformProfile) Normalize(out *api.PlatformProfile) { - normalizePlatform(&p.PlatformProfile, out) -} - func normalizePlatform(p *generated.PlatformProfile, out *api.PlatformProfile) { if p.ManagedResourceGroup != nil { out.ManagedResourceGroup = *p.ManagedResourceGroup @@ -453,10 +494,23 @@ func normalizePlatform(p *generated.PlatformProfile, out *api.PlatformProfile) { if p.EtcdEncryptionSetID != nil { out.EtcdEncryptionSetID = *p.EtcdEncryptionSetID } + if p.OperatorsAuthentication != nil { + normalizeOperatorsAuthentication(p.OperatorsAuthentication, &out.OperatorsAuthentication) + } } -func (p *ExternalAuthConfigProfile) Normalize(out *api.ExternalAuthConfigProfile) { - normalizeExternalAuthConfig(&p.ExternalAuthConfigProfile, out) +func normalizeOperatorsAuthentication(p *generated.OperatorsAuthenticationProfile, out *api.OperatorsAuthenticationProfile) { + if p.UserAssignedIdentities != nil { + normalizeUserAssignedIdentities(p.UserAssignedIdentities, &out.UserAssignedIdentities) + } +} + +func normalizeUserAssignedIdentities(p *generated.UserAssignedIdentitiesProfile, out *api.UserAssignedIdentitiesProfile) { + api.MergeStringPtrMap(p.ControlPlaneOperators, &out.ControlPlaneOperators) + api.MergeStringPtrMap(p.DataPlaneOperators, &out.DataPlaneOperators) + if p.ServiceManagedIdentity != nil { + out.ServiceManagedIdentity = *p.ServiceManagedIdentity + } } func normalizeExternalAuthConfig(p *generated.ExternalAuthConfigProfile, out *api.ExternalAuthConfigProfile) { @@ -550,3 +604,29 @@ func normalizeExternalAuthConfig(p *generated.ExternalAuthConfigProfile, out *ap out.ExternalAuths = append(out.ExternalAuths, provider) } } + +func normalizeIdentityUserAssignedIdentities(p map[string]*generated.UserAssignedIdentity, out *map[string]*arm.UserAssignedIdentity) { + if *out == nil { + *out = make(map[string]*arm.UserAssignedIdentity) + } + for key, value := range p { + if value != nil { + (*out)[key] = &arm.UserAssignedIdentity{ + ClientID: value.ClientID, + PrincipalID: value.PrincipalID, + } + } + } +} +func convertUserAssignedIdentities(from map[string]*arm.UserAssignedIdentity) map[string]*generated.UserAssignedIdentity { + converted := make(map[string]*generated.UserAssignedIdentity) + for key, value := range from { + if value != nil { + converted[key] = &generated.UserAssignedIdentity{ + ClientID: value.ClientID, + PrincipalID: value.PrincipalID, + } + } + } + return converted +} diff --git a/internal/api/v20240610preview/nodepools_methods.go b/internal/api/v20240610preview/nodepools_methods.go index 6a7beabcd..19f0d786d 100644 --- a/internal/api/v20240610preview/nodepools_methods.go +++ b/internal/api/v20240610preview/nodepools_methods.go @@ -43,6 +43,12 @@ func (h *HcpOpenShiftClusterNodePoolResource) Normalize(out *api.HCPOpenShiftClu if h.Location != nil { out.TrackedResource.Location = *h.Location } + // Per RPC-Patch-V1-04, the Tags field does NOT follow + // JSON merge-patch (RFC 7396) semantics: + // + // When Tags are patched, the tags from the request + // replace all existing tags for the resource + // out.Tags = api.StringPtrMapToStringMap(h.Tags) if h.Properties != nil { if h.Properties.ProvisioningState != nil { diff --git a/internal/api/validate.go b/internal/api/validate.go index ef20650a7..8099aff03 100644 --- a/internal/api/validate.go +++ b/internal/api/validate.go @@ -11,6 +11,7 @@ import ( "strings" "unicode" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" validator "github.com/go-playground/validator/v10" "github.com/Azure/ARO-HCP/internal/api/arm" @@ -35,6 +36,10 @@ func EnumValidateTag[S ~string](values ...S) string { s := make([]string, len(values)) for i, e := range values { s[i] = string(e) + // Replace special characters with the UTF-8 hex representation. + // https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Using_Validator_Tags + s[i] = strings.ReplaceAll(s[i], ",", "0x2C") + s[i] = strings.ReplaceAll(s[i], "|", "0x7C") } return fmt.Sprintf("oneof=%s", strings.Join(s, " ")) } @@ -51,6 +56,11 @@ func NewValidator() *validator.Validate { }) // Register ARM-mandated enumeration types. + validate.RegisterAlias("enum_managedserviceidentitytype", EnumValidateTag( + arm.ManagedServiceIdentityTypeNone, + arm.ManagedServiceIdentityTypeSystemAssigned, + arm.ManagedServiceIdentityTypeSystemAssignedUserAssigned, + arm.ManagedServiceIdentityTypeUserAssigned)) validate.RegisterAlias("enum_subscriptionstate", EnumValidateTag( arm.SubscriptionStateRegistered, arm.SubscriptionStateUnregistered, @@ -113,6 +123,25 @@ func NewValidator() *validator.Validate { panic(err) } + // Use this for string fields specifying an Azure resource ID. + // The optional argument further enforces a specific resource type. + err = validate.RegisterValidation("resource_id", func(fl validator.FieldLevel) bool { + field := fl.Field() + param := fl.Param() + if field.Kind() != reflect.String { + panic("String type required for resource_id") + } + resourceID, err := azcorearm.ParseResourceID(field.String()) + if err != nil { + return false + } + resourceType := resourceID.ResourceType.String() + return param == "" || strings.EqualFold(resourceType, param) + }) + if err != nil { + panic(err) + } + return validate } @@ -152,6 +181,12 @@ func ValidateRequest(validate *validator.Validate, method string, resource any) message += " (must provide PEM encoded certificates)" case "required", "required_for_put": // custom tag message = fmt.Sprintf("Missing required field '%s'", fieldErr.Field()) + case "resource_id": // custom tag + if fieldErr.Param() != "" { + message += fmt.Sprintf(" (must be a valid '%s' resource ID)", fieldErr.Param()) + } else { + message += " (must be a valid Azure resource ID)" + } case "cidrv4": message += " (must be a v4 CIDR range)" case "dns_rfc1035_label": diff --git a/internal/api/visibility.go b/internal/api/visibility.go index 0e381d59d..34999a6b1 100644 --- a/internal/api/visibility.go +++ b/internal/api/visibility.go @@ -99,7 +99,7 @@ type StructTagMap map[string]reflect.StructTag func buildStructTagMap(structTagMap StructTagMap, t reflect.Type, path string) { switch t.Kind() { - case reflect.Pointer, reflect.Slice: + case reflect.Map, reflect.Pointer, reflect.Slice: buildStructTagMap(structTagMap, t.Elem(), path) case reflect.Struct: @@ -242,23 +242,51 @@ func (vv *validateVisibility) recurse(newVal, curVal reflect.Value, mapKey, name } case reflect.Map: + // Determine if newVal and curVal share identical keys. + var keysEqual = true + // We already know that newVal is not nil. if curVal.IsNil() || newVal.Len() != curVal.Len() { - vv.checkFlags(flags, namespace, fieldname) + keysEqual = false } else { iter := newVal.MapRange() for iter.Next() { - k := iter.Key() - - subscript := fmt.Sprintf("[%q]", k.Interface()) - if curVal.MapIndex(k).IsValid() { - vv.recurse(newVal.MapIndex(k), curVal.MapIndex(k), mapKey, namespace, fieldname+subscript, flags) - } else { - vv.checkFlags(flags, namespace, fieldname+subscript) + if !curVal.MapIndex(iter.Key()).IsValid() { + keysEqual = false + break } } } + // Skip recursion if visibility check on the map itself fails. + if !keysEqual && !vv.checkFlags(flags, namespace, fieldname) { + return + } + + // Initialize a zero value for when curVal is missing a key in newVal. + // If the map value type is a pointer, create a zero value for the type + // being pointed to. + var zeroVal reflect.Value + mapValueType := newVal.Type().Elem() + if mapValueType.Kind() == reflect.Ptr { + // This returns a pointer to the new value. + zeroVal = reflect.New(mapValueType.Elem()) + } else { + // Follow the pointer to the new value. + zeroVal = reflect.New(mapValueType).Elem() + } + + iter := newVal.MapRange() + for iter.Next() { + k := iter.Key() + subscript := fmt.Sprintf("[%q]", k.Interface()) + if curVal.IsNil() || !curVal.MapIndex(k).IsValid() { + vv.recurse(newVal.MapIndex(k), zeroVal, mapKey, namespace, fieldname+subscript, flags) + } else { + vv.recurse(newVal.MapIndex(k), curVal.MapIndex(k), mapKey, namespace, fieldname+subscript, flags) + } + } + case reflect.Struct: for i := 0; i < newVal.NumField(); i++ { structField := newVal.Type().Field(i) @@ -273,7 +301,7 @@ func (vv *validateVisibility) recurse(newVal, curVal reflect.Value, mapKey, name } } -func (vv *validateVisibility) checkFlags(flags VisibilityFlags, namespace, fieldname string) { +func (vv *validateVisibility) checkFlags(flags VisibilityFlags, namespace, fieldname string) bool { if flags.ReadOnly() { vv.errs = append(vv.errs, arm.CloudErrorBody{ @@ -281,6 +309,7 @@ func (vv *validateVisibility) checkFlags(flags VisibilityFlags, namespace, field Message: fmt.Sprintf("Field '%s' is read-only", fieldname), Target: join(namespace, fieldname), }) + return false } else if vv.updating && !flags.CanUpdate() { vv.errs = append(vv.errs, arm.CloudErrorBody{ @@ -288,5 +317,7 @@ func (vv *validateVisibility) checkFlags(flags VisibilityFlags, namespace, field Message: fmt.Sprintf("Field '%s' cannot be updated", fieldname), Target: join(namespace, fieldname), }) + return false } + return true } diff --git a/internal/api/visibility_test.go b/internal/api/visibility_test.go index 645f354b5..7231ce998 100644 --- a/internal/api/visibility_test.go +++ b/internal/api/visibility_test.go @@ -101,8 +101,11 @@ type TestModelType struct { // Slice of struct type inherits visibility but can override. D []*TestModelSubtype `visibility:"update nocase"` + // Map of struct type inherits visibility but can override. + E map[string]*TestModelSubtype `visibility:"read create update nocase"` + // For equality checks of various reflect types. - E any `visibility:"read"` + F any `visibility:"read"` } type TestModelSubtype struct { @@ -135,7 +138,12 @@ func TestStructTagMap(t *testing.T) { "D.ReadNoCase": reflect.StructTag("visibility:\"read nocase\""), "D.ReadCreate": reflect.StructTag("visibility:\"read create\""), "D.ReadCreateUpdate": reflect.StructTag("visibility:\"read create update\""), - "E": reflect.StructTag("visibility:\"read\""), + "E": reflect.StructTag("visibility:\"read create update nocase\""), + "E.Read": reflect.StructTag("visibility:\"read\""), + "E.ReadNoCase": reflect.StructTag("visibility:\"read nocase\""), + "E.ReadCreate": reflect.StructTag("visibility:\"read create\""), + "E.ReadCreateUpdate": reflect.StructTag("visibility:\"read create update\""), + "F": reflect.StructTag("visibility:\"read\""), } // The test cases are encoded into the type itself. @@ -434,13 +442,69 @@ func TestValidateVisibility(t *testing.T) { updating: false, errorsExpected: 1, }, + { + name: "Add map key with read-only value to nil map is accepted for zero value", + v: TestModelType{ + E: map[string]*TestModelSubtype{ + "1up": &TestModelSubtype{}, + }, + }, + w: TestModelType{}, + m: TestModelTypeStructTagMap, + updating: false, + errorsExpected: 0, + }, + { + name: "Add map key with read-only value to nil map is rejected for non-zero value", + v: TestModelType{ + E: map[string]*TestModelSubtype{ + "1up": &testValues, + }, + }, + w: TestModelType{}, + m: TestModelTypeStructTagMap, + updating: false, + errorsExpected: 2, // testValues has two read-only fields + }, + { + name: "Add map key with read-only value to existing map is accepted for zero value", + v: TestModelType{ + E: map[string]*TestModelSubtype{ + "1up": &TestModelSubtype{}, + }, + }, + w: TestModelType{ + E: map[string]*TestModelSubtype{ + "2up": &testValues, + }, + }, + m: TestModelTypeStructTagMap, + updating: false, + errorsExpected: 0, + }, + { + name: "Add map key with read-only value to existing map is rejected for non-zero value", + v: TestModelType{ + E: map[string]*TestModelSubtype{ + "1up": &testValues, + }, + }, + w: TestModelType{ + E: map[string]*TestModelSubtype{ + "2up": &testValues, + }, + }, + m: TestModelTypeStructTagMap, + updating: false, + errorsExpected: 2, // testValues has two read-only fields + }, { name: "Test equality for bool type fields", v: TestModelType{ - E: Ptr(bool(true)), + F: Ptr(bool(true)), }, w: TestModelType{ - E: Ptr(bool(true)), + F: Ptr(bool(true)), }, m: TestModelTypeStructTagMap, updating: false, @@ -449,10 +513,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for bool type fields", v: TestModelType{ - E: Ptr(bool(true)), + F: Ptr(bool(true)), }, w: TestModelType{ - E: Ptr(bool(false)), + F: Ptr(bool(false)), }, m: TestModelTypeStructTagMap, updating: false, @@ -461,10 +525,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for int type fields", v: TestModelType{ - E: Ptr(int(1)), + F: Ptr(int(1)), }, w: TestModelType{ - E: Ptr(int(1)), + F: Ptr(int(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -473,10 +537,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for int type fields", v: TestModelType{ - E: Ptr(int(1)), + F: Ptr(int(1)), }, w: TestModelType{ - E: Ptr(int(0)), + F: Ptr(int(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -485,10 +549,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for int8 type fields", v: TestModelType{ - E: Ptr(int8(1)), + F: Ptr(int8(1)), }, w: TestModelType{ - E: Ptr(int8(1)), + F: Ptr(int8(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -497,10 +561,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for int8 type fields", v: TestModelType{ - E: Ptr(int8(1)), + F: Ptr(int8(1)), }, w: TestModelType{ - E: Ptr(int8(0)), + F: Ptr(int8(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -509,10 +573,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for int16 type fields", v: TestModelType{ - E: Ptr(int16(1)), + F: Ptr(int16(1)), }, w: TestModelType{ - E: Ptr(int16(1)), + F: Ptr(int16(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -521,10 +585,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for int16 type fields", v: TestModelType{ - E: Ptr(int16(1)), + F: Ptr(int16(1)), }, w: TestModelType{ - E: Ptr(int16(0)), + F: Ptr(int16(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -533,10 +597,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for int32 type fields", v: TestModelType{ - E: Ptr(int32(1)), + F: Ptr(int32(1)), }, w: TestModelType{ - E: Ptr(int32(1)), + F: Ptr(int32(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -545,10 +609,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for int32 type fields", v: TestModelType{ - E: Ptr(int32(1)), + F: Ptr(int32(1)), }, w: TestModelType{ - E: Ptr(int32(0)), + F: Ptr(int32(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -557,10 +621,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for int64 type fields", v: TestModelType{ - E: Ptr(int64(1)), + F: Ptr(int64(1)), }, w: TestModelType{ - E: Ptr(int64(1)), + F: Ptr(int64(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -569,10 +633,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for int64 type fields", v: TestModelType{ - E: Ptr(int64(1)), + F: Ptr(int64(1)), }, w: TestModelType{ - E: Ptr(int64(0)), + F: Ptr(int64(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -581,10 +645,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uint type fields", v: TestModelType{ - E: Ptr(uint(1)), + F: Ptr(uint(1)), }, w: TestModelType{ - E: Ptr(uint(1)), + F: Ptr(uint(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -593,10 +657,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uint type fields", v: TestModelType{ - E: Ptr(uint(1)), + F: Ptr(uint(1)), }, w: TestModelType{ - E: Ptr(uint(0)), + F: Ptr(uint(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -605,10 +669,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uintptr type fields", v: TestModelType{ - E: Ptr(uintptr(1)), + F: Ptr(uintptr(1)), }, w: TestModelType{ - E: Ptr(uintptr(1)), + F: Ptr(uintptr(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -617,10 +681,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uintptr type fields", v: TestModelType{ - E: Ptr(uintptr(1)), + F: Ptr(uintptr(1)), }, w: TestModelType{ - E: Ptr(uintptr(0)), + F: Ptr(uintptr(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -629,10 +693,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uint8 type fields", v: TestModelType{ - E: Ptr(uint8(1)), + F: Ptr(uint8(1)), }, w: TestModelType{ - E: Ptr(uint8(1)), + F: Ptr(uint8(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -641,10 +705,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uint8 type fields", v: TestModelType{ - E: Ptr(uint8(1)), + F: Ptr(uint8(1)), }, w: TestModelType{ - E: Ptr(uint8(0)), + F: Ptr(uint8(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -653,10 +717,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uint16 type fields", v: TestModelType{ - E: Ptr(uint16(1)), + F: Ptr(uint16(1)), }, w: TestModelType{ - E: Ptr(uint16(1)), + F: Ptr(uint16(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -665,10 +729,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uint16 type fields", v: TestModelType{ - E: Ptr(uint16(1)), + F: Ptr(uint16(1)), }, w: TestModelType{ - E: Ptr(uint16(0)), + F: Ptr(uint16(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -677,10 +741,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uint32 type fields", v: TestModelType{ - E: Ptr(uint32(1)), + F: Ptr(uint32(1)), }, w: TestModelType{ - E: Ptr(uint32(1)), + F: Ptr(uint32(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -689,10 +753,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uint32 type fields", v: TestModelType{ - E: Ptr(uint32(1)), + F: Ptr(uint32(1)), }, w: TestModelType{ - E: Ptr(uint32(0)), + F: Ptr(uint32(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -701,10 +765,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for uint64 type fields", v: TestModelType{ - E: Ptr(uint64(1)), + F: Ptr(uint64(1)), }, w: TestModelType{ - E: Ptr(uint64(1)), + F: Ptr(uint64(1)), }, m: TestModelTypeStructTagMap, updating: false, @@ -713,10 +777,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for uint64 type fields", v: TestModelType{ - E: Ptr(uint64(1)), + F: Ptr(uint64(1)), }, w: TestModelType{ - E: Ptr(uint64(0)), + F: Ptr(uint64(0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -725,10 +789,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for float32 type fields", v: TestModelType{ - E: Ptr(float32(1.0)), + F: Ptr(float32(1.0)), }, w: TestModelType{ - E: Ptr(float32(1.0)), + F: Ptr(float32(1.0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -737,10 +801,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for float32 type fields", v: TestModelType{ - E: Ptr(float32(1.0)), + F: Ptr(float32(1.0)), }, w: TestModelType{ - E: Ptr(float32(0.0)), + F: Ptr(float32(0.0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -749,10 +813,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for float64 type fields", v: TestModelType{ - E: Ptr(float64(1.0)), + F: Ptr(float64(1.0)), }, w: TestModelType{ - E: Ptr(float64(1.0)), + F: Ptr(float64(1.0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -761,10 +825,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for float64 type fields", v: TestModelType{ - E: Ptr(float64(1.0)), + F: Ptr(float64(1.0)), }, w: TestModelType{ - E: Ptr(float64(0.0)), + F: Ptr(float64(0.0)), }, m: TestModelTypeStructTagMap, updating: false, @@ -773,10 +837,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for complex64 type fields", v: TestModelType{ - E: Ptr(complex(float32(1.0), float32(-1.0))), + F: Ptr(complex(float32(1.0), float32(-1.0))), }, w: TestModelType{ - E: Ptr(complex(float32(1.0), float32(-1.0))), + F: Ptr(complex(float32(1.0), float32(-1.0))), }, m: TestModelTypeStructTagMap, updating: false, @@ -785,10 +849,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for complex64 type fields", v: TestModelType{ - E: Ptr(complex(float32(1.0), float32(-1.0))), + F: Ptr(complex(float32(1.0), float32(-1.0))), }, w: TestModelType{ - E: Ptr(complex(float32(0.0), float32(1.0))), + F: Ptr(complex(float32(0.0), float32(1.0))), }, m: TestModelTypeStructTagMap, updating: false, @@ -797,10 +861,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for complex128 type fields", v: TestModelType{ - E: Ptr(complex(float64(1.0), float64(-1.0))), + F: Ptr(complex(float64(1.0), float64(-1.0))), }, w: TestModelType{ - E: Ptr(complex(float64(1.0), float64(-1.0))), + F: Ptr(complex(float64(1.0), float64(-1.0))), }, m: TestModelTypeStructTagMap, updating: false, @@ -809,10 +873,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality for complex128 type fields", v: TestModelType{ - E: Ptr(complex(float64(1.0), float64(-1.0))), + F: Ptr(complex(float64(1.0), float64(-1.0))), }, w: TestModelType{ - E: Ptr(complex(float64(0.0), float64(1.0))), + F: Ptr(complex(float64(0.0), float64(1.0))), }, m: TestModelTypeStructTagMap, updating: false, @@ -821,10 +885,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for slice fields", v: TestModelType{ - E: []int{1, 2, 3}, + F: []int{1, 2, 3}, }, w: TestModelType{ - E: []int{1, 2, 3}, + F: []int{1, 2, 3}, }, m: TestModelTypeStructTagMap, updating: false, @@ -833,10 +897,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due to nil pointer for slice fields", v: TestModelType{ - E: []int{1, 2, 3}, + F: []int{1, 2, 3}, }, w: TestModelType{ - E: []int(nil), + F: []int(nil), }, m: TestModelTypeStructTagMap, updating: false, @@ -845,10 +909,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due to length for slice fields", v: TestModelType{ - E: []int{1, 2, 3}, + F: []int{1, 2, 3}, }, w: TestModelType{ - E: []int{1}, + F: []int{1}, }, m: TestModelTypeStructTagMap, updating: false, @@ -857,10 +921,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due to content for slice fields", v: TestModelType{ - E: []int{3, 2, 1}, + F: []int{3, 2, 1}, }, w: TestModelType{ - E: []int{1, 2, 3}, + F: []int{1, 2, 3}, }, m: TestModelTypeStructTagMap, updating: false, @@ -869,10 +933,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for array fields", v: TestModelType{ - E: [3]int{1, 2, 3}, + F: [3]int{1, 2, 3}, }, w: TestModelType{ - E: [3]int{1, 2, 3}, + F: [3]int{1, 2, 3}, }, m: TestModelTypeStructTagMap, updating: false, @@ -881,10 +945,10 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due for array fields", v: TestModelType{ - E: [3]int{3, 2, 1}, + F: [3]int{3, 2, 1}, }, w: TestModelType{ - E: [3]int{1, 2, 3}, + F: [3]int{1, 2, 3}, }, m: TestModelTypeStructTagMap, updating: false, @@ -893,7 +957,7 @@ func TestValidateVisibility(t *testing.T) { { name: "Test equality for map fields", v: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Blinky": "Shadow", "Pinky": "Speedy", "Inky": "Bashful", @@ -901,7 +965,7 @@ func TestValidateVisibility(t *testing.T) { }, }, w: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Blinky": "Shadow", "Pinky": "Speedy", "Inky": "Bashful", @@ -915,7 +979,7 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due to nil pointer for map fields", v: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Blinky": "Shadow", "Pinky": "Speedy", "Inky": "Bashful", @@ -923,7 +987,7 @@ func TestValidateVisibility(t *testing.T) { }, }, w: TestModelType{ - E: map[string]string(nil), + F: map[string]string(nil), }, m: TestModelTypeStructTagMap, updating: false, @@ -932,7 +996,7 @@ func TestValidateVisibility(t *testing.T) { { name: "Test inequality due to length for map fields", v: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Blinky": "Shadow", "Pinky": "Speedy", "Inky": "Bashful", @@ -940,7 +1004,7 @@ func TestValidateVisibility(t *testing.T) { }, }, w: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Blinky": "Shadow", }, }, @@ -949,9 +1013,9 @@ func TestValidateVisibility(t *testing.T) { errorsExpected: 1, }, { - name: "Test inequality due to content for map fields", + name: "Test inequality due to content for map keys", v: TestModelType{ - E: map[string]string{ + F: map[string]string{ "Akabei": "Oikake", "Pinky": "Machibuse", "Aosuke": "Kimagure", @@ -959,13 +1023,35 @@ func TestValidateVisibility(t *testing.T) { }, }, w: TestModelType{ - E: map[string]string{ + F: map[string]string{ + "Blinky": "Shadow", + "Pinky": "Speedy", + "Inky": "Bashful", + "Clyde": "Pokey", + }, + }, + m: TestModelTypeStructTagMap, + updating: false, + errorsExpected: 1, + }, + { + name: "Test inequality due to content for map values", + v: TestModelType{ + F: map[string]string{ "Blinky": "Shadow", "Pinky": "Speedy", "Inky": "Bashful", "Clyde": "Pokey", }, }, + w: TestModelType{ + F: map[string]string{ + "Blinky": "Red", + "Pinky": "Pink", + "Inky": "Cyan", + "Clyde": "Orange", + }, + }, m: TestModelTypeStructTagMap, updating: false, errorsExpected: 4, // error for each changed element diff --git a/internal/database/cache.go b/internal/database/cache.go deleted file mode 100644 index 63b6ca620..000000000 --- a/internal/database/cache.go +++ /dev/null @@ -1,198 +0,0 @@ -package database - -// Copyright (c) Microsoft Corporation. -// Licensed under the Apache License 2.0. - -import ( - "context" - "encoding/json" - "iter" - "strings" - - azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - - "github.com/Azure/ARO-HCP/internal/api/arm" -) - -var _ DBClient = &Cache{} - -// Cache is a simple DBClient that allows us to perform simple tests without needing a real CosmosDB. For production, -// use CosmosDBClient instead. Call NewCache() to initialize a Cache correctly. -type Cache struct { - resource map[string]*ResourceDocument - operation map[string]*OperationDocument - subscription map[string]*SubscriptionDocument -} - -type operationCacheIterator struct { - operation map[string]*OperationDocument - err error -} - -func (iter operationCacheIterator) Items(ctx context.Context) iter.Seq[[]byte] { - return func(yield func([]byte) bool) { - for _, doc := range iter.operation { - // Marshalling the document struct only to immediately unmarshal - // it back to a document struct is a little silly but this is to - // conform to the DBClientIterator interface. - item, err := json.Marshal(doc) - if err != nil { - iter.err = err - return - } - - if !yield(item) { - return - } - } - } -} - -func (iter operationCacheIterator) GetError() error { - return iter.err -} - -// NewCache initializes a new Cache to allow for simple tests without needing a real CosmosDB. For production, use -// NewCosmosDBConfig instead. -func NewCache() DBClient { - return &Cache{ - resource: make(map[string]*ResourceDocument), - operation: make(map[string]*OperationDocument), - subscription: make(map[string]*SubscriptionDocument), - } -} - -func (c *Cache) DBConnectionTest(ctx context.Context) error { - return nil -} - -func (c *Cache) GetLockClient() *LockClient { - return nil -} - -func (c *Cache) GetResourceDoc(ctx context.Context, resourceID *arm.ResourceID) (*ResourceDocument, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(resourceID.String()) - - if doc, ok := c.resource[key]; ok { - return doc, nil - } - - return nil, ErrNotFound -} - -func (c *Cache) CreateResourceDoc(ctx context.Context, doc *ResourceDocument) error { - // Make sure lookup keys are lowercase. - key := strings.ToLower(doc.Key.String()) - - c.resource[key] = doc - return nil -} - -func (c *Cache) UpdateResourceDoc(ctx context.Context, resourceID *arm.ResourceID, callback func(*ResourceDocument) bool) (bool, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(resourceID.String()) - - if doc, ok := c.resource[key]; ok { - return callback(doc), nil - } - - return false, ErrNotFound -} - -func (c *Cache) DeleteResourceDoc(ctx context.Context, resourceID *arm.ResourceID) error { - // Make sure lookup keys are lowercase. - key := strings.ToLower(resourceID.String()) - - delete(c.resource, key) - return nil -} - -func (c *Cache) ListResourceDocs(ctx context.Context, prefix *arm.ResourceID, resourceType *azcorearm.ResourceType, pageSizeHint int32, continuationToken *string) ([]*ResourceDocument, *string, error) { - var resourceList []*ResourceDocument - - // Make sure key prefix is lowercase. - prefixString := strings.ToLower(prefix.String() + "/") - - for key, doc := range c.resource { - if strings.HasPrefix(key, prefixString) { - if resourceType == nil || strings.EqualFold(resourceType.String(), doc.Key.ResourceType.String()) { - resourceList = append(resourceList, doc) - } - } - } - - return resourceList, nil, nil -} - -func (c *Cache) GetOperationDoc(ctx context.Context, operationID string) (*OperationDocument, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(operationID) - - if doc, ok := c.operation[key]; ok { - return doc, nil - } - - return nil, ErrNotFound -} - -func (c *Cache) CreateOperationDoc(ctx context.Context, doc *OperationDocument) error { - // Make sure lookup keys are lowercase. - key := strings.ToLower(doc.ID) - - c.operation[key] = doc - return nil -} - -func (c *Cache) UpdateOperationDoc(ctx context.Context, operationID string, callback func(*OperationDocument) bool) (bool, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(operationID) - - if doc, ok := c.operation[key]; ok { - return callback(doc), nil - } - - return false, ErrNotFound -} - -func (c *Cache) DeleteOperationDoc(ctx context.Context, operationID string) error { - // Make sure lookup keys are lowercase. - key := strings.ToLower(operationID) - - delete(c.operation, key) - return nil -} - -func (c *Cache) ListAllOperationDocs(ctx context.Context) DBClientIterator { - return operationCacheIterator{operation: c.operation} -} - -func (c *Cache) GetSubscriptionDoc(ctx context.Context, subscriptionID string) (*SubscriptionDocument, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(subscriptionID) - - if doc, ok := c.subscription[key]; ok { - return doc, nil - } - - return nil, ErrNotFound -} - -func (c *Cache) CreateSubscriptionDoc(ctx context.Context, doc *SubscriptionDocument) error { - // Make sure lookup keys are lowercase. - key := strings.ToLower(doc.ID) - - c.subscription[key] = doc - return nil -} - -func (c *Cache) UpdateSubscriptionDoc(ctx context.Context, subscriptionID string, callback func(*SubscriptionDocument) bool) (bool, error) { - // Make sure lookup keys are lowercase. - key := strings.ToLower(subscriptionID) - - if doc, ok := c.subscription[key]; ok { - return callback(doc), nil - } - - return false, ErrNotFound -} diff --git a/internal/database/database.go b/internal/database/database.go index 85b7c7348..4c5f58550 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -14,9 +14,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" - - "github.com/Azure/ARO-HCP/internal/api/arm" ) const ( @@ -49,8 +48,11 @@ func isResponseError(err error, statusCode int) bool { return errors.As(err, &responseError) && responseError.StatusCode == statusCode } +type DBClientIteratorItem iter.Seq[[]byte] + type DBClientIterator interface { - Items(ctx context.Context) iter.Seq[[]byte] + Items(ctx context.Context) DBClientIteratorItem + GetContinuationToken() string GetError() error } @@ -65,19 +67,19 @@ type DBClient interface { // GetResourceDoc retrieves a ResourceDocument from the database given its resourceID. // ErrNotFound is returned if an associated ResourceDocument cannot be found. - GetResourceDoc(ctx context.Context, resourceID *arm.ResourceID) (*ResourceDocument, error) + GetResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID) (*ResourceDocument, error) CreateResourceDoc(ctx context.Context, doc *ResourceDocument) error - UpdateResourceDoc(ctx context.Context, resourceID *arm.ResourceID, callback func(*ResourceDocument) bool) (bool, error) + UpdateResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID, callback func(*ResourceDocument) bool) (bool, error) // DeleteResourceDoc deletes a ResourceDocument from the database given the resourceID // of a Microsoft.RedHatOpenShift/HcpOpenShiftClusters resource or NodePools child resource. - DeleteResourceDoc(ctx context.Context, resourceID *arm.ResourceID) error - ListResourceDocs(ctx context.Context, prefix *arm.ResourceID, resourceType *azcorearm.ResourceType, pageSizeHint int32, continuationToken *string) ([]*ResourceDocument, *string, error) + DeleteResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID) error + ListResourceDocs(prefix *azcorearm.ResourceID, maxItems int32, continuationToken *string) DBClientIterator GetOperationDoc(ctx context.Context, operationID string) (*OperationDocument, error) CreateOperationDoc(ctx context.Context, doc *OperationDocument) error UpdateOperationDoc(ctx context.Context, operationID string, callback func(*OperationDocument) bool) (bool, error) DeleteOperationDoc(ctx context.Context, operationID string) error - ListAllOperationDocs(ctx context.Context) DBClientIterator + ListAllOperationDocs() DBClientIterator // GetSubscriptionDoc retrieves a SubscriptionDocument from the database given the subscriptionID. // ErrNotFound is returned if an associated SubscriptionDocument cannot be found. @@ -97,8 +99,9 @@ type CosmosDBClient struct { lockClient *LockClient } -// NewCosmosDBClient instantiates a Cosmos DatabaseClient targeting Frontends async DB -func NewCosmosDBClient(ctx context.Context, database *azcosmos.DatabaseClient) (DBClient, error) { +// NewDBClient instantiates a DBClient from a Cosmos DatabaseClient instance +// targeting the Frontends async database. +func NewDBClient(ctx context.Context, database *azcosmos.DatabaseClient) (DBClient, error) { // NewContainer only fails if the container ID argument is // empty, so we can safely disregard the error return value. resources, _ := database.NewContainer(resourcesContainer) @@ -134,7 +137,7 @@ func (d *CosmosDBClient) GetLockClient() *LockClient { } // GetResourceDoc retrieves a resource document from the "resources" DB using resource ID -func (d *CosmosDBClient) GetResourceDoc(ctx context.Context, resourceID *arm.ResourceID) (*ResourceDocument, error) { +func (d *CosmosDBClient) GetResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID) (*ResourceDocument, error) { // Make sure partition key is lowercase. pk := azcosmos.NewPartitionKeyString(strings.ToLower(resourceID.SubscriptionID)) @@ -175,7 +178,7 @@ func (d *CosmosDBClient) GetResourceDoc(ctx context.Context, resourceID *arm.Res // normalize or return a toupper or tolower form of the resource // group or resource name. The resource group name and resource // name must come from the URL and not the request body. - doc.Key = resourceID + doc.ResourceId = resourceID return doc, nil } return nil, fmt.Errorf("failed to read Resources container item for '%s': %w", resourceID, ErrNotFound) @@ -188,12 +191,12 @@ func (d *CosmosDBClient) CreateResourceDoc(ctx context.Context, doc *ResourceDoc data, err := json.Marshal(doc) if err != nil { - return fmt.Errorf("failed to marshal Resources container item for '%s': %w", doc.Key, err) + return fmt.Errorf("failed to marshal Resources container item for '%s': %w", doc.ResourceId, err) } _, err = d.resources.CreateItem(ctx, azcosmos.NewPartitionKeyString(doc.PartitionKey), data, nil) if err != nil { - return fmt.Errorf("failed to create Resources container item for '%s': %w", doc.Key, err) + return fmt.Errorf("failed to create Resources container item for '%s': %w", doc.ResourceId, err) } return nil @@ -207,7 +210,7 @@ func (d *CosmosDBClient) CreateResourceDoc(ctx context.Context, doc *ResourceDoc // The callback function should return true if modifications were applied, signaling to proceed // with the document replacement. The boolean return value reflects this: returning true if the // document was sucessfully replaced, or false with or without an error to indicate no change. -func (d *CosmosDBClient) UpdateResourceDoc(ctx context.Context, resourceID *arm.ResourceID, callback func(*ResourceDocument) bool) (bool, error) { +func (d *CosmosDBClient) UpdateResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID, callback func(*ResourceDocument) bool) (bool, error) { var err error // Make sure partition key is lowercase. @@ -250,7 +253,7 @@ func (d *CosmosDBClient) UpdateResourceDoc(ctx context.Context, resourceID *arm. } // DeleteResourceDoc removes a resource document from the "resources" DB using resource ID -func (d *CosmosDBClient) DeleteResourceDoc(ctx context.Context, resourceID *arm.ResourceID) error { +func (d *CosmosDBClient) DeleteResourceDoc(ctx context.Context, resourceID *azcorearm.ResourceID) error { // Make sure partition key is lowercase. pk := azcosmos.NewPartitionKeyString(strings.ToLower(resourceID.SubscriptionID)) @@ -269,13 +272,23 @@ func (d *CosmosDBClient) DeleteResourceDoc(ctx context.Context, resourceID *arm. return nil } -func (d *CosmosDBClient) ListResourceDocs(ctx context.Context, prefix *arm.ResourceID, resourceType *azcorearm.ResourceType, pageSizeHint int32, continuationToken *string) ([]*ResourceDocument, *string, error) { +// ListResourceDocs searches for resource documents that match the given resource ID prefix. +// maxItems can limit the number of items returned at once. A negative value will cause the +// returned iterator to yield all matching items. A positive value will cause the returned +// iterator to include a continuation token if additional items are available. +func (d *CosmosDBClient) ListResourceDocs(prefix *azcorearm.ResourceID, maxItems int32, continuationToken *string) DBClientIterator { // Make sure partition key is lowercase. pk := azcosmos.NewPartitionKeyString(strings.ToLower(prefix.SubscriptionID)) + // XXX The Cosmos DB REST API gives special meaning to -1 for "x-ms-max-item-count" + // but it's not clear if it treats all negative values equivalently. The Go SDK + // passes the PageSizeHint value as provided so normalize negative values to -1 + // to be safe. + maxItems = max(maxItems, -1) + query := "SELECT * FROM c WHERE STARTSWITH(c.key, @prefix, true)" opt := azcosmos.QueryOptions{ - PageSizeHint: pageSizeHint, + PageSizeHint: maxItems, ContinuationToken: continuationToken, QueryParameters: []azcosmos.QueryParameter{ { @@ -285,39 +298,13 @@ func (d *CosmosDBClient) ListResourceDocs(ctx context.Context, prefix *arm.Resou }, } - var response azcosmos.QueryItemsResponse - resourceDocs := make([]*ResourceDocument, 0, pageSizeHint) - - // Loop until we fill the pre-allocated resourceDocs slice, - // or until we run out of items from the resources container. - for opt.PageSizeHint > 0 { - var err error - - response, err = d.resources.NewQueryItemsPager(query, pk, &opt).NextPage(ctx) - if err != nil { - return nil, nil, fmt.Errorf("failed to advance page while querying Resources container for items with a key prefix of '%s': %w", prefix, err) - } - - for _, item := range response.Items { - var doc ResourceDocument - err = json.Unmarshal(item, &doc) - if err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal item while querying Resources container for items with a key prefix of '%s': %w", prefix, err) - } - if resourceType == nil || strings.EqualFold(resourceType.String(), doc.Key.ResourceType.String()) { - resourceDocs = append(resourceDocs, &doc) - } - } - - if response.ContinuationToken == nil { - break - } + pager := d.resources.NewQueryItemsPager(query, pk, &opt) - opt.PageSizeHint = int32(cap(resourceDocs) - len(resourceDocs)) - opt.ContinuationToken = response.ContinuationToken + if maxItems > 0 { + return newQueryItemsSinglePageIterator(pager) + } else { + return newQueryItemsIterator(pager) } - - return resourceDocs, response.ContinuationToken, nil } // GetOperationDoc retrieves the asynchronous operation document for the given @@ -428,9 +415,9 @@ func (d *CosmosDBClient) DeleteOperationDoc(ctx context.Context, operationID str return nil } -func (d *CosmosDBClient) ListAllOperationDocs(ctx context.Context) DBClientIterator { +func (d *CosmosDBClient) ListAllOperationDocs() DBClientIterator { pk := azcosmos.NewPartitionKeyString(operationsPartitionKey) - return NewQueryItemsIterator(d.operations.NewQueryItemsPager("SELECT * FROM c", pk, nil)) + return newQueryItemsIterator(d.operations.NewQueryItemsPager("SELECT * FROM c", pk, nil)) } // GetSubscriptionDoc retreives a subscription document from async DB using the subscription ID @@ -526,3 +513,26 @@ func (d *CosmosDBClient) UpdateSubscriptionDoc(ctx context.Context, subscription return false, err } + +// NewCosmosDatabaseClient instantiates a generic Cosmos database client. +func NewCosmosDatabaseClient(url string, dbName string, clientOptions azcore.ClientOptions) (*azcosmos.DatabaseClient, error) { + credential, err := azidentity.NewDefaultAzureCredential( + &azidentity.DefaultAzureCredentialOptions{ + ClientOptions: clientOptions, + }) + if err != nil { + return nil, err + } + + client, err := azcosmos.NewClient( + url, + credential, + &azcosmos.ClientOptions{ + ClientOptions: clientOptions, + }) + if err != nil { + return nil, err + } + + return client.NewDatabase(dbName) +} diff --git a/internal/database/document.go b/internal/database/document.go index f40021592..de6909db4 100644 --- a/internal/database/document.go +++ b/internal/database/document.go @@ -8,6 +8,7 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/google/uuid" "github.com/Azure/ARO-HCP/internal/api/arm" @@ -37,7 +38,8 @@ func newBaseDocument() BaseDocument { type ResourceDocument struct { BaseDocument - Key *arm.ResourceID `json:"key,omitempty"` + // FIXME: Change the JSON field name when we're ready to break backward-compat. + ResourceId *azcorearm.ResourceID `json:"key,omitempty"` PartitionKey string `json:"partitionKey,omitempty"` InternalID ocm.InternalID `json:"internalId,omitempty"` ActiveOperationID string `json:"activeOperationId,omitempty"` @@ -46,10 +48,10 @@ type ResourceDocument struct { Tags map[string]string `json:"tags,omitempty"` } -func NewResourceDocument(resourceID *arm.ResourceID) *ResourceDocument { +func NewResourceDocument(resourceID *azcorearm.ResourceID) *ResourceDocument { return &ResourceDocument{ BaseDocument: newBaseDocument(), - Key: resourceID, + ResourceId: resourceID, PartitionKey: strings.ToLower(resourceID.SubscriptionID), } } @@ -74,11 +76,12 @@ type OperationDocument struct { // Request is the type of asynchronous operation requested Request OperationRequest `json:"request,omitempty"` // ExternalID is the Azure resource ID of the cluster or node pool - ExternalID *arm.ResourceID `json:"externalId,omitempty"` + ExternalID *azcorearm.ResourceID `json:"externalId,omitempty"` // InternalID is the Cluster Service resource identifier in the form of a URL path InternalID ocm.InternalID `json:"internalId,omitempty"` - // OperationID is the Azure resource ID of the operation's status - OperationID *arm.ResourceID `json:"operationId,omitempty"` + // OperationID is the Azure resource ID of the operation status (may be nil if the + // operation was implicit, such as deleting a child resource along with the parent) + OperationID *azcorearm.ResourceID `json:"operationId,omitempty"` // NotificationURI is provided by the Azure-AsyncNotificationUri header if the // Async Operation Callbacks ARM feature is enabled NotificationURI string `json:"notificationUri,omitempty"` @@ -94,13 +97,15 @@ type OperationDocument struct { Error *arm.CloudErrorBody `json:"error,omitempty"` } -func NewOperationDocument(request OperationRequest) *OperationDocument { +func NewOperationDocument(request OperationRequest, externalID *azcorearm.ResourceID, internalID ocm.InternalID) *OperationDocument { now := time.Now().UTC() doc := &OperationDocument{ BaseDocument: newBaseDocument(), PartitionKey: operationsPartitionKey, Request: request, + ExternalID: externalID, + InternalID: internalID, StartTime: now, LastTransitionTime: now, Status: arm.ProvisioningStateAccepted, diff --git a/internal/database/util.go b/internal/database/util.go index 2ccbec4e4..5097edc02 100644 --- a/internal/database/util.go +++ b/internal/database/util.go @@ -5,25 +5,33 @@ package database import ( "context" - "iter" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) -type QueryItemsIterator struct { - pager *runtime.Pager[azcosmos.QueryItemsResponse] - err error +type queryItemsIterator struct { + pager *runtime.Pager[azcosmos.QueryItemsResponse] + singlePage bool + continuationToken string + err error } -// NewQueryItemsIterator is a failable push iterator for a paged query response. -func NewQueryItemsIterator(pager *runtime.Pager[azcosmos.QueryItemsResponse]) QueryItemsIterator { - return QueryItemsIterator{pager: pager} +// newQueryItemsIterator is a failable push iterator for a paged query response. +func newQueryItemsIterator(pager *runtime.Pager[azcosmos.QueryItemsResponse]) queryItemsIterator { + return queryItemsIterator{pager: pager} +} + +// newQueryItemsSinglePageIterator is a failable push iterator for a paged +// query response that stops at the end of the first page and includes a +// continuation token if additional items are available. +func newQueryItemsSinglePageIterator(pager *runtime.Pager[azcosmos.QueryItemsResponse]) queryItemsIterator { + return queryItemsIterator{pager: pager, singlePage: true} } // Items returns a push iterator that can be used directly in for/range loops. // If an error occurs during paging, iteration stops and the error is recorded. -func (iter QueryItemsIterator) Items(ctx context.Context) iter.Seq[[]byte] { +func (iter queryItemsIterator) Items(ctx context.Context) DBClientIteratorItem { return func(yield func([]byte) bool) { for iter.pager.More() { response, err := iter.pager.NextPage(ctx) @@ -31,17 +39,30 @@ func (iter QueryItemsIterator) Items(ctx context.Context) iter.Seq[[]byte] { iter.err = err return } + if iter.singlePage && response.ContinuationToken != nil { + iter.continuationToken = *response.ContinuationToken + } for _, item := range response.Items { if !yield(item) { return } } + if iter.singlePage { + return + } } } } +// GetContinuationToken returns a continuation token that can be used to obtain +// the next page of results. This is only set when the iterator was created with +// NewQueryItemsSinglePageIterator and additional items are available. +func (iter queryItemsIterator) GetContinuationToken() string { + return iter.continuationToken +} + // GetError returns any error that occurred during iteration. Call this after the // for/range loop that calls Items() to check if iteration completed successfully. -func (iter QueryItemsIterator) GetError() error { +func (iter queryItemsIterator) GetError() error { return iter.err } diff --git a/internal/go.mod b/internal/go.mod index 5b76f8883..e084c6993 100644 --- a/internal/go.mod +++ b/internal/go.mod @@ -4,50 +4,56 @@ go 1.23.0 require ( dario.cat/mergo v1.0.1 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 - github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 - github.com/go-playground/validator/v10 v10.22.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 + github.com/go-playground/validator/v10 v10.24.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 - github.com/openshift-online/ocm-sdk-go v0.1.447 + github.com/openshift-online/ocm-sdk-go v0.1.456 github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784 + go.uber.org/mock v0.5.0 ) require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect github.com/gorilla/css v1.0.1 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.20.4 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/tools v0.23.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/internal/go.sum b/internal/go.sum index afcc67507..acc6bb484 100644 --- a/internal/go.sum +++ b/internal/go.sum @@ -2,12 +2,12 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0 h1:c726lgbwpwFBuj+Fyrwuh/vUilqFo+hUAOUNjsKj5DI= -github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.1.0/go.mod h1:WzFGxuepAtZIZtQbz8/WviJycLMKJHpaEAqcXONxlag= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0 h1:1y5G4XTBTEt0nKNFtM7j6CxqkY5fxSuJb/mD8Zf0gPc= +github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.2.0/go.mod h1:1Dp+C8Sly0hnhX8k5zDuw72Z2ehd9Lv+pkLFn8dgXMA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= @@ -27,8 +27,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -37,14 +37,14 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg= +github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= @@ -110,8 +110,8 @@ github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/openshift-online/ocm-sdk-go v0.1.447 h1:PLau6NVgTpwL+L5OcKrBZm+HbET34tjHbENd2GsFhRw= -github.com/openshift-online/ocm-sdk-go v0.1.447/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= +github.com/openshift-online/ocm-sdk-go v0.1.456 h1:N9AmVv8H+FSlld88iCsafy+8Lhykz/1XUrmVhww/BYM= +github.com/openshift-online/ocm-sdk-go v0.1.456/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784 h1:SmOZFMxuAH4d1Cj7dOftVyo4Wg/mEC4pwz6QIJJsAkc= github.com/openshift/api v0.0.0-20240429104249-ac9356ba1784/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -137,23 +137,25 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 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.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 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= @@ -162,12 +164,13 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 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= diff --git a/internal/mocks/dbclient.go b/internal/mocks/dbclient.go new file mode 100644 index 000000000..965276f74 --- /dev/null +++ b/internal/mocks/dbclient.go @@ -0,0 +1,325 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ../database/database.go +// +// Generated by this command: +// +// mockgen-v0.5.0 -source=../database/database.go -destination=dbclient.go -package mocks github.com/Azure/ARO-HCP/internal/database DBClient +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + context "context" + reflect "reflect" + + database "github.com/Azure/ARO-HCP/internal/database" + arm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + gomock "go.uber.org/mock/gomock" +) + +// MockDBClientIterator is a mock of DBClientIterator interface. +type MockDBClientIterator struct { + ctrl *gomock.Controller + recorder *MockDBClientIteratorMockRecorder + isgomock struct{} +} + +// MockDBClientIteratorMockRecorder is the mock recorder for MockDBClientIterator. +type MockDBClientIteratorMockRecorder struct { + mock *MockDBClientIterator +} + +// NewMockDBClientIterator creates a new mock instance. +func NewMockDBClientIterator(ctrl *gomock.Controller) *MockDBClientIterator { + mock := &MockDBClientIterator{ctrl: ctrl} + mock.recorder = &MockDBClientIteratorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDBClientIterator) EXPECT() *MockDBClientIteratorMockRecorder { + return m.recorder +} + +// GetContinuationToken mocks base method. +func (m *MockDBClientIterator) GetContinuationToken() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetContinuationToken") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetContinuationToken indicates an expected call of GetContinuationToken. +func (mr *MockDBClientIteratorMockRecorder) GetContinuationToken() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContinuationToken", reflect.TypeOf((*MockDBClientIterator)(nil).GetContinuationToken)) +} + +// GetError mocks base method. +func (m *MockDBClientIterator) GetError() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetError") + ret0, _ := ret[0].(error) + return ret0 +} + +// GetError indicates an expected call of GetError. +func (mr *MockDBClientIteratorMockRecorder) GetError() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetError", reflect.TypeOf((*MockDBClientIterator)(nil).GetError)) +} + +// Items mocks base method. +func (m *MockDBClientIterator) Items(ctx context.Context) database.DBClientIteratorItem { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Items", ctx) + ret0, _ := ret[0].(database.DBClientIteratorItem) + return ret0 +} + +// Items indicates an expected call of Items. +func (mr *MockDBClientIteratorMockRecorder) Items(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Items", reflect.TypeOf((*MockDBClientIterator)(nil).Items), ctx) +} + +// MockDBClient is a mock of DBClient interface. +type MockDBClient struct { + ctrl *gomock.Controller + recorder *MockDBClientMockRecorder + isgomock struct{} +} + +// MockDBClientMockRecorder is the mock recorder for MockDBClient. +type MockDBClientMockRecorder struct { + mock *MockDBClient +} + +// NewMockDBClient creates a new mock instance. +func NewMockDBClient(ctrl *gomock.Controller) *MockDBClient { + mock := &MockDBClient{ctrl: ctrl} + mock.recorder = &MockDBClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDBClient) EXPECT() *MockDBClientMockRecorder { + return m.recorder +} + +// CreateOperationDoc mocks base method. +func (m *MockDBClient) CreateOperationDoc(ctx context.Context, doc *database.OperationDocument) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOperationDoc", ctx, doc) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateOperationDoc indicates an expected call of CreateOperationDoc. +func (mr *MockDBClientMockRecorder) CreateOperationDoc(ctx, doc any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOperationDoc", reflect.TypeOf((*MockDBClient)(nil).CreateOperationDoc), ctx, doc) +} + +// CreateResourceDoc mocks base method. +func (m *MockDBClient) CreateResourceDoc(ctx context.Context, doc *database.ResourceDocument) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateResourceDoc", ctx, doc) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateResourceDoc indicates an expected call of CreateResourceDoc. +func (mr *MockDBClientMockRecorder) CreateResourceDoc(ctx, doc any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateResourceDoc", reflect.TypeOf((*MockDBClient)(nil).CreateResourceDoc), ctx, doc) +} + +// CreateSubscriptionDoc mocks base method. +func (m *MockDBClient) CreateSubscriptionDoc(ctx context.Context, doc *database.SubscriptionDocument) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateSubscriptionDoc", ctx, doc) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateSubscriptionDoc indicates an expected call of CreateSubscriptionDoc. +func (mr *MockDBClientMockRecorder) CreateSubscriptionDoc(ctx, doc any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSubscriptionDoc", reflect.TypeOf((*MockDBClient)(nil).CreateSubscriptionDoc), ctx, doc) +} + +// DBConnectionTest mocks base method. +func (m *MockDBClient) DBConnectionTest(ctx context.Context) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DBConnectionTest", ctx) + ret0, _ := ret[0].(error) + return ret0 +} + +// DBConnectionTest indicates an expected call of DBConnectionTest. +func (mr *MockDBClientMockRecorder) DBConnectionTest(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DBConnectionTest", reflect.TypeOf((*MockDBClient)(nil).DBConnectionTest), ctx) +} + +// DeleteOperationDoc mocks base method. +func (m *MockDBClient) DeleteOperationDoc(ctx context.Context, operationID string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteOperationDoc", ctx, operationID) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteOperationDoc indicates an expected call of DeleteOperationDoc. +func (mr *MockDBClientMockRecorder) DeleteOperationDoc(ctx, operationID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteOperationDoc", reflect.TypeOf((*MockDBClient)(nil).DeleteOperationDoc), ctx, operationID) +} + +// DeleteResourceDoc mocks base method. +func (m *MockDBClient) DeleteResourceDoc(ctx context.Context, resourceID *arm.ResourceID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteResourceDoc", ctx, resourceID) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteResourceDoc indicates an expected call of DeleteResourceDoc. +func (mr *MockDBClientMockRecorder) DeleteResourceDoc(ctx, resourceID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteResourceDoc", reflect.TypeOf((*MockDBClient)(nil).DeleteResourceDoc), ctx, resourceID) +} + +// GetLockClient mocks base method. +func (m *MockDBClient) GetLockClient() *database.LockClient { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLockClient") + ret0, _ := ret[0].(*database.LockClient) + return ret0 +} + +// GetLockClient indicates an expected call of GetLockClient. +func (mr *MockDBClientMockRecorder) GetLockClient() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLockClient", reflect.TypeOf((*MockDBClient)(nil).GetLockClient)) +} + +// GetOperationDoc mocks base method. +func (m *MockDBClient) GetOperationDoc(ctx context.Context, operationID string) (*database.OperationDocument, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOperationDoc", ctx, operationID) + ret0, _ := ret[0].(*database.OperationDocument) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetOperationDoc indicates an expected call of GetOperationDoc. +func (mr *MockDBClientMockRecorder) GetOperationDoc(ctx, operationID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOperationDoc", reflect.TypeOf((*MockDBClient)(nil).GetOperationDoc), ctx, operationID) +} + +// GetResourceDoc mocks base method. +func (m *MockDBClient) GetResourceDoc(ctx context.Context, resourceID *arm.ResourceID) (*database.ResourceDocument, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetResourceDoc", ctx, resourceID) + ret0, _ := ret[0].(*database.ResourceDocument) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetResourceDoc indicates an expected call of GetResourceDoc. +func (mr *MockDBClientMockRecorder) GetResourceDoc(ctx, resourceID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourceDoc", reflect.TypeOf((*MockDBClient)(nil).GetResourceDoc), ctx, resourceID) +} + +// GetSubscriptionDoc mocks base method. +func (m *MockDBClient) GetSubscriptionDoc(ctx context.Context, subscriptionID string) (*database.SubscriptionDocument, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubscriptionDoc", ctx, subscriptionID) + ret0, _ := ret[0].(*database.SubscriptionDocument) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubscriptionDoc indicates an expected call of GetSubscriptionDoc. +func (mr *MockDBClientMockRecorder) GetSubscriptionDoc(ctx, subscriptionID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubscriptionDoc", reflect.TypeOf((*MockDBClient)(nil).GetSubscriptionDoc), ctx, subscriptionID) +} + +// ListAllOperationDocs mocks base method. +func (m *MockDBClient) ListAllOperationDocs() database.DBClientIterator { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListAllOperationDocs") + ret0, _ := ret[0].(database.DBClientIterator) + return ret0 +} + +// ListAllOperationDocs indicates an expected call of ListAllOperationDocs. +func (mr *MockDBClientMockRecorder) ListAllOperationDocs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAllOperationDocs", reflect.TypeOf((*MockDBClient)(nil).ListAllOperationDocs)) +} + +// ListResourceDocs mocks base method. +func (m *MockDBClient) ListResourceDocs(prefix *arm.ResourceID, maxItems int32, continuationToken *string) database.DBClientIterator { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListResourceDocs", prefix, maxItems, continuationToken) + ret0, _ := ret[0].(database.DBClientIterator) + return ret0 +} + +// ListResourceDocs indicates an expected call of ListResourceDocs. +func (mr *MockDBClientMockRecorder) ListResourceDocs(prefix, maxItems, continuationToken any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListResourceDocs", reflect.TypeOf((*MockDBClient)(nil).ListResourceDocs), prefix, maxItems, continuationToken) +} + +// UpdateOperationDoc mocks base method. +func (m *MockDBClient) UpdateOperationDoc(ctx context.Context, operationID string, callback func(*database.OperationDocument) bool) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateOperationDoc", ctx, operationID, callback) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateOperationDoc indicates an expected call of UpdateOperationDoc. +func (mr *MockDBClientMockRecorder) UpdateOperationDoc(ctx, operationID, callback any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateOperationDoc", reflect.TypeOf((*MockDBClient)(nil).UpdateOperationDoc), ctx, operationID, callback) +} + +// UpdateResourceDoc mocks base method. +func (m *MockDBClient) UpdateResourceDoc(ctx context.Context, resourceID *arm.ResourceID, callback func(*database.ResourceDocument) bool) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateResourceDoc", ctx, resourceID, callback) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateResourceDoc indicates an expected call of UpdateResourceDoc. +func (mr *MockDBClientMockRecorder) UpdateResourceDoc(ctx, resourceID, callback any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateResourceDoc", reflect.TypeOf((*MockDBClient)(nil).UpdateResourceDoc), ctx, resourceID, callback) +} + +// UpdateSubscriptionDoc mocks base method. +func (m *MockDBClient) UpdateSubscriptionDoc(ctx context.Context, subscriptionID string, callback func(*database.SubscriptionDocument) bool) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateSubscriptionDoc", ctx, subscriptionID, callback) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateSubscriptionDoc indicates an expected call of UpdateSubscriptionDoc. +func (mr *MockDBClientMockRecorder) UpdateSubscriptionDoc(ctx, subscriptionID, callback any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSubscriptionDoc", reflect.TypeOf((*MockDBClient)(nil).UpdateSubscriptionDoc), ctx, subscriptionID, callback) +} diff --git a/internal/mocks/generate.go b/internal/mocks/generate.go new file mode 100644 index 000000000..1e7609020 --- /dev/null +++ b/internal/mocks/generate.go @@ -0,0 +1,6 @@ +package mocks + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +//go:generate $MOCKGEN -source=../database/database.go -destination=dbclient.go -package mocks github.com/Azure/ARO-HCP/internal/database DBClient diff --git a/internal/ocm/internalid.go b/internal/ocm/internalid.go index 50bcba816..cf50e6f8d 100644 --- a/internal/ocm/internalid.go +++ b/internal/ocm/internalid.go @@ -9,6 +9,7 @@ import ( "path" "strings" + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" ) @@ -16,6 +17,9 @@ const ( v1Pattern = "/api/clusters_mgmt/v1" v1ClusterPattern = v1Pattern + "/clusters/*" v1NodePoolPattern = v1ClusterPattern + "/node_pools/*" + + aroHcpV1Alpha1Pattern = "/api/aro_hcp/v1alpha1" + aroHcpV1Alpha1ClusterPattern = aroHcpV1Alpha1Pattern + "/clusters/*" ) func GenerateClusterHREF(clusterName string) string { @@ -48,6 +52,10 @@ func (id *InternalID) validate() error { return nil } + if match, _ = path.Match(aroHcpV1Alpha1ClusterPattern, id.path); match { + return nil + } + return fmt.Errorf("Invalid InternalID: %s", id.path) } @@ -92,6 +100,12 @@ func (id *InternalID) Kind() string { kind = cmv1.ClusterKind } + // support clusters received via ARO HCP APIs + // without duplicating the whole codebase calling this method + if match, _ = path.Match(aroHcpV1Alpha1ClusterPattern, id.path); match { + kind = cmv1.ClusterKind + } + if match, _ = path.Match(v1NodePoolPattern, id.path); match { kind = cmv1.NodePoolKind } @@ -103,19 +117,54 @@ func (id *InternalID) Kind() string { // This works for both cluster and node pool resources. The transport // is most likely to be a Connection object from the SDK. func (id *InternalID) GetClusterClient(transport http.RoundTripper) (*cmv1.ClusterClient, bool) { - var thisPath string = id.path + switch matchClusterPath(id.path) { + case v1ClusterPattern: + return cmv1.NewClusterClient(transport, id.path), true + + case aroHcpV1Alpha1ClusterPattern: + // support clusters received via ARO HCP APIs + // without duplicating the whole codebase calling this method + newPath := strings.ReplaceAll(id.path, aroHcpV1Alpha1Pattern, v1Pattern) + return cmv1.NewClusterClient(transport, newPath), true + + default: + return nil, false + } +} + +// GetAroHCPClusterClient returns a arohcpv1alpha1 ClusterClient from the InternalID. +func (id *InternalID) GetAroHCPClusterClient(transport http.RoundTripper) (*arohcpv1alpha1.ClusterClient, bool) { + switch matchClusterPath(id.path) { + case v1ClusterPattern: + // support clusters received via cluster APIs + // without duplicating the whole codebase calling this method + newPath := strings.ReplaceAll(id.path, v1Pattern, aroHcpV1Alpha1Pattern) + return arohcpv1alpha1.NewClusterClient(transport, newPath), true + + case aroHcpV1Alpha1ClusterPattern: + return arohcpv1alpha1.NewClusterClient(transport, id.path), true + + default: + return nil, false + } +} + +func matchClusterPath(clusterPath string) string { + var thisPath = clusterPath var lastPath string for thisPath != lastPath { if match, _ := path.Match(v1ClusterPattern, thisPath); match { - return cmv1.NewClusterClient(transport, thisPath), true + return v1ClusterPattern + } else if match, _ := path.Match(aroHcpV1Alpha1ClusterPattern, thisPath); match { + return aroHcpV1Alpha1ClusterPattern } else { lastPath = thisPath thisPath = path.Dir(thisPath) } } - return nil, false + return "" } // GetNodePoolClient returns a v1 NodePoolClient from the InternalID. diff --git a/internal/ocm/internalid_test.go b/internal/ocm/internalid_test.go index fb02b9fd5..726f8f14d 100644 --- a/internal/ocm/internalid_test.go +++ b/internal/ocm/internalid_test.go @@ -39,6 +39,13 @@ func TestInternalID(t *testing.T) { kind: cmv1.ClusterKind, expectErr: false, }, + { + name: "parse v1 cluster", + path: "/api/aro_hcp/v1alpha1/clusters/abc", + id: "abc", + kind: cmv1.ClusterKind, + expectErr: false, + }, { name: "parse v1 node pool", path: "/api/clusters_mgmt/v1/clusters/abc/node_pools/def", @@ -51,15 +58,20 @@ func TestInternalID(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { internalID, err := NewInternalID(tt.path) - if err != nil { - if !tt.expectErr { - t.Error(err) - } - return + if err != nil && !tt.expectErr || err == nil && tt.expectErr { + t.Error(err) + } + + transport := &FakeTransport{} + if _, ok := internalID.GetClusterClient(transport); ok == tt.expectErr { + t.Errorf("failed to get cluster client") + } + if _, ok := internalID.GetAroHCPClusterClient(transport); ok == tt.expectErr { + t.Errorf("failed to get cluster client") } if tt.expectErr { - t.Error("expected unmarshaling to fail") + // test ends here if error is expected return } @@ -78,10 +90,6 @@ func TestInternalID(t *testing.T) { t.Errorf("expected string '%s', got '%s'", tt.path, str) } - transport := &FakeTransport{} - if _, ok := internalID.GetClusterClient(transport); !ok { - t.Errorf("failed to get cluster client") - } if kind == cmv1.NodePoolKind { if _, ok := internalID.GetNodePoolClient(transport); !ok { t.Errorf("failed to get node pool client") diff --git a/internal/ocm/iterators.go b/internal/ocm/iterators.go new file mode 100644 index 000000000..1120f94ae --- /dev/null +++ b/internal/ocm/iterators.go @@ -0,0 +1,121 @@ +package ocm + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "context" + "iter" + "math" + + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" + cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" +) + +type ClusterListIterator struct { + request *arohcpv1alpha1.ClustersListRequest + err error +} + +// Items returns a push iterator that can be used directly in for/range loops. +// If an error occurs during paging, iteration stops and the error is recorded. +func (iter ClusterListIterator) Items(ctx context.Context) iter.Seq[*arohcpv1alpha1.Cluster] { + return func(yield func(*arohcpv1alpha1.Cluster) bool) { + // Request can be nil to allow for mocking. + if iter.request != nil { + var page int = 0 + var count int = 0 + var total int = math.MaxInt + + for count < total { + page++ + result, err := iter.request.Page(page).SendContext(ctx) + if err != nil { + iter.err = err + return + } + + total = result.Total() + items := result.Items() + + // Safety check to prevent an infinite loop in case + // the result is somehow empty before count = total. + if items == nil || items.Empty() { + return + } + + count += items.Len() + + // XXX ClusterList.Each() lacks a boolean return to + // indicate whether iteration fully completed. + // ClusterList.Slice() may be less efficient but + // is easier to work with. + for _, item := range items.Slice() { + if !yield(item) { + return + } + } + } + } + } +} + +// GetError returns any error that occurred during iteration. Call this after the +// for/range loop that calls Items() to check if iteration completed successfully. +func (iter ClusterListIterator) GetError() error { + return iter.err +} + +type NodePoolListIterator struct { + request *cmv1.NodePoolsListRequest + err error +} + +// Items returns a push iterator that can be used directly in for/range loops. +// If an error occurs during paging, iteration stops and the error is recorded. +func (iter NodePoolListIterator) Items(ctx context.Context) iter.Seq[*cmv1.NodePool] { + return func(yield func(*cmv1.NodePool) bool) { + // Request can be nil to allow for mocking. + if iter.request != nil { + var page int = 0 + var count int = 0 + var total int = math.MaxInt + + for count < total { + page++ + result, err := iter.request.Page(page).SendContext(ctx) + if err != nil { + iter.err = err + return + } + + total = result.Total() + items := result.Items() + + // Safety check to prevent an infinite loop in case + // the result is somehow empty before count = total. + if items == nil || items.Empty() { + return + } + + count += items.Len() + + // XXX NodePoolList.Each() lacks a boolean return to + // indicate whether iteration fully completed. + // NodePoolList.Slice() may be less efficient but + // is easier to work with. + for _, item := range items.Slice() { + if !yield(item) { + return + } + } + } + } + } +} + +// GetError returns any error that occurred during iteration. Call this after the +// for/range loop that calls Items() to check if iteration completed successfully. +func (iter NodePoolListIterator) GetError() error { + return iter.err +} diff --git a/internal/ocm/mock.go b/internal/ocm/mock.go index 2081d2517..a2ed44a7e 100644 --- a/internal/ocm/mock.go +++ b/internal/ocm/mock.go @@ -8,6 +8,7 @@ import ( "fmt" sdk "github.com/openshift-online/ocm-sdk-go" + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" "github.com/openshift-online/ocm-sdk-go/errors" ) @@ -15,7 +16,7 @@ import ( // MockClusterServiceClient allows for unit testing functions // that make calls to the ClusterServiceClient interface. type MockClusterServiceClient struct { - clusters map[InternalID](*cmv1.Cluster) + clusters map[InternalID](*arohcpv1alpha1.Cluster) nodePools map[InternalID](*cmv1.NodePool) } @@ -34,19 +35,19 @@ func mockNotFoundError(internalID InternalID) error { // NewCosmosDBConfig instead. func NewMockClusterServiceClient() MockClusterServiceClient { return MockClusterServiceClient{ - clusters: make(map[InternalID]*cmv1.Cluster), + clusters: make(map[InternalID]*arohcpv1alpha1.Cluster), nodePools: make(map[InternalID]*cmv1.NodePool), } } func (mcsc *MockClusterServiceClient) GetConn() *sdk.Connection { panic("GetConn not implemented") } -func (csc *MockClusterServiceClient) AddProperties(builder *cmv1.ClusterBuilder) *cmv1.ClusterBuilder { - additionalProperties := getDefaultAdditionalProperities() +func (csc *MockClusterServiceClient) AddProperties(builder *arohcpv1alpha1.ClusterBuilder) *arohcpv1alpha1.ClusterBuilder { + additionalProperties := map[string]string{} return builder.Properties(additionalProperties) } -func (mcsc *MockClusterServiceClient) GetCSCluster(ctx context.Context, internalID InternalID) (*cmv1.Cluster, error) { +func (mcsc *MockClusterServiceClient) GetCSCluster(ctx context.Context, internalID InternalID) (*arohcpv1alpha1.Cluster, error) { cluster, ok := mcsc.clusters[internalID] if !ok { @@ -55,10 +56,10 @@ func (mcsc *MockClusterServiceClient) GetCSCluster(ctx context.Context, internal return cluster, nil } -func (mcsc *MockClusterServiceClient) PostCSCluster(ctx context.Context, cluster *cmv1.Cluster) (*cmv1.Cluster, error) { +func (mcsc *MockClusterServiceClient) PostCSCluster(ctx context.Context, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) { href := GenerateClusterHREF(cluster.Name()) // Adding the HREF to correspond with what the full client does when crating the body - clusterBuilder := cmv1.NewCluster() + clusterBuilder := arohcpv1alpha1.NewCluster() enrichedCluster, err := clusterBuilder.Copy(cluster).HREF(href).Build() if err != nil { return nil, err @@ -71,7 +72,7 @@ func (mcsc *MockClusterServiceClient) PostCSCluster(ctx context.Context, cluster return enrichedCluster, nil } -func (mcsc *MockClusterServiceClient) UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *cmv1.Cluster) (*cmv1.Cluster, error) { +func (mcsc *MockClusterServiceClient) UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) { _, ok := mcsc.clusters[internalID] if !ok { @@ -91,6 +92,10 @@ func (mcsc *MockClusterServiceClient) DeleteCSCluster(ctx context.Context, inter return nil } +func (mcsc *MockClusterServiceClient) ListCSClusters(searchExpression string) ClusterListIterator { + return ClusterListIterator{err: fmt.Errorf("ListCSClusters not implemented")} +} + func (mcsc *MockClusterServiceClient) GetCSNodePool(ctx context.Context, internalID InternalID) (*cmv1.NodePool, error) { nodePool, ok := mcsc.nodePools[internalID] if !ok { @@ -133,3 +138,7 @@ func (mcsc *MockClusterServiceClient) DeleteCSNodePool(ctx context.Context, inte delete(mcsc.nodePools, internalID) return nil } + +func (mcsc *MockClusterServiceClient) ListCSNodePools(clusterInternalID InternalID, searchExpression string) NodePoolListIterator { + return NodePoolListIterator{err: fmt.Errorf("ListCSClusters not implemented")} +} diff --git a/internal/ocm/ocm.go b/internal/ocm/ocm.go index 6c5dc2fea..e607e3b42 100644 --- a/internal/ocm/ocm.go +++ b/internal/ocm/ocm.go @@ -8,41 +8,23 @@ import ( "fmt" sdk "github.com/openshift-online/ocm-sdk-go" + arohcpv1alpha1 "github.com/openshift-online/ocm-sdk-go/arohcp/v1alpha1" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" ) type ClusterServiceClientSpec interface { GetConn() *sdk.Connection - AddProperties(builder *cmv1.ClusterBuilder) *cmv1.ClusterBuilder - GetCSCluster(ctx context.Context, internalID InternalID) (*cmv1.Cluster, error) - PostCSCluster(ctx context.Context, cluster *cmv1.Cluster) (*cmv1.Cluster, error) - UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *cmv1.Cluster) (*cmv1.Cluster, error) + AddProperties(builder *arohcpv1alpha1.ClusterBuilder) *arohcpv1alpha1.ClusterBuilder + GetCSCluster(ctx context.Context, internalID InternalID) (*arohcpv1alpha1.Cluster, error) + PostCSCluster(ctx context.Context, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) + UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) DeleteCSCluster(ctx context.Context, internalID InternalID) error + ListCSClusters(searchExpression string) ClusterListIterator GetCSNodePool(ctx context.Context, internalID InternalID) (*cmv1.NodePool, error) PostCSNodePool(ctx context.Context, clusterInternalID InternalID, nodePool *cmv1.NodePool) (*cmv1.NodePool, error) UpdateCSNodePool(ctx context.Context, internalID InternalID, nodePool *cmv1.NodePool) (*cmv1.NodePool, error) DeleteCSNodePool(ctx context.Context, internalID InternalID) error -} - -// Get the default set of properties for the Cluster Service -func getDefaultAdditionalProperities() map[string]string { - // additionalProperties should be empty in production, it is configurable for development to pin to specific - // provision shards or instruct CS to skip the full provisioning/deprovisioning flow. - additionalProperties := map[string]string{ - // Enable the ARO HCP provisioner during development. For now, if not set a cluster will not progress past the - // installing state in CS. - "provisioner_hostedcluster_step_enabled": "true", - // Enable the provisioning of ACM's ManagedCluster CR associated to the ARO-HCP - // cluster during ARO-HCP Cluster provisioning. For now, if not set a cluster will not progress past the - // installing state in CS. - "provisioner_managedcluster_step_enabled": "true", - - // Enable the provisioning and deprovisioning of ARO-HCP Node Pools. For now, if not set the provisioning - // and deprovisioning of day 2 ARO-HCP Node Pools will not be performed on the Management Cluster. - "np_provisioner_provision_enabled": "true", - "np_provisioner_deprovision_enabled": "true", - } - return additionalProperties + ListCSNodePools(clusterInternalID InternalID, searchExpression string) NodePoolListIterator } type ClusterServiceClient struct { @@ -64,9 +46,9 @@ type ClusterServiceClient struct { func (csc *ClusterServiceClient) GetConn() *sdk.Connection { return csc.Conn } -// AddProperties injects the some addtional properties into the CSCluster Object. -func (csc *ClusterServiceClient) AddProperties(builder *cmv1.ClusterBuilder) *cmv1.ClusterBuilder { - additionalProperties := getDefaultAdditionalProperities() +// AddProperties injects the some additional properties into the CSCluster Object. +func (csc *ClusterServiceClient) AddProperties(builder *arohcpv1alpha1.ClusterBuilder) *arohcpv1alpha1.ClusterBuilder { + additionalProperties := map[string]string{} if csc.ProvisionShardID != nil { additionalProperties["provision_shard_id"] = *csc.ProvisionShardID } @@ -80,8 +62,8 @@ func (csc *ClusterServiceClient) AddProperties(builder *cmv1.ClusterBuilder) *cm } // GetCSCluster creates and sends a GET request to fetch a cluster from Clusters Service -func (csc *ClusterServiceClient) GetCSCluster(ctx context.Context, internalID InternalID) (*cmv1.Cluster, error) { - client, ok := internalID.GetClusterClient(csc.Conn) +func (csc *ClusterServiceClient) GetCSCluster(ctx context.Context, internalID InternalID) (*arohcpv1alpha1.Cluster, error) { + client, ok := internalID.GetAroHCPClusterClient(csc.Conn) if !ok { return nil, fmt.Errorf("OCM path is not a cluster: %s", internalID) } @@ -114,8 +96,8 @@ func (csc *ClusterServiceClient) GetCSClusterStatus(ctx context.Context, interna } // PostCSCluster creates and sends a POST request to create a cluster in Clusters Service -func (csc *ClusterServiceClient) PostCSCluster(ctx context.Context, cluster *cmv1.Cluster) (*cmv1.Cluster, error) { - clustersAddResponse, err := csc.Conn.ClustersMgmt().V1().Clusters().Add().Body(cluster).SendContext(ctx) +func (csc *ClusterServiceClient) PostCSCluster(ctx context.Context, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) { + clustersAddResponse, err := csc.Conn.AroHCP().V1alpha1().Clusters().Add().Body(cluster).SendContext(ctx) if err != nil { return nil, err } @@ -127,8 +109,8 @@ func (csc *ClusterServiceClient) PostCSCluster(ctx context.Context, cluster *cmv } // UpdateCSCluster sends a PATCH request to update a cluster in Clusters Service -func (csc *ClusterServiceClient) UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *cmv1.Cluster) (*cmv1.Cluster, error) { - client, ok := internalID.GetClusterClient(csc.Conn) +func (csc *ClusterServiceClient) UpdateCSCluster(ctx context.Context, internalID InternalID, cluster *arohcpv1alpha1.Cluster) (*arohcpv1alpha1.Cluster, error) { + client, ok := internalID.GetAroHCPClusterClient(csc.Conn) if !ok { return nil, fmt.Errorf("OCM path is not a cluster: %s", internalID) } @@ -145,7 +127,7 @@ func (csc *ClusterServiceClient) UpdateCSCluster(ctx context.Context, internalID // DeleteCSCluster creates and sends a DELETE request to delete a cluster from Clusters Service func (csc *ClusterServiceClient) DeleteCSCluster(ctx context.Context, internalID InternalID) error { - client, ok := internalID.GetClusterClient(csc.Conn) + client, ok := internalID.GetAroHCPClusterClient(csc.Conn) if !ok { return fmt.Errorf("OCM path is not a cluster: %s", internalID) } @@ -153,6 +135,17 @@ func (csc *ClusterServiceClient) DeleteCSCluster(ctx context.Context, internalID return err } +// ListCSClusters prepares a GET request with the given search expression. Call Items() on +// the returned iterator in a for/range loop to execute the request and paginate over results, +// then call GetError() to check for an iteration error. +func (csc *ClusterServiceClient) ListCSClusters(searchExpression string) ClusterListIterator { + clustersListRequest := csc.Conn.AroHCP().V1alpha1().Clusters().List() + if searchExpression != "" { + clustersListRequest.Search(searchExpression) + } + return ClusterListIterator{request: clustersListRequest} +} + // GetCSNodePool creates and sends a GET request to fetch a node pool from Clusters Service func (csc *ClusterServiceClient) GetCSNodePool(ctx context.Context, internalID InternalID) (*cmv1.NodePool, error) { client, ok := internalID.GetNodePoolClient(csc.Conn) @@ -213,3 +206,18 @@ func (csc *ClusterServiceClient) DeleteCSNodePool(ctx context.Context, internalI _, err := client.Delete().SendContext(ctx) return err } + +// ListCSNodePools prepares a GET request with the given search expression. Call Items() on +// the returned iterator in a for/range loop to execute the request and paginate over results, +// then call GetError() to check for an iteration error. +func (csc *ClusterServiceClient) ListCSNodePools(clusterInternalID InternalID, searchExpression string) NodePoolListIterator { + client, ok := clusterInternalID.GetClusterClient(csc.Conn) + if !ok { + return NodePoolListIterator{err: fmt.Errorf("OCM path is not a cluster: %s", clusterInternalID)} + } + nodePoolsListRequest := client.NodePools().List() + if searchExpression != "" { + nodePoolsListRequest.Search(searchExpression) + } + return NodePoolListIterator{request: nodePoolsListRequest} +} diff --git a/istio/Makefile b/istio/Makefile index 963abf6ea..948cc206c 100644 --- a/istio/Makefile +++ b/istio/Makefile @@ -1,7 +1,9 @@ +-include ../setup-env.mk + deploy: deploy-service deploy-service: - kubectl apply -k overlays/svc + kubectl apply ${KUBECTL_DRY_RUN} -k overlays/svc undeploy-service: kubectl delete -k overlays/svc diff --git a/istio/pipeline.yaml b/istio/pipeline.yaml new file mode 100644 index 000000000..b757e223a --- /dev/null +++ b/istio/pipeline.yaml @@ -0,0 +1,15 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.Istio +rolloutName: RP Istio Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: KUBECTL_DRY_RUN + value: "--dry-run=client -o yaml" diff --git a/maestro/agent/Makefile b/maestro/agent/Makefile index 2509361cd..aea932b5f 100644 --- a/maestro/agent/Makefile +++ b/maestro/agent/Makefile @@ -1,14 +1,14 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../../setup-env.mk +-include ../../helm-cmd.mk +HELM_CMD ?= helm upgrade --install deploy: - TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ + @kubectl create namespace maestro --dry-run=client -o json | kubectl apply -f - + @TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ EVENTGRID_HOSTNAME=$(shell az resource show -n ${EVENTGRID_NAME} -g ${REGION_RG} --resource-type "Microsoft.EventGrid/namespaces" --query properties.topicSpacesConfiguration.hostname -o tsv) && \ MAESTRO_MI_CLIENT_ID=$(shell az identity show -g "${MGMT_RG}" -n maestro-consumer --query clientId -o tsv) && \ - helm upgrade --install maestro-agent ./helm \ - --create-namespace --namespace maestro \ + ${HELM_CMD} maestro-agent ./helm \ + --namespace maestro \ --set consumerName=${CONSUMER_NAME} \ --set broker.host=$${EVENTGRID_HOSTNAME} \ --set credsKeyVault.name=${KEYVAULT_NAME} \ diff --git a/maestro/agent/config.tmpl.mk b/maestro/agent/config.tmpl.mk deleted file mode 100644 index f9ceeac01..000000000 --- a/maestro/agent/config.tmpl.mk +++ /dev/null @@ -1,7 +0,0 @@ -EVENTGRID_NAME ?= {{ .maestroEventgridName}} -REGION_RG ?= {{ .regionRG }} -MGMT_RG ?= {{ .managementClusterRG }} -CONSUMER_NAME ?= {{ .maestroConsumerName }} -KEYVAULT_NAME ?= {{ .maestroKeyVaultName }} -IMAGE_BASE ?= {{ .maestroImageBase }} -IMAGE_TAG ?= {{ .maestroImageTag }} diff --git a/maestro/agent/pipeline.yaml b/maestro/agent/pipeline.yaml new file mode 100644 index 000000000..a26fd2f62 --- /dev/null +++ b/maestro/agent/pipeline.yaml @@ -0,0 +1,30 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Maestro.Agent +rolloutName: Maestro Agent Rollout +resourceGroups: +- name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: EVENTGRID_NAME + configRef: maestro.eventGrid.name + - name: REGION_RG + configRef: regionRG + - name: MGMT_RG + configRef: mgmt.rg + - name: CONSUMER_NAME + configRef: maestro.consumerName + - name: KEYVAULT_NAME + configRef: mgmtKeyVault.name + - name: IMAGE_BASE + configRef: maestro.imageBase + - name: IMAGE_TAG + configRef: maestro.imageTag diff --git a/maestro/registration/Makefile b/maestro/registration/Makefile index d62b33184..c790cc8ad 100644 --- a/maestro/registration/Makefile +++ b/maestro/registration/Makefile @@ -2,13 +2,15 @@ SHELL = /bin/bash DEPLOY_ENV ?= personal-dev $(shell ../../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) include config.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install deploy: - @if ! kubectl get service maestro -n maestro > /dev/null 2>&1; then \ - echo "Error: Service 'maestro' not found in namespace 'maestro'"; \ + @if ! kubectl get service maestro -n ${NAMESPACE} > /dev/null 2>&1; then \ + echo "Error: Service 'maestro' not found in namespace '${NAMESPACE}'"; \ exit 1; \ fi - helm upgrade --install ${CONSUMER_NAME} ./helm \ - --namespace maestro \ + ${HELM_CMD} ${CONSUMER_NAME} ./helm \ + --namespace ${NAMESPACE} \ --set consumerName=${CONSUMER_NAME} .PHONY: deploy diff --git a/maestro/registration/config.tmpl.mk b/maestro/registration/config.tmpl.mk index 8918876a7..cf233a0bc 100644 --- a/maestro/registration/config.tmpl.mk +++ b/maestro/registration/config.tmpl.mk @@ -1 +1,2 @@ -CONSUMER_NAME ?= {{ .maestroConsumerName }} +CONSUMER_NAME ?= {{ .maestro.consumerName }} +NAMESPACE ?= {{ .maestro.server.k8s.namespace }} diff --git a/maestro/server/Makefile b/maestro/server/Makefile index 2f97063fb..346e17d65 100644 --- a/maestro/server/Makefile +++ b/maestro/server/Makefile @@ -1,24 +1,29 @@ -SHELL = /bin/bash -DEPLOY_ENV ?= personal-dev -$(shell ../../templatize.sh $(DEPLOY_ENV) config.tmpl.mk config.mk) -include config.mk +-include ../../setup-env.mk +-include ../../helm-cmd.mk +HELM_CMD ?= helm upgrade --install deploy: - kubectl create namespace maestro --dry-run=client -o json | kubectl apply -f - - ISTO_VERSION=$(shell az aks show -n ${AKS_NAME} -g ${SVC_RG} --query serviceMeshProfile.istio.revisions[-1] -o tsv) && \ - kubectl label namespace maestro "istio.io/rev=$${ISTO_VERSION}" --overwrite=true - EVENTGRID_HOSTNAME=$(shell az resource show -n ${EVENTGRID_NAME} -g ${REGION_RG} --resource-type "Microsoft.EventGrid/namespaces" --query properties.topicSpacesConfiguration.hostname -o tsv) && \ + @kubectl create namespace ${NAMESPACE} --dry-run=client -o json | kubectl apply -f - + @kubectl label ${KUBECTL_DRY_RUN} namespace ${NAMESPACE} "istio.io/rev=${ISTO_TAG}" --overwrite=true + @EVENTGRID_HOSTNAME=$(shell az resource show -n ${EVENTGRID_NAME} -g ${REGION_RG} --resource-type "Microsoft.EventGrid/namespaces" --query properties.topicSpacesConfiguration.hostname -o tsv) && \ TENANT_ID=$(shell az account show --query tenantId --output tsv) && \ - MAESTRO_MI_CLIENT_ID=$(shell az identity show -g "${SVC_RG}" -n maestro-server --query clientId -o tsv) && \ - helm upgrade --install maestro-server ./helm \ - --namespace maestro \ + MAESTRO_MI_CLIENT_ID=$(shell az identity show -g "${SVC_RG}" -n ${MANAGED_IDENTITY_NAME} --query clientId -o tsv) && \ + DATABASE_HOST=$$(if [ "${USE_AZURE_DB}" = "true" ]; then az postgres flexible-server show -g ${SVC_RG} -n ${DATABASE_SERVER_NAME} --query fullyQualifiedDomainName -o tsv; else echo "maestro-db"; fi) && \ + OVERRIDES=$$(if [ "${USE_AZURE_DB}" = "true" ]; then echo "azuredb.values.yaml"; else echo "containerdb.values.yaml"; fi) && \ + ${HELM_CMD} maestro-server ./helm \ + --namespace ${NAMESPACE} \ + -f helm/$${OVERRIDES} \ + --set maestro.serviceAccount=${SERVICE_ACCOUNT_NAME} \ --set broker.host=$${EVENTGRID_HOSTNAME} \ --set credsKeyVault.name=${KEYVAULT_NAME} \ + --set credsKeyVault.secret=${MQTT_CLIENT_NAME} \ --set azure.clientId=$${MAESTRO_MI_CLIENT_ID} \ --set azure.tenantId=$${TENANT_ID} \ --set istio.restrictIngress=${ISTIO_RESTRICT_INGRESS} \ --set image.base=${IMAGE_BASE} \ --set image.tag=${IMAGE_TAG} \ - --set database.containerizedDb=${USE_CONTAINERIZED_DB} \ - --set database.ssl='${USE_DATABASE_SSL}' + --set database.host=$${DATABASE_HOST} \ + --set database.name=${DATABASE_NAME} \ + --set clusterService.namespace=${CS_NAMESPACE} \ + --set clusterService.serviceAccount=${CS_SERVICE_ACCOUNT_NAME} .PHONY: deploy diff --git a/maestro/server/config.tmpl.mk b/maestro/server/config.tmpl.mk deleted file mode 100644 index 31acff9d0..000000000 --- a/maestro/server/config.tmpl.mk +++ /dev/null @@ -1,10 +0,0 @@ -EVENTGRID_NAME ?= {{ .maestroEventgridName}} -REGION_RG ?= {{ .regionRG }} -AKS_NAME ?= {{ .aksName }} -SVC_RG ?= {{ .serviceClusterRG }} -IMAGE_BASE ?= {{ .maestroImageBase }} -IMAGE_TAG ?= {{ .maestroImageTag }} -USE_CONTAINERIZED_DB ?= {{ not .maestroPostgresDeploy }} -USE_DATABASE_SSL ?= {{ ternary "enable" "disable" .maestroPostgresDeploy }} -ISTIO_RESTRICT_INGRESS ?= {{ .maestroRestrictIstioIngress }} -KEYVAULT_NAME ?= {{ .maestroKeyVaultName }} diff --git a/maestro/server/helm/azuredb.values.yaml b/maestro/server/helm/azuredb.values.yaml new file mode 100644 index 000000000..b972f8750 --- /dev/null +++ b/maestro/server/helm/azuredb.values.yaml @@ -0,0 +1,4 @@ +database: + containerizedDb: false + ssl: require + authMethod: az-entra diff --git a/maestro/server/helm/containerdb.values.yaml b/maestro/server/helm/containerdb.values.yaml new file mode 100644 index 000000000..7079babc2 --- /dev/null +++ b/maestro/server/helm/containerdb.values.yaml @@ -0,0 +1,7 @@ +database: + containerizedDb: true + ssl: disable + authMethod: password + password: "TheBlurstOfTimes" + containerizedDbImage: docker.io/library/postgres:14.2 + containerizedDbPvcCapacity: 512Mi diff --git a/maestro/server/helm/templates/maestro.deployment.yaml b/maestro/server/helm/templates/maestro.deployment.yaml index 3ee367a24..9ad607742 100644 --- a/maestro/server/helm/templates/maestro.deployment.yaml +++ b/maestro/server/helm/templates/maestro.deployment.yaml @@ -19,6 +19,7 @@ spec: metadata: labels: app: maestro + azure.workload.identity/use: "true" annotations: checksum/credsstore: {{ include (print $.Template.BasePath "/maestro.secretproviderclass.yaml") . | sha256sum }} checksum/config: {{ include (print $.Template.BasePath "/maestro.secret.yaml") . | sha256sum }} @@ -53,9 +54,11 @@ spec: - --db-user-file=/secrets/db/db.user - --db-password-file=/secrets/db/db.password - --db-name-file=/secrets/db/db.name + - --db-rootcert= - --db-sslmode={{ .Values.database.ssl }} - --alsologtostderr - -v={{ .Values.maestro.glog_v }} + - --db-auth-method={{ .Values.database.authMethod }} containers: - name: service image: "{{ .Values.image.base }}:{{ .Values.image.tag }}" @@ -86,7 +89,7 @@ spec: - --db-user-file=/secrets/db/db.user - --db-password-file=/secrets/db/db.password - --db-name-file=/secrets/db/db.name - - --db-rootcert=/secrets/db/db.ca_cert + - --db-rootcert= - --db-sslmode={{ .Values.database.ssl }} - --db-max-open-connections={{ .Values.database.maxOpenConnections }} - --message-broker-config-file=/secrets/maestro/config.yaml @@ -110,6 +113,7 @@ spec: - --label-metrics-inclusion-duration={{ .Values.maestro.labelMetricsInclusionDuration }} - --alsologtostderr - -v={{ .Values.maestro.glog_v }} + - --db-auth-method={{ .Values.database.authMethod }} resources: requests: cpu: {{ .Values.deployment.requests.cpu }} diff --git a/maestro/server/helm/values.yaml b/maestro/server/helm/values.yaml index c23d15478..e8d1ec861 100644 --- a/maestro/server/helm/values.yaml +++ b/maestro/server/helm/values.yaml @@ -11,16 +11,17 @@ broker: port: 8883 database: containerizedDb: false - containerizedDbImage: docker.io/library/postgres:14.2 - containerizedDbPvcCapacity: 512Mi - host: "maestro-db" + containerizedDbImage: "" + containerizedDbPvcCapacity: "" + host: "" port: 5432 name: "maestro" - user: "maestro" - password: "TheBlurstOfTimes" - ssl: "require" + user: "maestro-server" + password: "" + ssl: "" maxOpenConnections: 50 debug: false + authMethod: "" maestro: serviceAccount: maestro httpReadTimeout: 60s diff --git a/maestro/server/pipeline.yaml b/maestro/server/pipeline.yaml new file mode 100644 index 000000000..0f6a4eeb1 --- /dev/null +++ b/maestro/server/pipeline.yaml @@ -0,0 +1,52 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Maestro.Server +rolloutName: Maestro Server Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: EVENTGRID_NAME + configRef: maestro.eventGrid.name + - name: REGION_RG + configRef: regionRG + - name: SVC_RG + configRef: svc.rg + - name: AKS_NAME + configRef: aksName + - name: IMAGE_BASE + configRef: maestro.imageBase + - name: IMAGE_TAG + configRef: maestro.imageTag + - name: USE_AZURE_DB + configRef: maestro.postgres.deploy + - name: DATABASE_SERVER_NAME + configRef: maestro.postgres.name + - name: DATABASE_NAME + configRef: maestro.postgres.databaseName + - name: ISTIO_RESTRICT_INGRESS + configRef: maestro.restrictIstioIngress + - name: KEYVAULT_NAME + configRef: serviceKeyVault.name + - name: MQTT_CLIENT_NAME + configRef: maestro.server.mqttClientName + - name: ISTO_TAG + configRef: svc.istio.tag + - name: NAMESPACE + configRef: maestro.server.k8s.namespace + - name: SERVICE_ACCOUNT_NAME + configRef: maestro.server.k8s.serviceAccountName + - name: MANAGED_IDENTITY_NAME + configRef: maestro.server.managedIdentityName + - name: CS_NAMESPACE + configRef: clusterService.k8s.namespace + - name: CS_SERVICE_ACCOUNT_NAME + configRef: clusterService.k8s.serviceAccountName diff --git a/metrics/Makefile b/metrics/Makefile index 1d8bebccb..83f2ebfd1 100644 --- a/metrics/Makefile +++ b/metrics/Makefile @@ -1,7 +1,9 @@ +-include ../setup-env.mk + deploy: deploy-config deploy-config: - kubectl apply -k overlays/svc-cluster + kubectl apply ${KUBECTL_DRY_RUN} -k overlays/svc-cluster undeploy-config: kubectl delete -k overlays/svc-cluster diff --git a/metrics/overlays/svc-cluster/envoy-stats.podmonitor.yml b/metrics/overlays/svc-cluster/envoy-stats.podmonitor.yml new file mode 100644 index 000000000..ed97fa399 --- /dev/null +++ b/metrics/overlays/svc-cluster/envoy-stats.podmonitor.yml @@ -0,0 +1,20 @@ +apiVersion: azmonitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: envoy-stats +spec: + jobLabel: app + # The following limits - labelLimit, labelNameLengthLimit and labelValueLengthLimit should exist in the pod monitor CR + # These ensure that the metrics don't get dropped because labels/labelnames/labelvalues exceed the limits supported by the processing pipeline + labelLimit: 63 + labelNameLengthLimit: 511 + labelValueLengthLimit: 1023 + selector: + matchLabels: + security.istio.io/tlsMode: istio + namespaceSelector: + any: true + podMetricsEndpoints: + - interval: 15s + path: /stats/prometheus + port: http-envoy-prom diff --git a/metrics/overlays/svc-cluster/istiod.servicemonitor.yml b/metrics/overlays/svc-cluster/istiod.servicemonitor.yml new file mode 100644 index 000000000..182158d3f --- /dev/null +++ b/metrics/overlays/svc-cluster/istiod.servicemonitor.yml @@ -0,0 +1,23 @@ +apiVersion: azmonitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: istiod +spec: + jobLabel: app + # The following limits - labelLimit, labelNameLengthLimit and labelValueLengthLimit should exist in the pod monitor CR + # These ensure that the metrics don't get dropped because labels/labelnames/labelvalues exceed the limits supported by the processing pipeline + labelLimit: 63 + labelNameLengthLimit: 511 + labelValueLengthLimit: 1023 + selector: + matchExpressions: + - key: app + operator: In + values: + - istiod + namespaceSelector: + matchNames: + - aks-istio-system + endpoints: + - interval: 15s + port: http-monitoring diff --git a/metrics/overlays/svc-cluster/kustomization.yml b/metrics/overlays/svc-cluster/kustomization.yml index baec80bc0..ad1e6618b 100644 --- a/metrics/overlays/svc-cluster/kustomization.yml +++ b/metrics/overlays/svc-cluster/kustomization.yml @@ -1,5 +1,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - prometheus-config.yml + - envoy-stats.podmonitor.yml + - istiod.servicemonitor.yml namespace: kube-system diff --git a/metrics/overlays/svc-cluster/prometheus-config.yml b/metrics/overlays/svc-cluster/prometheus-config.yml deleted file mode 100644 index ba8ddd397..000000000 --- a/metrics/overlays/svc-cluster/prometheus-config.yml +++ /dev/null @@ -1,30 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -data: - prometheus-config: |- - global: - scrape_interval: 15s - scrape_configs: - # scrape sidecar proxies and gateway proxies - - job_name: 'envoy-stats' - metrics_path: /stats/prometheus - kubernetes_sd_configs: - - role: pod - relabel_configs: - - source_labels: [__meta_kubernetes_pod_container_port_name] - action: keep - regex: '.*-envoy-prom' - - - job_name: 'istiod' - kubernetes_sd_configs: - - role: endpoints - namespaces: - names: - - aks-istio-system - relabel_configs: - - source_labels: [__meta_kubernetes_endpoints_label_app, __meta_kubernetes_endpoint_port_name] - action: keep - regex: istiod;http-monitoring -metadata: - name: ama-metrics-prometheus-config - namespace: kube-system diff --git a/metrics/pipeline.yaml b/metrics/pipeline.yaml new file mode 100644 index 000000000..215c089ff --- /dev/null +++ b/metrics/pipeline.yaml @@ -0,0 +1,15 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.Metrics +rolloutName: RP Metrics Rollout +resourceGroups: +- name: {{ .svc.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: KUBECTL_DRY_RUN + value: "--dry-run=client -o yaml" diff --git a/mgmt-fixes/Makefile b/mgmt-fixes/Makefile new file mode 100644 index 000000000..29926e86e --- /dev/null +++ b/mgmt-fixes/Makefile @@ -0,0 +1,12 @@ +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install + +deploy: + ${HELM_CMD} mgmt-fixes \ + deploy/helm/mgmt-fixes/ +.PHONY: deploy + +undeploy: + helm uninstall mgmt-fixes +.PHONY: undeploy diff --git a/mgmt-fixes/README.md b/mgmt-fixes/README.md new file mode 100644 index 000000000..1c3b8e889 --- /dev/null +++ b/mgmt-fixes/README.md @@ -0,0 +1,8 @@ +# Fixes for Management Clusters + +Any changes to management clusters that are needed +but can't be applied using AKS configuration +go here. +Ideally anything here is treated as temporary +and always ends up getting upstreamed. + diff --git a/mgmt-fixes/deploy/helm/mgmt-fixes/Chart.yaml b/mgmt-fixes/deploy/helm/mgmt-fixes/Chart.yaml new file mode 100644 index 000000000..e8df69b8b --- /dev/null +++ b/mgmt-fixes/deploy/helm/mgmt-fixes/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: Fixes +description: Any fixes that need to be applied but have not (yet) been upstreamed +version: 0.1.0 +appVersion: "0.1.0" diff --git a/mgmt-fixes/deploy/helm/mgmt-fixes/templates/ds-kubelet-parameters.yaml b/mgmt-fixes/deploy/helm/mgmt-fixes/templates/ds-kubelet-parameters.yaml new file mode 100644 index 000000000..d7b0bdda5 --- /dev/null +++ b/mgmt-fixes/deploy/helm/mgmt-fixes/templates/ds-kubelet-parameters.yaml @@ -0,0 +1,77 @@ +# Alter kubelet config for better stability at higher scales +# Ref: https://issues.redhat.com/browse/ARO-13357 +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + component: kubelet-parameters + name: set-kubelet-parameters-for-scale + namespace: kube-system +spec: + revisionHistoryLimit: 10 + selector: + matchLabels: + component: kubelet-parameters + tier: node + template: + metadata: + creationTimestamp: null + labels: + component: kubelet-parameters + tier: node + spec: + containers: + - command: + - nsenter + - --target + - "1" + - --mount + - --uts + - --ipc + - --net + - --pid + - -- + - sh + - -c + - | + if cat /etc/default/kubelet | grep -q '\-\-system-reserved=cpu=3000m,memory=7550Mi,pid=1000';then + echo "kube-reserved parameter already updated to system-reserved in kubelet configuration" + else + sed -i -E 's/--kube-reserved=[^ ]+/--system-reserved=cpu=3000m,memory=7550Mi,pid=1000/g' /etc/default/kubelet + systemctl daemon-reload + systemctl restart kubelet + echo "kube-reserved parameter has been updated to system-reserved in kubelet configuration" + fi + if grep -q '\-\-collector.netclass.netlink' /usr/local/bin/node-exporter-startup.sh;then + echo "collector.netclass.netlink parameter already updated in node-exporter configuration" + else + sed -i 's/--no-collector.arp.netlink/--no-collector.arp.netlink --collector.netclass.netlink/g' /usr/local/bin/node-exporter-startup.sh + systemctl daemon-reload + systemctl restart node-exporter + echo "collector.netclass.netlink parameter has been updated in node-exporter configuration" + fi + sleep infinity + image: alpine + imagePullPolicy: IfNotPresent + name: kubelet-parameters + resources: + requests: + cpu: 10m + securityContext: + privileged: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + hostPID: true + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + tolerations: + - effect: NoSchedule + operator: Exists + updateStrategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + type: RollingUpdate diff --git a/mgmt-fixes/deploy/helm/mgmt-fixes/values.yaml b/mgmt-fixes/deploy/helm/mgmt-fixes/values.yaml new file mode 100644 index 000000000..08a1c1568 --- /dev/null +++ b/mgmt-fixes/deploy/helm/mgmt-fixes/values.yaml @@ -0,0 +1 @@ +# This file is intentionally left blank. diff --git a/mgmt-fixes/pipeline.yaml b/mgmt-fixes/pipeline.yaml new file mode 100644 index 000000000..b65bda71a --- /dev/null +++ b/mgmt-fixes/pipeline.yaml @@ -0,0 +1,15 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.Management.Fixes +rolloutName: Fixes for management clusters +resourceGroups: + - name: {{ .mgmt.rg }} + subscription: {{ .mgmt.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" diff --git a/pko/Makefile b/pko/Makefile index f31fac90e..939927fec 100644 --- a/pko/Makefile +++ b/pko/Makefile @@ -1,6 +1,37 @@ -SHELL = /bin/bash +-include ../setup-env.mk +-include ../helm-cmd.mk +HELM_CMD ?= helm upgrade --install + +NAMESPACE ?= package-operator-system +ARO_HCP_IMAGE_REGISTRY ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io +ARO_HCP_IMAGE_REPOSITORY ?= package-operator/package-operator-package deploy: - oc apply -f https://github.com/package-operator/package-operator/releases/download/v1.11.0/self-bootstrap-job.yaml + @kubectl create namespace ${NAMESPACE} --dry-run=client -o json | kubectl apply -f - + IMAGE_PULLER_MI_CLIENT_ID=$$(az identity show \ + -g ${RESOURCEGROUP} \ + -n image-puller \ + --query clientId -o tsv) && \ + IMAGE_PULLER_MI_TENANT_ID=$$(az identity show \ + -g ${RESOURCEGROUP} \ + -n image-puller \ + --query tenantId -o tsv) && \ + ${HELM_CMD} package-operator ./helm \ + --namespace ${NAMESPACE} \ + --set pkoImage=${PKO_IMAGE} \ + --set pkoImageManager=${PKO_IMAGE_MANAGER} \ + --set pkoImageTag=${PKO_IMAGE_TAG} \ + --set pullBinding.workloadIdentityClientId="$${IMAGE_PULLER_MI_CLIENT_ID}" \ + --set pullBinding.workloadIdentityTenantId="$${IMAGE_PULLER_MI_TENANT_ID}" \ + --set pullBinding.registry=${ARO_HCP_IMAGE_REGISTRY} \ + --set pullBinding.scope='repository:*:pull' + +image: + az acr login --name ${ARO_HCP_IMAGE_ACR} && \ + cd $$(mktemp -d) && \ + git clone https://github.com/package-operator/package-operator.git && \ + cd package-operator && \ + git checkout ${PKO_IMAGE_TAG} && \ + IMAGE_REGISTRY=${ARO_HCP_IMAGE_REGISTRY}/package-operator ./do ci:release .PHONY: deploy diff --git a/pko/helm/Chart.yaml b/pko/helm/Chart.yaml new file mode 100644 index 000000000..1c2dbeb91 --- /dev/null +++ b/pko/helm/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: package-operator +description: A Helm chart for package-operator +type: application + +version: 0.1.0 +appVersion: "1.0.0" diff --git a/pko/helm/templates/acrpullbinding.yaml b/pko/helm/templates/acrpullbinding.yaml new file mode 100644 index 000000000..2bbc27f6c --- /dev/null +++ b/pko/helm/templates/acrpullbinding.yaml @@ -0,0 +1,15 @@ +apiVersion: acrpull.microsoft.com/v1beta2 +kind: AcrPullBinding +metadata: + name: pull-binding +spec: + acr: + environment: PublicCloud + server: {{ .Values.pullBinding.registry }} + scope: {{ .Values.pullBinding.scope }} + auth: + workloadIdentity: + serviceAccountRef: package-operator + clientID: {{ .Values.pullBinding.workloadIdentityClientId }} + tenantID: {{ .Values.pullBinding.workloadIdentityTenantId }} + serviceAccountName: package-operator diff --git a/hypershiftoperator/deploy/base/clusterrolebinding-external-dns.yaml b/pko/helm/templates/clusterrolebinding.yaml similarity index 52% rename from hypershiftoperator/deploy/base/clusterrolebinding-external-dns.yaml rename to pko/helm/templates/clusterrolebinding.yaml index 9b736ccb3..cb88410f5 100644 --- a/hypershiftoperator/deploy/base/clusterrolebinding-external-dns.yaml +++ b/pko/helm/templates/clusterrolebinding.yaml @@ -1,13 +1,14 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - creationTimestamp: null - name: external-dns -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: external-dns -subjects: -- kind: ServiceAccount - name: external-dns - namespace: hypershift +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: package-operator + labels: + package-operator.run/cache: "True" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: package-operator + namespace: package-operator-system diff --git a/pko/helm/templates/job.yaml b/pko/helm/templates/job.yaml new file mode 100644 index 000000000..c1f21a6c4 --- /dev/null +++ b/pko/helm/templates/job.yaml @@ -0,0 +1,37 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: package-operator-bootstrap + namespace: package-operator-system +spec: + # delete right after completion + ttlSecondsAfterFinished: 0 + # set deadline to 30min + activeDeadlineSeconds: 1800 + template: + spec: + restartPolicy: OnFailure + serviceAccountName: package-operator + containers: + - name: package-operator + image: "{{ .Values.pkoImageManager }}:{{ .Values.pkoImageTag }}" + args: ["-self-bootstrap={{ .Values.pkoImage }}:{{ .Values.pkoImageTag }}"] + imagePullPolicy: Always + env: + - name: PKO_REGISTRY_HOST_OVERRIDES + value: '' + - name: PKO_CONFIG + value: '' + - name: PKO_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: PKO_SERVICE_ACCOUNT_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: PKO_SERVICE_ACCOUNT_NAME + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + backoffLimit: 3 diff --git a/pko/helm/templates/serviceaccount.yaml b/pko/helm/templates/serviceaccount.yaml new file mode 100644 index 000000000..555b9c2a6 --- /dev/null +++ b/pko/helm/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: package-operator + namespace: package-operator-system + labels: + package-operator.run/cache: "True" diff --git a/pko/helm/values.yaml b/pko/helm/values.yaml new file mode 100644 index 000000000..5f787db42 --- /dev/null +++ b/pko/helm/values.yaml @@ -0,0 +1,8 @@ +pkoImage: "" +pkoImageManager: "" +pkoImageTag: "" +pullBinding: + registry: "" + scope: "" + workloadIdentityClientId: "" + workloadIdentityTenantId: "" diff --git a/pko/pipeline.yaml b/pko/pipeline.yaml new file mode 100644 index 000000000..69062c076 --- /dev/null +++ b/pko/pipeline.yaml @@ -0,0 +1,26 @@ +$schema: "pipeline.schema.v1" +serviceGroup: Microsoft.Azure.ARO.HCP.RP.PKO +rolloutName: RP PKO Rollout +resourceGroups: +- name: {{ .mgmt.rg }} + subscription: {{ .svc.subscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "true" + variables: + - name: ARO_HCP_IMAGE_ACR + configRef: svcAcrName + - name: PKO_IMAGE + configRef: pko.image + - name: PKO_IMAGE_MANAGER + configRef: pko.imageManager + - name: PKO_IMAGE_TAG + configRef: pko.imageTag + - name: RESOURCEGROUP + configRef: mgmt.rg diff --git a/setup-env.mk b/setup-env.mk new file mode 100644 index 000000000..25c877cc0 --- /dev/null +++ b/setup-env.mk @@ -0,0 +1,24 @@ +SHELL = /bin/bash +SHELLFLAGS = -eu -o pipefail + +ifndef EV2 +ifndef RUNS_IN_TEMPLATIZE +PROJECT_ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +DEPLOY_ENV ?= personal-dev +PIPELINE ?= pipeline.yaml +PIPELINE_STEP ?= deploy +HASH = $(shell echo -n "$(DEPLOY_ENV)$(PIPELINE)$(PIPELINE_STEP)$(PWD)" | sha256sum | cut -d " " -f 1) +ENV_VARS_FILE ?= /tmp/deploy.${HASH}.cfg + +# Target to generate the environment variables file +$(ENV_VARS_FILE): ${PROJECT_ROOT_DIR}/config/config.yaml ${PIPELINE} ${PROJECT_ROOT_DIR}/templatize.sh ${MAKEFILE_LIST} + @echo "generate env vars file ${ENV_VARS_FILE}" + @${PROJECT_ROOT_DIR}/templatize.sh ${DEPLOY_ENV} \ + -p ${PIPELINE} \ + -s ${PIPELINE_STEP} > $(ENV_VARS_FILE) + +# Include the environment variables file if it exists +-include ${ENV_VARS_FILE} +endif +endif diff --git a/svc-deploy.sh b/svc-deploy.sh index c71af31d5..0aeb109fe 100755 --- a/svc-deploy.sh +++ b/svc-deploy.sh @@ -1,23 +1,29 @@ #!/bin/bash +# bash will report what is happening and stop in case of non zero return code +set -xe + # deploy a service to a cluster # ./svc-deploy [target] # this script expects the to contain a Makefile that takes care # of processing any config.mk template on its own -cd $(dirname "$(realpath "${BASH_SOURCE[0]}")") || exit +cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")" export DEPLOY_ENV=$1 export DIR=$2 export CLUSTER=$3 export TARGET=${4:-deploy} -if [[ "$CLUSTER" != "svc" && "$CLUSTER" != "mgmt" ]]; then - echo "Error: CLUSTER must be either 'svc' or 'mgmt'." +if [[ "${CLUSTER}" != "svc" && "${CLUSTER}" != "mgmt" ]]; then + echo "Error: CLUSTER must be either 'svc' or 'mgmt'." >&2 exit 1 fi -export KUBECONFIG=$(cd dev-infrastructure || exit ; make --no-print-directory $CLUSTER.aks.kubeconfigfile) +cd dev-infrastructure +KUBECONFIG=$(make --no-print-directory "${CLUSTER}.aks.kubeconfigfile") +export KUBECONFIG +cd - -cd ${DIR} || exit -make $TARGET +cd "${DIR}" +make "${TARGET}" diff --git a/templatize.sh b/templatize.sh index 31a023a92..881d3ba17 100755 --- a/templatize.sh +++ b/templatize.sh @@ -7,6 +7,8 @@ CLOUD="${CLOUD:-public}" REGION="${REGION:-westus3}" CXSTAMP="${CXSTAMP:-1}" EXTRA_ARGS="" +PIPELINE_MODE="inspect" +DRY_RUN="" # Function to display usage usage() { @@ -14,10 +16,15 @@ usage() { echo " deploy_env Deployment environment" echo " input Optional input file" echo " output Optional output file" + echo " -d Dry run" + echo " -i Set the input file same as second arg" + echo " -o Set the output file same as third arg" echo " -c Set the cloud (default: public)" echo " -r Set the region (default: westus3)" echo " -x Set the cxstamp (default: 1)" echo " -e Extra args for config interpolation" + echo " -p Pipeline to inspect" + echo " -s Pipeline step to inspect" exit 1 } @@ -41,11 +48,14 @@ if [ "$#" -ge 1 ] && [[ ! "$1" =~ ^- ]]; then fi # Parse optional flags -while getopts "c:r:x:e:" opt; do +while getopts "c:dr:x:e:i:o:p:P:s:" opt; do case ${opt} in c) CLOUD=${OPTARG} ;; + d) + DRY_RUN="--dry-run" + ;; r) REGION=${OPTARG} ;; @@ -55,42 +65,127 @@ while getopts "c:r:x:e:" opt; do e) EXTRA_ARGS="--extra-args ${OPTARG}" ;; + i) + INPUT=${OPTARG} + ;; + o) + OUTPUT=${OPTARG} + ;; + p) + PIPELINE=${OPTARG} + ;; + P) + PIPELINE_MODE=${OPTARG} + ;; + s) + PIPELINE_STEP=${OPTARG} + ;; *) usage ;; esac done +# short names from EV2 prod ServiceConfig +case ${REGION} in + eastus) + REGION_SHORT="use" + ;; + westus) + REGION_SHORT="usw" + ;; + centralus) + REGION_SHORT="usc" + ;; + northcentralus) + REGION_SHORT="usnc" + ;; + southcentralus) + REGION_SHORT="ussc" + ;; + westus2) + REGION_SHORT="usw2" + ;; + westus3) + REGION_SHORT="usw3" + ;; + uksouth) + REGION_SHORT="ln" + ;; + *) + echo "unsupported region: ${REGION}" + exit 1 +esac + if [ "$DEPLOY_ENV" == "personal-dev" ]; then - REGION_STAMP=${USER} + REGION_STAMP="${REGION_SHORT}${USER:0:4}" else - REGION_STAMP=${DEPLOY_ENV} + CLEAN_DEPLOY_ENV=$(echo "${DEPLOY_ENV}" | tr -cd '[:alnum:]') + REGION_STAMP="${CLEAN_DEPLOY_ENV}" fi -TEMPLATIZE=${PROJECT_ROOT_DIR}/tooling/templatize/templatize -if [ ! -f "${TEMPLATIZE}" ] || [ -n "${REBUILD_TEMPLATIZE}" ]; then - go build -o "$TEMPLATIZE" ${PROJECT_ROOT_DIR}/tooling/templatize +make -s -C ${PROJECT_ROOT_DIR}/tooling/templatize templatize +TEMPLATIZE="${PROJECT_ROOT_DIR}/tooling/templatize/templatize" + +PERSIST_FLAG="" +if [ -z "$PERSIST" ] || [ "$PERSIST" == "false" ]; then + PERSIST_FLAG="--no-persist-tag" fi -CONFIG_FILE=${PROJECT_ROOT_DIR}/config/config.yaml +CONFIG_FILE=${CONFIG_FILE:-${PROJECT_ROOT_DIR}/config/config.yaml} if [ -n "$INPUT" ] && [ -n "$OUTPUT" ]; then $TEMPLATIZE generate \ --config-file=${CONFIG_FILE} \ --cloud=${CLOUD} \ --deploy-env=${DEPLOY_ENV} \ --region=${REGION} \ - --region-stamp=${REGION_STAMP} \ - --cx-stamp=${CXSTAMP} \ + --region-short=${REGION_STAMP} \ + --stamp=${CXSTAMP} \ --input=${INPUT} \ --output=${OUTPUT} \ ${EXTRA_ARGS} +elif [ $PIPELINE_MODE == "inspect" ] && [ -n "$PIPELINE" ] && [ -n "$PIPELINE_STEP" ]; then + $TEMPLATIZE pipeline inspect \ + --config-file=${CONFIG_FILE} \ + --cloud=${CLOUD} \ + --deploy-env=${DEPLOY_ENV} \ + --region=${REGION} \ + --region-short=${REGION_STAMP} \ + --stamp=${CXSTAMP} \ + --pipeline-file=${PIPELINE} \ + --step=${PIPELINE_STEP} \ + --scope vars \ + --format makefile +elif [ $PIPELINE_MODE == "run" ] && [ -n "$PIPELINE" ] && [ -n "$PIPELINE_STEP" ]; then + $TEMPLATIZE pipeline run \ + --config-file=${CONFIG_FILE} \ + --cloud=${CLOUD} \ + --deploy-env=${DEPLOY_ENV} \ + --region=${REGION} \ + --region-short=${REGION_STAMP} \ + --stamp=${CXSTAMP} \ + --pipeline-file=${PIPELINE} \ + --step=${PIPELINE_STEP} \ + ${PERSIST_FLAG} \ + ${DRY_RUN} +elif [ $PIPELINE_MODE == "run" ] && [ -n "$PIPELINE" ]; then + $TEMPLATIZE pipeline run \ + --config-file=${CONFIG_FILE} \ + --cloud=${CLOUD} \ + --deploy-env=${DEPLOY_ENV} \ + --region=${REGION} \ + --region-short=${REGION_STAMP} \ + --stamp=${CXSTAMP} \ + --pipeline-file=${PIPELINE} \ + ${PERSIST_FLAG} \ + ${DRY_RUN} else $TEMPLATIZE inspect \ --config-file=${CONFIG_FILE} \ --cloud=${CLOUD} \ --deploy-env=${DEPLOY_ENV} \ --region=${REGION} \ - --region-stamp=${REGION_STAMP} \ - --cx-stamp=${CXSTAMP} \ + --region-short=${REGION_STAMP} \ + --stamp=${CXSTAMP} \ ${EXTRA_ARGS} fi diff --git a/tooling/azure-automation/github-actions/hack/create-application.sh b/tooling/azure-automation/github-actions/hack/create-application.sh index a4f9ceb43..0c2a97fc6 100755 --- a/tooling/azure-automation/github-actions/hack/create-application.sh +++ b/tooling/azure-automation/github-actions/hack/create-application.sh @@ -20,6 +20,7 @@ OBJ_ID=$(az ad sp create --id $APP_ID | jq -r '.id') # Create role assignment and federate credentials az role assignment create --assignee "${OBJ_ID}" --role Contributor --scope /subscriptions/${SUBSCRIPTION} az role assignment create --assignee "${OBJ_ID}" --role "Role Based Access Control Administrator" --scope /subscriptions/${SUBSCRIPTION} +az role assignment create --assignee "${OBJ_ID}" --role "Grafana Admin" --scope /subscriptions/${SUBSCRIPTION} az ad app federated-credential create --id "${APP_ID}" --parameters \ '{ diff --git a/tooling/azure-automation/resources-cleanup/requirements.txt b/tooling/azure-automation/resources-cleanup/requirements.txt index 54c2e3990..288fc1819 100644 --- a/tooling/azure-automation/resources-cleanup/requirements.txt +++ b/tooling/azure-automation/resources-cleanup/requirements.txt @@ -19,7 +19,7 @@ portalocker==2.8.2 pycparser==2.21 PyJWT==2.8.0 pytest==7.4.4 -requests==2.32.0 +requests==2.32.3 six==1.16.0 tomli==2.0.1 typing_extensions==4.9.0 diff --git a/tooling/azure-automation/resources-cleanup/src/resources_cleanup.py b/tooling/azure-automation/resources-cleanup/src/resources_cleanup.py index 5a7b00f45..3fb135541 100644 --- a/tooling/azure-automation/resources-cleanup/src/resources_cleanup.py +++ b/tooling/azure-automation/resources-cleanup/src/resources_cleanup.py @@ -120,10 +120,10 @@ def process_resource_group(resource_group: ResourceGroup, resource_client: Resou result_poller = resource_client.resource_groups.begin_delete(resource_group_name) print(f"result_poller of resource group deletion: {result_poller}") except HttpResponseError as err: - target_error_code = "DenyAssignmentAuthorizationFailed" - if err.error.code == target_error_code: - print("skipping deletion of resource group due to deny assignment in the resource group") - else: + error_codes = ("DenyAssignmentAuthorizationFailed", "ScopeLocked") + if err.error.code in error_codes: + print(f"skipping deletion of resource group due to error code {err.error.code}") + else: raise err diff --git a/tooling/image-sync/Dockerfile b/tooling/image-sync/Dockerfile index 4a2e64e0a..a40ae2c8a 100644 --- a/tooling/image-sync/Dockerfile +++ b/tooling/image-sync/Dockerfile @@ -1,11 +1,11 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:6c1b07df15c152fb6a7f4eeece5f50824d83b8bf672709cc951aaa0d5c29887f as builder +FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-cbl-mariner2.0@sha256:e6951a34cc0cbdc62b5110c4301dfe9c8daf8ee89c1b8616082a6e0b89cd820f as builder WORKDIR /app ADD . . # https://github.com/microsoft/go/tree/microsoft/main/eng/doc/fips#build-option-to-require-fips-mode RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags=containers_image_openpgp,requirefips . -FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:acb1ab4d2162ecebbe67888bf679f26dcaef29c153954a09396e020e9639862d +FROM --platform=linux/amd64 mcr.microsoft.com/cbl-mariner/distroless/base:2.0-nonroot@sha256:ce44fc29db88c9aba8041a50c1abcd19a54f997c2b99a8c513e8ec113261374a WORKDIR / COPY --from=builder /app/image-sync . diff --git a/tooling/image-sync/README.md b/tooling/image-sync/README.md index e77193039..7bb9fa21b 100644 --- a/tooling/image-sync/README.md +++ b/tooling/image-sync/README.md @@ -10,18 +10,21 @@ The main configuration looks like this: repositories: - registry.k8s.io/external-dns/external-dns numberOfTags: 3 -quaySecretfile: /var/run/quay-secret.json -acrRegistry: someregistry.azurecr.io +acrTargetRegistry: someregistry.azurecr.io tenantId: 1ab61791-4b66-4ea4-85ff-aa2c0bf37e57 +secrets: + - registry: registry.k8s.io + secretFile: /secret.txt ``` Explanation: - `repositories` - list of repositories to sync. Do not specify tags, since this utility will sync only the latest tags. - `numberOfTags` - number of tags to sync. The utility will sync the latest `numberOfTags` tags. - `quaySecretfile` - path to the secret file for the Quay registry. -- `acrRegistry` - the target registry. +- `acrTargetRegistry` - the target registry. - `tenantId` - the tenant ID used for authentication with Azure. - `RequestTimeout` - the timeout for the HTTP requests. Default is 10 seconds. +- `secrets` - Array of secrets used for API authentitcation ### quaySecretfile diff --git a/tooling/image-sync/config.tmpl.mk b/tooling/image-sync/config.tmpl.mk index e38b7290e..e82b4c19d 100644 --- a/tooling/image-sync/config.tmpl.mk +++ b/tooling/image-sync/config.tmpl.mk @@ -1,3 +1,3 @@ ARO_HCP_IMAGE_ACR ?= {{ .svcAcrName }} ARO_HCP_BASE_IMAGE ?= ${ARO_HCP_IMAGE_ACR}.azurecr.io -ARO_HCP_IMAGE_SYNC_IMAGE ?= $(ARO_HCP_BASE_IMAGE)/{{ .imageSyncImageRepo }} +ARO_HCP_IMAGE_SYNC_IMAGE ?= $(ARO_HCP_BASE_IMAGE)/{{ .imageSync.componentSync.imageRepo }} diff --git a/tooling/image-sync/example.yml b/tooling/image-sync/example.yml index 5d301b313..43a19024d 100644 --- a/tooling/image-sync/example.yml +++ b/tooling/image-sync/example.yml @@ -1,8 +1,9 @@ repositories: - registry.k8s.io/external-dns/external-dns - - quay.io/acm-d/rhtap-hypershift-operator - - quay.io/app-sre/uhc-clusters-service -numberOfTags: 40 -quaySecretfile: /home/jboll/workspace/opensource/quay-secret.json -acrRegistry: testing.azurecr.io + - testingone.azurecr.io/azure-cli +numberOfTags: 2 +acrTargetRegistry: testingtrgt.azurecr.io tenantId: 64dc69e4-d083-49fc-9569-ebece1dd1408 +secrets: + - registry: testingone.azurecr.io + azureSecretfile: /home/jboll/workspace/opensource/other-secret.json diff --git a/tooling/image-sync/go.mod b/tooling/image-sync/go.mod index b22618917..1e98b1d96 100644 --- a/tooling/image-sync/go.mod +++ b/tooling/image-sync/go.mod @@ -3,10 +3,10 @@ module github.com/Azure/ARO-HCP/tooling/image-sync go 1.23.0 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.2 - github.com/containers/image/v5 v5.32.2 + github.com/containers/image/v5 v5.33.0 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 go.uber.org/zap v1.27.0 @@ -14,7 +14,6 @@ require ( ) require ( - dario.cat/mergo v1.0.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/BurntSushi/toml v1.4.0 // indirect @@ -23,16 +22,16 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.0 // indirect - github.com/containers/storage v1.55.0 // indirect + github.com/containers/storage v1.56.0 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/docker v27.3.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-openapi/analysis v0.23.0 // indirect github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -46,25 +45,26 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-containerregistry v0.20.0 // indirect + github.com/google/go-containerregistry v0.20.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/letsencrypt/boulder v0.0.0-20240418210053-89b07f4543e0 // indirect + github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/sys/capability v0.3.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect - github.com/moby/sys/user v0.2.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/oklog/ulid v1.3.1 // indirect @@ -75,14 +75,13 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/proglottis/gpgme v0.1.3 // indirect github.com/prometheus/client_golang v1.20.4 // indirect - github.com/prometheus/client_model v0.6.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect - github.com/sigstore/fulcio v1.4.5 // indirect + github.com/sigstore/fulcio v1.6.4 // indirect github.com/sigstore/rekor v1.3.6 // indirect - github.com/sigstore/sigstore v1.8.4 // indirect + github.com/sigstore/sigstore v1.8.9 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -90,23 +89,22 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/ulikunitz/xz v0.5.12 // indirect - github.com/vbatts/tar-split v0.11.5 // indirect - github.com/vbauerster/mpb/v8 v8.7.5 // indirect + github.com/vbatts/tar-split v0.11.6 // indirect + github.com/vbauerster/mpb/v8 v8.8.3 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/grpc v1.64.1 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.67.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tooling/image-sync/go.sum b/tooling/image-sync/go.sum index 7c4dacbfd..100f33300 100644 --- a/tooling/image-sync/go.sum +++ b/tooling/image-sync/go.sum @@ -1,7 +1,7 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= @@ -28,14 +28,14 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containers/image/v5 v5.32.2 h1:SzNE2Y6sf9b1GJoC8qjCuMBXwQrACFp4p0RK15+4gmQ= -github.com/containers/image/v5 v5.32.2/go.mod h1:v1l73VeMugfj/QtKI+jhYbwnwFCFnNGckvbST3rQ5Hk= +github.com/containers/image/v5 v5.33.0 h1:6oPEFwTurf7pDTGw7TghqGs8K0+OvPtY/UyzU0B2DfE= +github.com/containers/image/v5 v5.33.0/go.mod h1:T7HpASmvnp2H1u4cyckMvCzLuYgpD18dSmabSw0AcHk= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= -github.com/containers/storage v1.55.0 h1:wTWZ3YpcQf1F+dSP4KxG9iqDfpQY1otaUXjPpffuhgg= -github.com/containers/storage v1.55.0/go.mod h1:28cB81IDk+y7ok60Of6u52RbCeBRucbFOeLunhER1RQ= +github.com/containers/storage v1.56.0 h1:DZ9KSkj6M2tvj/4bBoaJu3QDHRl35BwsZ4kmLJS97ZI= +github.com/containers/storage v1.56.0/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= @@ -47,12 +47,12 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 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/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= +github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= -github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -65,8 +65,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 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/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= -github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= @@ -87,16 +87,16 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 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-containerregistry v0.20.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg= -github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= @@ -114,8 +114,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -124,24 +124,26 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/letsencrypt/boulder v0.0.0-20240418210053-89b07f4543e0 h1:aiPrFdHDCCvigNBCkOWj2lv9Bx5xDp210OANZEoiP0I= -github.com/letsencrypt/boulder v0.0.0-20240418210053-89b07f4543e0/go.mod h1:srVwm2N3DC/tWqQ+igZXDrmKlNRN8X/dmJ1wEZrv760= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ= +github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg= +github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= -github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM= -github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= 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= @@ -172,8 +174,8 @@ github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zI github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY= +github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= @@ -190,12 +192,12 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= -github.com/sigstore/fulcio v1.4.5 h1:WWNnrOknD0DbruuZWCbN+86WRROpEl3Xts+WT2Ek1yc= -github.com/sigstore/fulcio v1.4.5/go.mod h1:oz3Qwlma8dWcSS/IENR/6SjbW4ipN0cxpRVfgdsjMU8= +github.com/sigstore/fulcio v1.6.4 h1:d86obfxUAG3Y6CYwOx1pdwCZwKmROB6w6927pKOVIRY= +github.com/sigstore/fulcio v1.6.4/go.mod h1:Y6bn3i3KGhXpaHsAtYP3Z4Np0+VzCo1fLv8Ci6mbPDs= github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8= github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc= -github.com/sigstore/sigstore v1.8.4 h1:g4ICNpiENFnWxjmBzBDWUn62rNFeny/P77HUC8da32w= -github.com/sigstore/sigstore v1.8.4/go.mod h1:1jIKtkTFEeISen7en+ZPWdDHazqhxco/+v9CNjc7oNg= +github.com/sigstore/sigstore v1.8.9 h1:NiUZIVWywgYuVTxXmRoTT4O4QAGiTEKup4N1wdxFadk= +github.com/sigstore/sigstore v1.8.9/go.mod h1:d9ZAbNDs8JJfxJrYmulaTazU3Pwr8uLL9+mii4BNR3w= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -221,20 +223,19 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vbauerster/mpb/v8 v8.7.5 h1:hUF3zaNsuaBBwzEFoCvfuX3cpesQXZC0Phm/JcHZQ+c= -github.com/vbauerster/mpb/v8 v8.7.5/go.mod h1:bRCnR7K+mj5WXKsy0NWB6Or+wctYGvVwKn6huwvxKa0= +github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= +github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= +github.com/vbauerster/mpb/v8 v8.8.3 h1:dTOByGoqwaTJYPubhVz3lO5O6MK553XVgUo33LdnNsQ= +github.com/vbauerster/mpb/v8 v8.8.3/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -251,26 +252,26 @@ 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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= +google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tooling/image-sync/internal/repository.go b/tooling/image-sync/internal/repository.go index 141774d78..a6ca80402 100644 --- a/tooling/image-sync/internal/repository.go +++ b/tooling/image-sync/internal/repository.go @@ -163,13 +163,13 @@ func NewAzureContainerRegistry(cfg *SyncConfig) *AzureContainerRegistry { } } - client, err := azcontainerregistry.NewClient(fmt.Sprintf("https://%s", cfg.AcrRegistry), cred, nil) + client, err := azcontainerregistry.NewClient(fmt.Sprintf("https://%s", cfg.AcrTargetRegistry), cred, nil) if err != nil { Log().Fatalf("failed to create client: %v", err) } return &AzureContainerRegistry{ - acrName: cfg.AcrRegistry, + acrName: cfg.AcrTargetRegistry, acrClient: client, credential: cred, httpClient: &http.Client{Timeout: time.Duration(cfg.RequestTimeout) * time.Second}, @@ -295,18 +295,124 @@ func (a *AzureContainerRegistry) GetTags(ctx context.Context, repository string) return tags, nil } +type ACRWithTokenAuth struct { + httpclient *http.Client + acrName string + numberOftags int + bearerToken string +} + +type AccessSecret struct { + AccessToken string `json:"access_token"` +} + +type rawACRTagResponse struct { + Tags []rawACRTags +} + +type rawACRTags struct { + Name string +} + +func getACRBearerToken(ctx context.Context, secret AzureSecretFile, acrName string) (string, error) { + scope := "repository:*:*" + path := fmt.Sprintf("https://%s/oauth2/token?service=%s&scope=%s", acrName, acrName, scope) + + Log().Debugw("Creating request", "path", path) + req, err := http.NewRequestWithContext(ctx, "GET", path, nil) + req.Header.Add("Authorization", fmt.Sprintf("Basic %s", secret.BasicAuthEncoded())) + if err != nil { + return "", fmt.Errorf("failed to create request: %v", err) + } + + // todo replace with timeout enabled client + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", fmt.Errorf("failed to send request: %v", err) + } + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("unexpected status code %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("failed to read response: %v", err) + } + + var accessSecret AccessSecret + + err = json.Unmarshal(body, &accessSecret) + if err != nil { + return "", fmt.Errorf("failed to unmarshal response: %v", err) + } + + return accessSecret.AccessToken, nil +} + +func NewACRWithTokenAuth(cfg *SyncConfig, acrName string, bearerToken string) *ACRWithTokenAuth { + return &ACRWithTokenAuth{ + httpclient: &http.Client{Timeout: time.Duration(cfg.RequestTimeout) * time.Second}, + acrName: acrName, + bearerToken: bearerToken, + numberOftags: cfg.NumberOfTags, + } +} + +func (n *ACRWithTokenAuth) GetTags(ctx context.Context, image string) ([]string, error) { + Log().Debugw("Getting tags for image", "image", image) + + path := fmt.Sprintf("https://%s/acr/v1/%s/_tags?orderby=%s&n=%d", n.acrName, image, azcontainerregistry.ArtifactTagOrderByLastUpdatedOnDescending, n.numberOftags) + req, err := http.NewRequestWithContext(ctx, "GET", path, nil) + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", n.bearerToken)) + if err != nil { + return nil, fmt.Errorf("failed to create request: %v", err) + } + + Log().Debugw("Sending request", "path", path) + resp, err := n.httpclient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %v", err) + } + Log().Debugw("Got response", "statuscode", resp.StatusCode) + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response: %v", err) + } + + var acrResponse rawACRTagResponse + err = json.Unmarshal(body, &acrResponse) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal response: %v", err) + } + + tagList := make([]string, 0) + + for _, tag := range acrResponse.Tags { + tagList = append(tagList, tag.Name) + } + + return tagList, nil +} + // OCIRegistry implements OCI Repository access type OCIRegistry struct { httpclient *http.Client baseURL string numberOftags int + bearerToken string } // NewOCIRegistry creates a new OCIRegistry access client -func NewOCIRegistry(cfg *SyncConfig, baseURL string) *OCIRegistry { +func NewOCIRegistry(cfg *SyncConfig, baseURL, bearerToken string) *OCIRegistry { o := &OCIRegistry{ httpclient: &http.Client{Timeout: time.Duration(cfg.RequestTimeout) * time.Second}, numberOftags: cfg.NumberOfTags, + bearerToken: bearerToken, } if !strings.HasPrefix(o.baseURL, "https://") { o.baseURL = fmt.Sprintf("https://%s", baseURL) @@ -361,6 +467,9 @@ func (o *OCIRegistry) GetTags(ctx context.Context, image string) ([]string, erro path := fmt.Sprintf("%s/v2/%s/tags/list", o.baseURL, image) req, err := http.NewRequestWithContext(ctx, "GET", path, nil) + if o.bearerToken != "" { + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", o.bearerToken)) + } if err != nil { return nil, fmt.Errorf("failed to create request: %v", err) } diff --git a/tooling/image-sync/internal/sync.go b/tooling/image-sync/internal/sync.go index 3e93e73a4..3036edfbe 100644 --- a/tooling/image-sync/internal/sync.go +++ b/tooling/image-sync/internal/sync.go @@ -2,6 +2,7 @@ package internal import ( "context" + "encoding/base64" "encoding/json" "fmt" "os" @@ -22,19 +23,33 @@ func Log() *zap.SugaredLogger { type SyncConfig struct { Repositories []string NumberOfTags int - QuaySecretFile string - AcrRegistry string + Secrets []Secrets + AcrTargetRegistry string TenantId string RequestTimeout int AddLatest bool ManagedIdentityClientID string } +type Secrets struct { + Registry string + SecretFile string +} -// QuaySecret is the secret for quay.io -type QuaySecret struct { +// BearerSecret is the secret for the source OCI registry +type BearerSecret struct { BearerToken string } +// AzureSecret is the token configured in the ACR +type AzureSecretFile struct { + Username string + Password string +} + +func (a AzureSecretFile) BasicAuthEncoded() string { + return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", a.Username, a.Password))) +} + // Copy copies an image from one registry to another func Copy(ctx context.Context, dstreference, srcreference string, dstauth, srcauth *types.DockerAuthConfig) error { policyctx, err := signature.NewPolicyContext(&signature.Policy{ @@ -68,12 +83,26 @@ func Copy(ctx context.Context, dstreference, srcreference string, dstauth, srcau return err } -func readQuaySecret(filename string) (*QuaySecret, error) { +func readBearerSecret(filename string) (*BearerSecret, error) { + secretBytes, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + var secret BearerSecret + err = json.Unmarshal(secretBytes, &secret) + if err != nil { + return nil, err + } + + return &secret, nil +} + +func readAzureSecret(filename string) (*AzureSecretFile, error) { secretBytes, err := os.ReadFile(filename) if err != nil { return nil, err } - var secret QuaySecret + var secret AzureSecretFile err = json.Unmarshal(secretBytes, &secret) if err != nil { return nil, err @@ -103,19 +132,48 @@ func DoSync(cfg *SyncConfig) error { Log().Infow("Syncing images", "images", cfg.Repositories, "numberoftags", cfg.NumberOfTags) ctx := context.Background() - quaySecret, err := readQuaySecret(cfg.QuaySecretFile) - if err != nil { - return fmt.Errorf("error reading secret file: %w %s", err, cfg.QuaySecretFile) + srcRegistries := make(map[string]Registry) + var err error + + for _, secret := range cfg.Secrets { + if secret.Registry == "quay.io" { + quaySecret, err := readBearerSecret(secret.SecretFile) + if err != nil { + return fmt.Errorf("error reading secret file: %w %s", err, secret.SecretFile) + } + qr := NewQuayRegistry(cfg, quaySecret.BearerToken) + srcRegistries[secret.Registry] = qr + } else { + if strings.HasSuffix(secret.Registry, "azurecr.io") || + strings.HasSuffix(secret.Registry, "azurecr.cn") || + strings.HasSuffix(secret.Registry, "azurecr.us") { + azureSecret, err := readAzureSecret(secret.SecretFile) + if err != nil { + return fmt.Errorf("error reading azure secret file: %w %s", err, secret.SecretFile) + } + bearerSecret, err := getACRBearerToken(ctx, *azureSecret, secret.Registry) + if err != nil { + return fmt.Errorf("error getting ACR bearer token: %w", err) + } + srcRegistries[secret.Registry] = NewACRWithTokenAuth(cfg, secret.Registry, bearerSecret) + } else { + s, err := readBearerSecret(secret.SecretFile) + bearerSecret := s.BearerToken + if err != nil { + return fmt.Errorf("error reading secret file: %w %s", err, secret.SecretFile) + } + srcRegistries[secret.Registry] = NewOCIRegistry(cfg, secret.Registry, bearerSecret) + } + } } - qr := NewQuayRegistry(cfg, quaySecret.BearerToken) - acr := NewAzureContainerRegistry(cfg) - acrPullSecret, err := acr.GetPullSecret(ctx) + targetACR := NewAzureContainerRegistry(cfg) + acrPullSecret, err := targetACR.GetPullSecret(ctx) if err != nil { return fmt.Errorf("error getting pull secret: %w", err) } - acrAuth := types.DockerAuthConfig{Username: "00000000-0000-0000-0000-000000000000", Password: acrPullSecret.RefreshToken} + targetACRAuth := types.DockerAuthConfig{Username: "00000000-0000-0000-0000-000000000000", Password: acrPullSecret.RefreshToken} for _, repoName := range cfg.Repositories { var srcTags, acrTags []string @@ -125,14 +183,15 @@ func DoSync(cfg *SyncConfig) error { Log().Infow("Syncing repository", "repository", repoName, "baseurl", baseURL) - if baseURL == "quay.io" { - srcTags, err = qr.GetTags(ctx, repoName) + if client, ok := srcRegistries[baseURL]; ok { + srcTags, err = client.GetTags(ctx, repoName) if err != nil { - return fmt.Errorf("error getting quay tags: %w", err) + return fmt.Errorf("error getting tags from %s: %w", baseURL, err) } Log().Debugw("Got tags from quay", "tags", srcTags) } else { - oci := NewOCIRegistry(cfg, baseURL) + // No secret defined, create a default client without auth + oci := NewOCIRegistry(cfg, baseURL, "") srcTags, err = oci.GetTags(ctx, repoName) if err != nil { return fmt.Errorf("error getting oci tags: %w", err) @@ -140,13 +199,13 @@ func DoSync(cfg *SyncConfig) error { Log().Debugw(fmt.Sprintf("Got tags from %s", baseURL), "repo", repoName, "tags", srcTags) } - exists, err := acr.RepositoryExists(ctx, repoName) + exists, err := targetACR.RepositoryExists(ctx, repoName) if err != nil { return fmt.Errorf("error getting ACR repository information: %w", err) } if exists { - acrTags, err = acr.GetTags(ctx, repoName) + acrTags, err = targetACR.GetTags(ctx, repoName) if err != nil { return fmt.Errorf("error getting ACR tags: %w", err) } @@ -161,10 +220,10 @@ func DoSync(cfg *SyncConfig) error { for _, tagToSync := range tagsToSync { source := fmt.Sprintf("%s/%s:%s", baseURL, repoName, tagToSync) - target := fmt.Sprintf("%s/%s:%s", cfg.AcrRegistry, repoName, tagToSync) + target := fmt.Sprintf("%s/%s:%s", cfg.AcrTargetRegistry, repoName, tagToSync) Log().Infow("Copying images", "images", tagToSync, "from", source, "to", target) - err = Copy(ctx, target, source, &acrAuth, nil) + err = Copy(ctx, target, source, &targetACRAuth, nil) if err != nil { return fmt.Errorf("error copying image: %w", err) } diff --git a/tooling/image-sync/main.go b/tooling/image-sync/main.go index e430ccdd1..a632c6bce 100644 --- a/tooling/image-sync/main.go +++ b/tooling/image-sync/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" defaultlog "log" "os" "time" @@ -64,8 +65,7 @@ func newSyncConfig() *internal.SyncConfig { "RequestTimeout": "REQUEST_TIMEOUT", "AddLatest": "ADD_LATEST", "Repositories": "REPOSITORIES", - "QuaySecretFile": "QUAY_SECRET_FILE", - "AcrRegistry": "ACR_REGISTRY", + "AcrTargetRegistry": "ACR_TARGET_REGISTRY", "TenantId": "TENANT_ID", "ManagedIdentityClientID": "MANAGED_IDENTITY_CLIENT_ID", } @@ -78,6 +78,19 @@ func newSyncConfig() *internal.SyncConfig { if err := v.Unmarshal(&sc); err != nil { Log().Fatalw("Error while unmarshalling configuration %s", err.Error()) } + + if secretEnv := os.Getenv("SECRETS"); secretEnv != "" { + type listOfSecrets struct { + Secrets []internal.Secrets + } + var s listOfSecrets + err := json.Unmarshal([]byte(secretEnv), &s) + if err != nil { + Log().Fatal("Error unmarshalling configuration") + } + sc.Secrets = append(sc.Secrets, s.Secrets...) + } + Log().Debugw("Using configuration", "config", sc) return sc } diff --git a/tooling/mcerepkg/go.mod b/tooling/mcerepkg/go.mod index 25ed03f38..c698720da 100644 --- a/tooling/mcerepkg/go.mod +++ b/tooling/mcerepkg/go.mod @@ -66,12 +66,12 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect google.golang.org/protobuf v1.34.2 // indirect diff --git a/tooling/mcerepkg/go.sum b/tooling/mcerepkg/go.sum index 6a7c8e577..e7f084873 100644 --- a/tooling/mcerepkg/go.sum +++ b/tooling/mcerepkg/go.sum @@ -145,27 +145,27 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn 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.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.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.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= 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.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/tooling/templatize/Makefile b/tooling/templatize/Makefile new file mode 100644 index 000000000..09b05933e --- /dev/null +++ b/tooling/templatize/Makefile @@ -0,0 +1,18 @@ + +SHELL = /bin/bash + +# Define the binary name +BINARY = templatize + +# Define the source files +SOURCES = $(shell find . -name '*.go') + +# Build the binary +$(BINARY): $(SOURCES) $(MAKEFILE_LIST) + go build -o $(BINARY) . + +# Clean the build artifacts +clean: + rm -f $(BINARY) + +.PHONY: clean diff --git a/tooling/templatize/cmd/generate/generate.go b/tooling/templatize/cmd/generate/cmd.go similarity index 70% rename from tooling/templatize/cmd/generate/generate.go rename to tooling/templatize/cmd/generate/cmd.go index 655cf4af6..f9dadc922 100644 --- a/tooling/templatize/cmd/generate/generate.go +++ b/tooling/templatize/cmd/generate/cmd.go @@ -1,28 +1,28 @@ package generate import ( - "log" + "context" "github.com/spf13/cobra" ) -func NewCommand() *cobra.Command { +func NewCommand() (*cobra.Command, error) { opts := DefaultGenerationOptions() cmd := &cobra.Command{ Use: "generate", Short: "generate", Long: "generate", RunE: func(cmd *cobra.Command, args []string) error { - return generate(opts) + return generate(cmd.Context(), opts) }, } if err := BindGenerationOptions(opts, cmd); err != nil { - log.Fatal(err) + return nil, err } - return cmd + return cmd, nil } -func generate(opts *RawGenerationOptions) error { +func generate(ctx context.Context, opts *RawGenerationOptions) error { validated, err := opts.Validate() if err != nil { return err diff --git a/tooling/templatize/cmd/generate/generate_test.go b/tooling/templatize/cmd/generate/cmd_test.go similarity index 78% rename from tooling/templatize/cmd/generate/generate_test.go rename to tooling/templatize/cmd/generate/cmd_test.go index 2f39319d4..231508555 100644 --- a/tooling/templatize/cmd/generate/generate_test.go +++ b/tooling/templatize/cmd/generate/cmd_test.go @@ -9,21 +9,22 @@ import ( "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" - "github.com/Azure/ARO-HCP/tooling/templatize/internal/config" + options "github.com/Azure/ARO-HCP/tooling/templatize/cmd" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" ) func TestExecuteTemplate(t *testing.T) { for _, testCase := range []struct { - name string - config config.Variables - input string + name string + vars config.Variables + input string expected string expectedError bool }{ { name: "happy case generates a file", - config: config.Variables{ + vars: config.Variables{ "region_maestro_keyvault": "kv", "region_eventgrid_namespace": "ns", }, @@ -36,7 +37,7 @@ param maestroEventGridMaxClientSessionsPerAuthName = 4`, }, { name: "referencing unset variable errors", - config: config.Variables{ + vars: config.Variables{ "region_maestro_keyvault": "kv", }, input: `param maestroKeyVaultName = '{{ .region_maestro_keyvault }}' @@ -49,10 +50,10 @@ param maestroEventGridMaxClientSessionsPerAuthName = 4`, output := &bytes.Buffer{} opts := GenerationOptions{ completedGenerationOptions: &completedGenerationOptions{ - Config: testCase.config, - Input: fstest.MapFS{"test": &fstest.MapFile{Data: []byte(testCase.input)}}, - InputFile: "test", - Output: &nopCloser{Writer: output}, + InputFS: fstest.MapFS{"test": &fstest.MapFile{Data: []byte(testCase.input)}}, + InputFile: "test", + OutputFile: &nopCloser{Writer: output}, + RolloutOptions: options.NewRolloutOptions(testCase.vars), }, } err := opts.ExecuteTemplate() diff --git a/tooling/templatize/cmd/generate/options.go b/tooling/templatize/cmd/generate/options.go index 20b229319..ebac5e6b9 100644 --- a/tooling/templatize/cmd/generate/options.go +++ b/tooling/templatize/cmd/generate/options.go @@ -4,24 +4,23 @@ import ( "fmt" "io" "io/fs" - "log" "os" "path/filepath" - "text/template" - "github.com/Masterminds/sprig/v3" "github.com/spf13/cobra" options "github.com/Azure/ARO-HCP/tooling/templatize/cmd" - "github.com/Azure/ARO-HCP/tooling/templatize/internal/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" ) func DefaultGenerationOptions() *RawGenerationOptions { - return &RawGenerationOptions{} + return &RawGenerationOptions{ + RolloutOptions: options.DefaultRolloutOptions(), + } } func BindGenerationOptions(opts *RawGenerationOptions, cmd *cobra.Command) error { - err := options.BindOptions(&opts.RawOptions, cmd) + err := options.BindRolloutOptions(opts.RolloutOptions, cmd) if err != nil { return fmt.Errorf("failed to bind raw options: %w", err) } @@ -29,7 +28,7 @@ func BindGenerationOptions(opts *RawGenerationOptions, cmd *cobra.Command) error cmd.Flags().StringVar(&opts.Output, "output", opts.Output, "output file path") for _, flag := range []string{"config-file", "input", "output"} { - if err := cmd.MarkFlagFilename("config-file"); err != nil { + if err := cmd.MarkFlagFilename(flag); err != nil { return fmt.Errorf("failed to mark flag %q as a file: %w", flag, err) } } @@ -38,26 +37,15 @@ func BindGenerationOptions(opts *RawGenerationOptions, cmd *cobra.Command) error // RawGenerationOptions holds input values. type RawGenerationOptions struct { - options.RawOptions - Input string - Output string -} - -func (o *RawGenerationOptions) Validate() (*ValidatedGenerationOptions, error) { - if _, err := o.RawOptions.Validate(); err != nil { - return nil, fmt.Errorf("validation failed for raw options: %w", err) - } - - return &ValidatedGenerationOptions{ - validatedGenerationOptions: &validatedGenerationOptions{ - RawGenerationOptions: o, - }, - }, nil + RolloutOptions *options.RawRolloutOptions + Input string + Output string } // validatedGenerationOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. type validatedGenerationOptions struct { *RawGenerationOptions + *options.ValidatedRolloutOptions } type ValidatedGenerationOptions struct { @@ -65,11 +53,41 @@ type ValidatedGenerationOptions struct { *validatedGenerationOptions } +// completedGenerationOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedGenerationOptions struct { + *options.RolloutOptions + InputFS fs.FS + InputFile string + OutputFile io.Writer +} + +type GenerationOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedGenerationOptions +} + +func (o *RawGenerationOptions) Validate() (*ValidatedGenerationOptions, error) { + validatedRolloutOptions, err := o.RolloutOptions.Validate() + if err != nil { + return nil, fmt.Errorf("validation failed for raw options: %w", err) + } + + if _, err := os.Stat(o.Input); os.IsNotExist(err) { + return nil, fmt.Errorf("input file %s does not exist", o.Input) + } + + return &ValidatedGenerationOptions{ + validatedGenerationOptions: &validatedGenerationOptions{ + RawGenerationOptions: o, + ValidatedRolloutOptions: validatedRolloutOptions, + }, + }, nil +} + func (o *ValidatedGenerationOptions) Complete() (*GenerationOptions, error) { - cfg := config.NewConfigProvider(o.ConfigFile, o.Region, o.RegionStamp, o.CXStamp) - vars, err := cfg.GetVariables(o.Cloud, o.DeployEnv, o.ExtraVars) + completed, err := o.ValidatedRolloutOptions.Complete() if err != nil { - return nil, fmt.Errorf("failed to get variables for cloud %s: %w", o.Cloud, err) + return nil, err } inputFile := filepath.Base(o.Input) @@ -78,50 +96,25 @@ func (o *ValidatedGenerationOptions) Complete() (*GenerationOptions, error) { return nil, fmt.Errorf("failed to create output directory %s: %w", o.Output, err) } - output, err := os.Create(o.Output) + outputFile, err := os.Create(o.Output) if err != nil { return nil, fmt.Errorf("failed to create output file %s: %w", o.Input, err) } return &GenerationOptions{ completedGenerationOptions: &completedGenerationOptions{ - Config: vars, - Input: os.DirFS(filepath.Dir(o.Input)), - InputFile: inputFile, - Output: output, + RolloutOptions: completed, + InputFS: os.DirFS(filepath.Dir(o.Input)), + InputFile: inputFile, + OutputFile: outputFile, }, }, nil } -// completedGenerationOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. -type completedGenerationOptions struct { - Config config.Variables - Input fs.FS - InputFile string - Output io.WriteCloser -} - -type GenerationOptions struct { - // Embed a private pointer that cannot be instantiated outside of this package. - *completedGenerationOptions -} - func (opts *GenerationOptions) ExecuteTemplate() error { - tmpl := template.New(opts.InputFile).Funcs(sprig.FuncMap()) - content, err := fs.ReadFile(opts.Input, opts.InputFile) + content, err := fs.ReadFile(opts.InputFS, opts.InputFile) if err != nil { return err } - - tmpl, err = tmpl.Parse(string(content)) - if err != nil { - return err - } - - defer func() { - if err := opts.Output.Close(); err != nil { - log.Printf("error closing output: %v\n", err) - } - }() - return tmpl.Option("missingkey=error").ExecuteTemplate(opts.Output, opts.InputFile, opts.Config) + return config.PreprocessContentIntoWriter(content, opts.RolloutOptions.Config, opts.OutputFile) } diff --git a/tooling/templatize/cmd/generate/options_test.go b/tooling/templatize/cmd/generate/options_test.go index 3fd96d475..0d518f460 100644 --- a/tooling/templatize/cmd/generate/options_test.go +++ b/tooling/templatize/cmd/generate/options_test.go @@ -1,6 +1,7 @@ package generate import ( + "context" "fmt" "path/filepath" "testing" @@ -14,17 +15,19 @@ import ( func TestRawOptions(t *testing.T) { tmpdir := t.TempDir() opts := &RawGenerationOptions{ - RawOptions: options.RawOptions{ - ConfigFile: "../../testdata/config.yaml", - Cloud: "public", - DeployEnv: "dev", + RolloutOptions: &options.RawRolloutOptions{ Region: "uksouth", - RegionStamp: "1", - CXStamp: "cx", + RegionShort: "abcde", + Stamp: "fghij", + BaseOptions: &options.RawOptions{ + ConfigFile: "../../testdata/config.yaml", + Cloud: "public", + DeployEnv: "dev", + }, }, - Input: "../../testdata/helm.sh", - Output: fmt.Sprintf("%s/helm.sh", tmpdir), + Input: "../../testdata/pipeline.yaml", + Output: fmt.Sprintf("%s/pipeline.yaml", tmpdir), } - assert.NoError(t, generate(opts)) - testutil.CompareFileWithFixture(t, filepath.Join(tmpdir, "helm.sh")) + assert.NoError(t, generate(context.Background(), opts)) + testutil.CompareFileWithFixture(t, filepath.Join(tmpdir, "pipeline.yaml")) } diff --git a/tooling/templatize/cmd/inspect/inspect.go b/tooling/templatize/cmd/inspect/cmd.go similarity index 73% rename from tooling/templatize/cmd/inspect/inspect.go rename to tooling/templatize/cmd/inspect/cmd.go index 8edb69449..087a25036 100644 --- a/tooling/templatize/cmd/inspect/inspect.go +++ b/tooling/templatize/cmd/inspect/cmd.go @@ -1,8 +1,8 @@ package inspect import ( + "context" "fmt" - "log" "github.com/spf13/cobra" @@ -10,25 +10,26 @@ import ( output "github.com/Azure/ARO-HCP/tooling/templatize/internal/utils" ) -func NewCommand() *cobra.Command { - opts := options.DefaultOptions() +func NewCommand() (*cobra.Command, error) { + opts := options.DefaultRolloutOptions() + format := "json" cmd := &cobra.Command{ Use: "inspect", Short: "inspect", Long: "inspect", RunE: func(cmd *cobra.Command, args []string) error { - return dumpConfig(format, opts) + return dumpConfig(cmd.Context(), format, opts) }, } - if err := options.BindOptions(opts, cmd); err != nil { - log.Fatal(err) + if err := options.BindRolloutOptions(opts, cmd); err != nil { + return nil, err } cmd.Flags().StringVar(&format, "format", format, "output format (json, yaml)") - return cmd + return cmd, nil } -func dumpConfig(format string, opts *options.RawOptions) error { +func dumpConfig(ctx context.Context, format string, opts *options.RawRolloutOptions) error { validated, err := opts.Validate() if err != nil { return err diff --git a/tooling/templatize/cmd/inspect/options.go b/tooling/templatize/cmd/inspect/options.go deleted file mode 100644 index eda521fdc..000000000 --- a/tooling/templatize/cmd/inspect/options.go +++ /dev/null @@ -1 +0,0 @@ -package inspect diff --git a/tooling/templatize/cmd/options.go b/tooling/templatize/cmd/options.go index 2d4e66793..28fa6116d 100644 --- a/tooling/templatize/cmd/options.go +++ b/tooling/templatize/cmd/options.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/sets" - "github.com/Azure/ARO-HCP/tooling/templatize/internal/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" ) func DefaultOptions() *RawOptions { @@ -17,22 +17,14 @@ func BindOptions(opts *RawOptions, cmd *cobra.Command) error { cmd.Flags().StringVar(&opts.ConfigFile, "config-file", opts.ConfigFile, "config file path") cmd.Flags().StringVar(&opts.Cloud, "cloud", opts.Cloud, "the cloud (public, fairfax)") cmd.Flags().StringVar(&opts.DeployEnv, "deploy-env", opts.DeployEnv, "the deploy environment") - cmd.Flags().StringVar(&opts.Region, "region", opts.Region, "resources location") - cmd.Flags().StringVar(&opts.RegionStamp, "region-stamp", opts.RegionStamp, "region stamp") - cmd.Flags().StringVar(&opts.CXStamp, "cx-stamp", opts.CXStamp, "CX stamp") - cmd.Flags().StringToStringVar(&opts.ExtraVars, "extra-args", opts.ExtraVars, "Extra arguments to be used config templating") return nil } // RawGenerationOptions holds input values. type RawOptions struct { - ConfigFile string - Cloud string - DeployEnv string - Region string - RegionStamp string - CXStamp string - ExtraVars map[string]string + ConfigFile string + Cloud string + DeployEnv string } func (o *RawOptions) Validate() (*ValidatedOptions, error) { @@ -59,22 +51,22 @@ type ValidatedOptions struct { } func (o *ValidatedOptions) Complete() (*Options, error) { - cfg := config.NewConfigProvider(o.ConfigFile, o.Region, o.RegionStamp, o.CXStamp) - vars, err := cfg.GetVariables(o.Cloud, o.DeployEnv, o.ExtraVars) + configProvider := config.NewConfigProvider(o.ConfigFile) + err := configProvider.Validate(o.Cloud, o.DeployEnv) if err != nil { - return nil, fmt.Errorf("failed to get variables for cloud %s: %w", o.Cloud, err) + return nil, fmt.Errorf("failed to validate config: %w", err) } return &Options{ completedOptions: &completedOptions{ - Config: vars, + ConfigProvider: configProvider, }, }, nil } // completedGenerationOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. type completedOptions struct { - Config config.Variables + ConfigProvider config.ConfigProvider } type Options struct { diff --git a/tooling/templatize/cmd/pipeline/cmd.go b/tooling/templatize/cmd/pipeline/cmd.go new file mode 100644 index 000000000..6a7d80d96 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/cmd.go @@ -0,0 +1,35 @@ +package pipeline + +import ( + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/inspect" + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/run" +) + +func NewCommand() (*cobra.Command, error) { + cmd := &cobra.Command{ + Use: "pipeline", + Short: "pipeline", + Long: "pipeline", + SilenceUsage: true, + TraverseChildren: true, + CompletionOptions: cobra.CompletionOptions{ + HiddenDefaultCmd: true, + }, + } + + commands := []func() (*cobra.Command, error){ + run.NewCommand, + inspect.NewCommand, + } + for _, newCmd := range commands { + c, err := newCmd() + if err != nil { + return nil, err + } + cmd.AddCommand(c) + } + + return cmd, nil +} diff --git a/tooling/templatize/cmd/pipeline/inspect/cmd.go b/tooling/templatize/cmd/pipeline/inspect/cmd.go new file mode 100644 index 000000000..8c18187bf --- /dev/null +++ b/tooling/templatize/cmd/pipeline/inspect/cmd.go @@ -0,0 +1,35 @@ +package inspect + +import ( + "context" + + "github.com/spf13/cobra" +) + +func NewCommand() (*cobra.Command, error) { + opts := DefaultOptions() + cmd := &cobra.Command{ + Use: "inspect", + Short: "inspect scopes of a pipeline.yaml file", + Long: "inspect scopes of a pipeline.yaml file", + RunE: func(cmd *cobra.Command, args []string) error { + return runInspect(cmd.Context(), opts) + }, + } + if err := BindOptions(opts, cmd); err != nil { + return nil, err + } + return cmd, nil +} + +func runInspect(ctx context.Context, opts *RawInspectOptions) error { + validated, err := opts.Validate() + if err != nil { + return err + } + completed, err := validated.Complete() + if err != nil { + return err + } + return completed.RunInspect(ctx) +} diff --git a/tooling/templatize/cmd/pipeline/inspect/options.go b/tooling/templatize/cmd/pipeline/inspect/options.go new file mode 100644 index 000000000..774a43e18 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/inspect/options.go @@ -0,0 +1,117 @@ +package inspect + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/options" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func DefaultOptions() *RawInspectOptions { + return &RawInspectOptions{ + PipelineOptions: options.DefaultOptions(), + } +} + +func BindOptions(opts *RawInspectOptions, cmd *cobra.Command) error { + err := options.BindOptions(opts.PipelineOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().StringVar(&opts.Scope, "scope", opts.Scope, "scope of the pipeline to inspect") + cmd.Flags().StringVar(&opts.Format, "format", opts.Format, "output format") + return nil +} + +type RawInspectOptions struct { + PipelineOptions *options.RawPipelineOptions + Scope string + Format string +} + +// validatedInspectOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedInspectOptions struct { + *RawInspectOptions + *options.ValidatedPipelineOptions +} + +type ValidatedInspectOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedInspectOptions +} + +// completedRunOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedInspectOptions struct { + PipelineOptions *options.PipelineOptions + Scope string + Format string +} + +type InspectOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedInspectOptions +} + +func (o *RawInspectOptions) Validate() (*ValidatedInspectOptions, error) { + validatedPipelineOptions, err := o.PipelineOptions.Validate() + if err != nil { + return nil, err + } + + inspectScopes := pipeline.NewStepInspectScopes() + if _, ok := inspectScopes[o.Scope]; !ok { + scopes := make([]string, 0, len(inspectScopes)) + for scope := range inspectScopes { + scopes = append(scopes, scope) + } + availableScopes := strings.Join(scopes, ", ") + return nil, fmt.Errorf("unknown inspect scope %q, valid scopes are: (%v)", o.Scope, availableScopes) + } + + return &ValidatedInspectOptions{ + validatedInspectOptions: &validatedInspectOptions{ + RawInspectOptions: o, + ValidatedPipelineOptions: validatedPipelineOptions, + }, + }, nil +} + +func (o *ValidatedInspectOptions) Complete() (*InspectOptions, error) { + completed, err := o.ValidatedPipelineOptions.Complete() + if err != nil { + return nil, err + } + + return &InspectOptions{ + completedInspectOptions: &completedInspectOptions{ + PipelineOptions: completed, + Scope: o.Scope, + Format: o.Format, + }, + }, nil +} + +func (o *InspectOptions) RunInspect(ctx context.Context) error { + rolloutOptions := o.PipelineOptions.RolloutOptions + variables, err := rolloutOptions.Options.ConfigProvider.GetVariables( + rolloutOptions.Cloud, + rolloutOptions.DeployEnv, + rolloutOptions.Region, + config.NewConfigReplacements( + rolloutOptions.Region, + rolloutOptions.RegionShort, + rolloutOptions.Stamp, + ), + ) + if err != nil { + return err + } + inspectOptions := pipeline.NewInspectOptions(variables, rolloutOptions.Region, o.PipelineOptions.Step, o.Scope, o.Format) + return o.PipelineOptions.Pipeline.Inspect(ctx, inspectOptions, os.Stdout) +} diff --git a/tooling/templatize/cmd/pipeline/options/options.go b/tooling/templatize/cmd/pipeline/options/options.go new file mode 100644 index 000000000..66bdfd6a5 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/options/options.go @@ -0,0 +1,104 @@ +package options + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + options "github.com/Azure/ARO-HCP/tooling/templatize/cmd" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func DefaultOptions() *RawPipelineOptions { + return &RawPipelineOptions{ + RolloutOptions: options.DefaultRolloutOptions(), + } +} + +func BindOptions(opts *RawPipelineOptions, cmd *cobra.Command) error { + err := options.BindRolloutOptions(opts.RolloutOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().StringVar(&opts.PipelineFile, "pipeline-file", opts.PipelineFile, "pipeline file path") + cmd.Flags().StringVar(&opts.Step, "step", opts.Step, "run only a specific step in the pipeline") + + for _, flag := range []string{"pipeline-file"} { + if err := cmd.MarkFlagFilename(flag); err != nil { + return fmt.Errorf("failed to mark flag %q as a file: %w", flag, err) + } + if err := cmd.MarkFlagRequired(flag); err != nil { + return fmt.Errorf("failed to mark flag %q as required: %w", flag, err) + } + } + return nil +} + +// RawRunOptions holds input values. +type RawPipelineOptions struct { + RolloutOptions *options.RawRolloutOptions + PipelineFile string + Step string +} + +// validatedPipelineOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedPipelineOptions struct { + *RawPipelineOptions + *options.ValidatedRolloutOptions +} + +type ValidatedPipelineOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedPipelineOptions +} + +// completedPipelineOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedPipelineOptions struct { + RolloutOptions *options.RolloutOptions + Pipeline *pipeline.Pipeline + Step string +} + +type PipelineOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedPipelineOptions +} + +func (o *RawPipelineOptions) Validate() (*ValidatedPipelineOptions, error) { + validatedRolloutOptions, err := o.RolloutOptions.Validate() + if err != nil { + return nil, err + } + + if _, err := os.Stat(o.PipelineFile); os.IsNotExist(err) { + return nil, fmt.Errorf("pipeline file %s does not exist", o.PipelineFile) + } + + return &ValidatedPipelineOptions{ + validatedPipelineOptions: &validatedPipelineOptions{ + RawPipelineOptions: o, + ValidatedRolloutOptions: validatedRolloutOptions, + }, + }, nil +} + +func (o *ValidatedPipelineOptions) Complete() (*PipelineOptions, error) { + completed, err := o.ValidatedRolloutOptions.Complete() + if err != nil { + return nil, err + } + + pipeline, err := pipeline.NewPipelineFromFile(o.PipelineFile, completed.Config) + if err != nil { + return nil, fmt.Errorf("failed to load pipeline %s: %w", o.PipelineFile, err) + } + + return &PipelineOptions{ + completedPipelineOptions: &completedPipelineOptions{ + RolloutOptions: completed, + Pipeline: pipeline, + Step: o.Step, + }, + }, nil +} diff --git a/tooling/templatize/cmd/pipeline/run/cmd.go b/tooling/templatize/cmd/pipeline/run/cmd.go new file mode 100644 index 000000000..afd5f63a7 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/run/cmd.go @@ -0,0 +1,35 @@ +package run + +import ( + "context" + + "github.com/spf13/cobra" +) + +func NewCommand() (*cobra.Command, error) { + opts := DefaultOptions() + cmd := &cobra.Command{ + Use: "run", + Short: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster", + Long: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster", + RunE: func(cmd *cobra.Command, args []string) error { + return runPipeline(cmd.Context(), opts) + }, + } + if err := BindOptions(opts, cmd); err != nil { + return nil, err + } + return cmd, nil +} + +func runPipeline(ctx context.Context, opts *RawRunOptions) error { + validated, err := opts.Validate() + if err != nil { + return err + } + completed, err := validated.Complete() + if err != nil { + return err + } + return completed.RunPipeline(ctx) +} diff --git a/tooling/templatize/cmd/pipeline/run/options.go b/tooling/templatize/cmd/pipeline/run/options.go new file mode 100644 index 000000000..3abf920b0 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/run/options.go @@ -0,0 +1,116 @@ +package run + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/options" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func DefaultOptions() *RawRunOptions { + return &RawRunOptions{ + PipelineOptions: options.DefaultOptions(), + } +} + +func BindOptions(opts *RawRunOptions, cmd *cobra.Command) error { + err := options.BindOptions(opts.PipelineOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().BoolVar(&opts.DryRun, "dry-run", opts.DryRun, "validate the pipeline without executing it") + cmd.Flags().BoolVar(&opts.NoPersist, "no-persist-tag", opts.NoPersist, "toggle if persist tag should not be set") + cmd.Flags().IntVar(&opts.DeploymentTimeoutSeconds, "deployment-timeout-seconds", pipeline.DefaultDeploymentTimeoutSeconds, "Timeout in Seconds to wait for previous deployments of the pipeline to finish") + return nil +} + +type RawRunOptions struct { + PipelineOptions *options.RawPipelineOptions + DryRun bool + NoPersist bool + DeploymentTimeoutSeconds int +} + +// validatedRunOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedRunOptions struct { + *RawRunOptions + *options.ValidatedPipelineOptions +} + +type ValidatedRunOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedRunOptions +} + +// completedRunOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedRunOptions struct { + PipelineOptions *options.PipelineOptions + DryRun bool + NoPersist bool + DeploymentTimeoutSeconds int +} + +type RunOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedRunOptions +} + +func (o *RawRunOptions) Validate() (*ValidatedRunOptions, error) { + validatedPipelineOptions, err := o.PipelineOptions.Validate() + if err != nil { + return nil, err + } + + return &ValidatedRunOptions{ + validatedRunOptions: &validatedRunOptions{ + RawRunOptions: o, + ValidatedPipelineOptions: validatedPipelineOptions, + }, + }, nil +} + +func (o *ValidatedRunOptions) Complete() (*RunOptions, error) { + completed, err := o.ValidatedPipelineOptions.Complete() + if err != nil { + return nil, err + } + + return &RunOptions{ + completedRunOptions: &completedRunOptions{ + PipelineOptions: completed, + DryRun: o.DryRun, + NoPersist: o.NoPersist, + DeploymentTimeoutSeconds: o.DeploymentTimeoutSeconds, + }, + }, nil +} + +func (o *RunOptions) RunPipeline(ctx context.Context) error { + rolloutOptions := o.PipelineOptions.RolloutOptions + variables, err := rolloutOptions.Options.ConfigProvider.GetVariables( + rolloutOptions.Cloud, + rolloutOptions.DeployEnv, + rolloutOptions.Region, + config.NewConfigReplacements( + rolloutOptions.Region, + rolloutOptions.RegionShort, + rolloutOptions.Stamp, + ), + ) + if err != nil { + return err + } + return pipeline.RunPipeline(o.PipelineOptions.Pipeline, ctx, &pipeline.PipelineRunOptions{ + DryRun: o.DryRun, + Vars: variables, + Region: rolloutOptions.Region, + Step: o.PipelineOptions.Step, + SubsciptionLookupFunc: pipeline.LookupSubscriptionID, + NoPersist: o.NoPersist, + DeploymentTimeoutSeconds: o.DeploymentTimeoutSeconds, + }) +} diff --git a/tooling/templatize/cmd/rolloutoptions.go b/tooling/templatize/cmd/rolloutoptions.go new file mode 100644 index 000000000..c5bd75091 --- /dev/null +++ b/tooling/templatize/cmd/rolloutoptions.go @@ -0,0 +1,113 @@ +package options + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func DefaultRolloutOptions() *RawRolloutOptions { + return &RawRolloutOptions{ + BaseOptions: DefaultOptions(), + } +} + +func NewRolloutOptions(config config.Variables) *RolloutOptions { + return &RolloutOptions{ + completedRolloutOptions: &completedRolloutOptions{ + Config: config, + }, + } +} + +func EV2RolloutOptions() *RawRolloutOptions { + return &RawRolloutOptions{ + Region: "$location()", + RegionShort: "$(regionShort)", + Stamp: "$stamp()", + } +} + +func BindRolloutOptions(opts *RawRolloutOptions, cmd *cobra.Command) error { + err := BindOptions(opts.BaseOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().StringVar(&opts.Region, "region", opts.Region, "resources location") + cmd.Flags().StringVar(&opts.RegionShort, "region-short", opts.RegionShort, "short region string") + cmd.Flags().StringVar(&opts.Stamp, "stamp", opts.Stamp, "stamp") + cmd.Flags().StringToStringVar(&opts.ExtraVars, "extra-args", opts.ExtraVars, "Extra arguments to be used config templating") + return nil +} + +// RawRolloutOptions holds input values. +type RawRolloutOptions struct { + Region string + RegionShort string + Stamp string + ExtraVars map[string]string + BaseOptions *RawOptions +} + +// validatedRolloutOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedRolloutOptions struct { + *RawRolloutOptions + *ValidatedOptions +} + +type ValidatedRolloutOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedRolloutOptions +} + +type completedRolloutOptions struct { + *ValidatedRolloutOptions + Options *Options + Config config.Variables +} + +type RolloutOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedRolloutOptions +} + +func (o *RawRolloutOptions) Validate() (*ValidatedRolloutOptions, error) { + validatedBaseOptions, err := o.BaseOptions.Validate() + if err != nil { + return nil, err + } + + return &ValidatedRolloutOptions{ + validatedRolloutOptions: &validatedRolloutOptions{ + RawRolloutOptions: o, + ValidatedOptions: validatedBaseOptions, + }, + }, nil +} + +func (o *ValidatedRolloutOptions) Complete() (*RolloutOptions, error) { + completed, err := o.ValidatedOptions.Complete() + if err != nil { + return nil, err + } + + variables, err := completed.ConfigProvider.GetVariables(o.Cloud, o.DeployEnv, o.Region, config.NewConfigReplacements(o.Region, o.RegionShort, o.Stamp)) + if err != nil { + return nil, fmt.Errorf("failed to get variables: %w", err) + } + extraVars := make(map[string]interface{}) + for k, v := range o.ExtraVars { + extraVars[k] = v + } + variables["extraVars"] = extraVars + + return &RolloutOptions{ + completedRolloutOptions: &completedRolloutOptions{ + ValidatedRolloutOptions: o, + Options: completed, + Config: variables, + }, + }, nil +} diff --git a/tooling/templatize/go.mod b/tooling/templatize/go.mod index 73bc01893..6f6e5199d 100644 --- a/tooling/templatize/go.mod +++ b/tooling/templatize/go.mod @@ -3,29 +3,85 @@ module github.com/Azure/ARO-HCP/tooling/templatize go 1.23.0 require ( - github.com/Masterminds/sprig/v3 v3.3.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0 + github.com/dusted-go/logging v1.3.0 + github.com/go-logr/logr v1.4.2 github.com/google/go-cmp v0.6.0 + github.com/google/uuid v1.6.0 + github.com/microsoft/kiota-authentication-azure-go v1.1.0 + github.com/microsoftgraph/msgraph-sdk-go v1.51.0 + github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.31.1 + gotest.tools v2.2.0+incompatible + gotest.tools/v3 v3.5.1 + k8s.io/apimachinery v0.31.2 + k8s.io/client-go v0.31.2 sigs.k8s.io/yaml v1.4.0 ) require ( - dario.cat/mergo v1.0.1 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/cjlapao/common-go v0.0.39 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/huandu/xstrings v1.5.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microsoft/kiota-abstractions-go v1.7.0 // indirect + github.com/microsoft/kiota-http-go v1.4.4 // indirect + github.com/microsoft/kiota-serialization-form-go v1.0.0 // indirect + github.com/microsoft/kiota-serialization-json-go v1.0.8 // indirect + github.com/microsoft/kiota-serialization-multipart-go v1.0.0 // indirect + github.com/microsoft/kiota-serialization-text-go v1.0.0 // indirect + github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/shopspring/decimal v1.4.0 // indirect - github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/crypto v0.26.0 // indirect + github.com/std-uritemplate/std-uritemplate/go v0.0.57 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + k8s.io/api v0.31.2 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/tooling/templatize/go.sum b/tooling/templatize/go.sum index 412df81cc..b06992ace 100644 --- a/tooling/templatize/go.sum +++ b/tooling/templatize/go.sum @@ -1,57 +1,248 @@ -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= -github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 h1:qiir/pptnHqp6hV8QwV+IExYIf6cPsXBfUDUXQ27t2Y= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2/go.mod h1:jVRrRDLCOuif95HDYC23ADTMlvahB7tMdl519m9Iyjc= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 h1:figxyQZXzZQIcP3njhC68bYUiTw45J8/SsHaLW8Ax0M= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0/go.mod h1:TmlMW4W5OvXOmOyKNnor8nlMMiO1ctIyzmHme/VHsrA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0 h1:wxQx2Bt4xzPIKvW59WQf1tJNx/ZZKPfN+EhPX3Z6CYY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0/go.mod h1:TpiwjwnW/khS0LKs4vW5UmmT9OWcxaveS8U7+tlknzo= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +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/cjlapao/common-go v0.0.39 h1:bAAUrj2B9v0kMzbAOhzjSmiyDy+rd56r2sy7oEiQLlA= +github.com/cjlapao/common-go v0.0.39/go.mod h1:M3dzazLjTjEtZJbbxoA5ZDiGCiHmpwqW9l4UWaddwOA= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dusted-go/logging v1.3.0 h1:SL/EH1Rp27oJQIte+LjWvWACSnYDTqNx5gZULin0XRY= +github.com/dusted-go/logging v1.3.0/go.mod h1:s58+s64zE5fxSWWZfp+b8ZV0CHyKHjamITGyuY1wzGg= +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/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +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-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +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.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= 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/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= -github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +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/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= +github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +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.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/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/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/microsoft/kiota-abstractions-go v1.7.0 h1:/0OKSSEe94Z1qgpcGE7ZFI9P+4iAnsDQo9v9UOk+R8E= +github.com/microsoft/kiota-abstractions-go v1.7.0/go.mod h1:FI1I2OHg0E7bK5t8DPnw+9C/CHVyLP6XeqDBT+95pTE= +github.com/microsoft/kiota-authentication-azure-go v1.1.0 h1:HudH57Enel9zFQ4TEaJw6lMiyZ5RbBdrRHwdU0NP2RY= +github.com/microsoft/kiota-authentication-azure-go v1.1.0/go.mod h1:zfPFOiLdEqM77Hua5B/2vpcXrVaGqSWjHSRzlvAWEgc= +github.com/microsoft/kiota-http-go v1.4.4 h1:HM0KT/Q7o+JsGatFkkbTIqJL24Jzo5eMI5NNe9N4TQ4= +github.com/microsoft/kiota-http-go v1.4.4/go.mod h1:Kup5nMDD3a9sjdgRKHCqZWqtrv3FbprjcPaGjLR6FzM= +github.com/microsoft/kiota-serialization-form-go v1.0.0 h1:UNdrkMnLFqUCccQZerKjblsyVgifS11b3WCx+eFEsAI= +github.com/microsoft/kiota-serialization-form-go v1.0.0/go.mod h1:h4mQOO6KVTNciMF6azi1J9QB19ujSw3ULKcSNyXXOMA= +github.com/microsoft/kiota-serialization-json-go v1.0.8 h1:+aViv9k6wqaw1Fx6P49fl5GIB1hN3b6CG0McNTcUYBc= +github.com/microsoft/kiota-serialization-json-go v1.0.8/go.mod h1:O8+v11U0EUwHlCz7hrW38KxDmdhKAHfv4Q89uvsBalY= +github.com/microsoft/kiota-serialization-multipart-go v1.0.0 h1:3O5sb5Zj+moLBiJympbXNaeV07K0d46IfuEd5v9+pBs= +github.com/microsoft/kiota-serialization-multipart-go v1.0.0/go.mod h1:yauLeBTpANk4L03XD985akNysG24SnRJGaveZf+p4so= +github.com/microsoft/kiota-serialization-text-go v1.0.0 h1:XOaRhAXy+g8ZVpcq7x7a0jlETWnWrEum0RhmbYrTFnA= +github.com/microsoft/kiota-serialization-text-go v1.0.0/go.mod h1:sM1/C6ecnQ7IquQOGUrUldaO5wj+9+v7G2W3sQ3fy6M= +github.com/microsoftgraph/msgraph-sdk-go v1.51.0 h1:IfRY0uVHToT8X9k6Ri19tKdt8hwPomji2yx5YsKoaw4= +github.com/microsoftgraph/msgraph-sdk-go v1.51.0/go.mod h1:MVTeFCCih3qXy9D0q+f4NdOyumFnMZ+Ppcpurgd30TY= +github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1 h1:P1wpmn3xxfPMFJHg+PJPcusErfRkl63h6OdAnpDbkS8= +github.com/microsoftgraph/msgraph-sdk-go-core v1.2.1/go.mod h1:vFmWQGWyLlhxCESNLv61vlE4qesBU+eWmEVH7DJSESA= +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/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.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= +github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= -github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= -github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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/std-uritemplate/std-uritemplate/go v0.0.57 h1:GHGjptrsmazP4IVDlUprssiEf9ESVkbjx15xQXXzvq4= +github.com/std-uritemplate/std-uritemplate/go v0.0.57/go.mod h1:rG/bqh/ThY4xE5de7Rap3vaDkYUT76B0GPJ0loYeTTc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +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.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +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.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= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= +k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= +k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= +k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.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-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/tooling/templatize/internal/config/config.go b/tooling/templatize/internal/config/config.go deleted file mode 100644 index 0b208a569..000000000 --- a/tooling/templatize/internal/config/config.go +++ /dev/null @@ -1,137 +0,0 @@ -package config - -import ( - "bytes" - "fmt" - "os" - "reflect" - "text/template" - - "gopkg.in/yaml.v3" - - "github.com/Azure/ARO-HCP/tooling/templatize/internal/naming" -) - -type Provider interface { - GetVariables(cloud, deployEnv string) (Variables, error) -} - -func NewConfigProvider(config, region, regionStamp, cxStamp string) *configProviderImpl { - return &configProviderImpl{ - config: config, - region: region, - regionStamp: regionStamp, - cxStamp: cxStamp, - } -} - -func interfaceToVariables(i interface{}) (Variables, bool) { - // Helper, that reduces need for reflection calls, i.e. MapIndex - // from: https://github.com/peterbourgon/mergemap/blob/master/mergemap.go - value := reflect.ValueOf(i) - if value.Kind() == reflect.Map { - m := Variables{} - for _, k := range value.MapKeys() { - m[k.String()] = value.MapIndex(k).Interface() - } - return m, true - } - return Variables{}, false -} - -// Merges variables, returns merged variables -// However the return value is only used for recursive updates on the map -// The actual merged variables are updated in the base map -func mergeVariables(base, override Variables) Variables { - for k, newValue := range override { - if baseValue, exists := base[k]; exists { - srcMap, srcMapOk := interfaceToVariables(newValue) - dstMap, dstMapOk := interfaceToVariables(baseValue) - if srcMapOk && dstMapOk { - newValue = mergeVariables(dstMap, srcMap) - } - } - base[k] = newValue - } - - return base -} - -// get the variables toke effect finally for cloud/deployEnv/region -func (cp *configProviderImpl) GetVariables(cloud, deployEnv string, extraVars map[string]string) (Variables, error) { - variableOverrides, err := cp.loadConfig(cloud, deployEnv) - variables := Variables{} - - if err == nil { - for k, v := range variableOverrides.Defaults { - variables[k] = v - } - if cloudOverride, ok := variableOverrides.Overrides[cloud]; ok { - mergeVariables(variables, cloudOverride.Defaults) - if deployEnvOverride, ok := cloudOverride.Overrides[deployEnv]; ok { - mergeVariables(variables, deployEnvOverride.Defaults) - if regionOverride, ok := deployEnvOverride.Overrides[cp.region]; ok { - mergeVariables(variables, regionOverride) - } - } else { - return nil, fmt.Errorf("the deployment env %s is not found under cloud %s in %s", deployEnv, cloud, cp.config) - } - } - } - - if _, exists := variables["extraVars"]; exists { - return nil, fmt.Errorf("extraVars is a reserved key and cannot be used in the config file") - } - - if len(extraVars) > 0 { - variables["extraVars"] = extraVars - } - return variables, err -} - -func (cp *configProviderImpl) loadConfig(cloud, deployEnv string) (*VariableOverrides, error) { - vars := map[string]interface{}{ - "ctx": map[string]interface{}{ - "region": cp.region, - "cloud": cloud, - "deployEnv": deployEnv, - "regionStamp": cp.regionStamp, - "cxStamp": cp.cxStamp, - }, - } - - functions := template.FuncMap{ - "azureEventGridName": naming.AzureEventGridName, - "azurePostgresName": naming.AzurePostgresName, - "azureKeyVaultName": naming.AzureKeyVaultName, - "azureStorageAccountName": naming.AzureStorageAccountName, - "azureCosmosDBName": naming.AzureCosmosDBName, - "uniqueString": naming.UniqueString, - } - - // parse, execute and unmarshal the config file as a template to generate the final config file - tmpl := template.New("configTemplate").Funcs(functions) - content, err := os.ReadFile(cp.config) - if err != nil { - return nil, err - } - - tmpl, err = tmpl.Parse(string(content)) - if err != nil { - return nil, err - } - - var tmplBytes bytes.Buffer - if err := tmpl.Option("missingkey=error").Execute(&tmplBytes, vars); err != nil { - return nil, err - } - - currentVariableOverrides := &VariableOverrides{} - if err := yaml.Unmarshal(tmplBytes.Bytes(), currentVariableOverrides); err == nil { - cp.baseVariableOverrides = currentVariableOverrides - } else { - return nil, err - } - - return cp.baseVariableOverrides, err -} diff --git a/tooling/templatize/internal/config/config_test.go b/tooling/templatize/internal/config/config_test.go deleted file mode 100644 index 22d9b6ee9..000000000 --- a/tooling/templatize/internal/config/config_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package config - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestConfigProvider(t *testing.T) { - region := "uksouth" - regionStamp := "1" - cxStamp := "cx" - - configProvider := NewConfigProvider("../../testdata/config.yaml", region, regionStamp, cxStamp) - - variables, err := configProvider.GetVariables("public", "int", map[string]string{}) - assert.NoError(t, err) - assert.NotNil(t, variables) - - // key is not in the config file - assert.Nil(t, variables["svc_resourcegroup"]) - - // key is in the config file, region constant value - assert.Equal(t, "uksouth", variables["test"]) - - // key is in the config file, default in INT, constant value - assert.Equal(t, "aro-hcp-int.azurecr.io/maestro-server:the-stable-one", variables["maestro_image"]) - - // key is in the config file, default, varaible value - assert.Equal(t, fmt.Sprintf("hcp-underlay-%s-%s", region, regionStamp), variables["region_resourcegroup"]) -} - -func TestInterfaceToVariable(t *testing.T) { - testCases := []struct { - name string - i interface{} - ok bool - expecetedVariables Variables - }{ - { - name: "empty interface", - ok: false, - expecetedVariables: Variables{}, - }, - { - name: "empty map", - i: map[string]interface{}{}, - ok: true, - expecetedVariables: Variables{}, - }, - { - name: "map", - i: map[string]interface{}{ - "key1": "value1", - "key2": "value2", - }, - ok: true, - expecetedVariables: Variables{ - "key1": "value1", - "key2": "value2", - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - vars, ok := interfaceToVariables(tc.i) - assert.Equal(t, tc.ok, ok) - assert.Equal(t, tc.expecetedVariables, vars) - }) - } -} - -func TestMergeVariable(t *testing.T) { - testCases := []struct { - name string - base Variables - override Variables - expected Variables - }{ - { - name: "nil base", - expected: nil, - }, - { - name: "empty base and override", - base: Variables{}, - expected: Variables{}, - }, - { - name: "merge into empty base", - base: Variables{}, - override: Variables{"key1": "value1"}, - expected: Variables{"key1": "value1"}, - }, - { - name: "merge into base", - base: Variables{"key1": "value1"}, - override: Variables{"key2": "value2"}, - expected: Variables{"key1": "value1", "key2": "value2"}, - }, - { - name: "override base, change schema", - base: Variables{"key1": Variables{"key2": "value2"}}, - override: Variables{"key1": "value1"}, - expected: Variables{"key1": "value1"}, - }, - { - name: "merge into sub map", - base: Variables{"key1": Variables{"key2": "value2"}}, - override: Variables{"key1": Variables{"key3": "value3"}}, - expected: Variables{"key1": Variables{"key2": "value2", "key3": "value3"}}, - }, - { - name: "override sub map value", - base: Variables{"key1": Variables{"key2": "value2"}}, - override: Variables{"key1": Variables{"key2": "value3"}}, - expected: Variables{"key1": Variables{"key2": "value3"}}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - result := mergeVariables(tc.base, tc.override) - assert.Equal(t, tc.expected, result) - }) - } - -} diff --git a/tooling/templatize/internal/config/types.go b/tooling/templatize/internal/config/types.go deleted file mode 100644 index aafc3e593..000000000 --- a/tooling/templatize/internal/config/types.go +++ /dev/null @@ -1,29 +0,0 @@ -package config - -type configProviderImpl struct { - baseVariableOverrides *VariableOverrides - config string - region string - regionStamp string - cxStamp string -} - -type Variables map[string]interface{} - -type VariableOverrides struct { - Defaults Variables `yaml:"defaults"` - // key is the cloud alias - Overrides map[string]*CloudVariableOverride `yaml:"clouds"` -} - -type CloudVariableOverride struct { - Defaults Variables `yaml:"defaults"` - // key is the deploy env - Overrides map[string]*DeployEnvVariableOverride `yaml:"environments"` -} - -type DeployEnvVariableOverride struct { - Defaults Variables `yaml:"defaults"` - // key is the region name - Overrides map[string]Variables `yaml:"regions"` -} diff --git a/tooling/templatize/internal/end2end/e2e.go b/tooling/templatize/internal/end2end/e2e.go new file mode 100644 index 000000000..c9a76cfe4 --- /dev/null +++ b/tooling/templatize/internal/end2end/e2e.go @@ -0,0 +1,216 @@ +package testutil + +import ( + "context" + "fmt" + "os" + + "math/rand/v2" + + "gopkg.in/yaml.v2" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +var defaultRgName = "hcp-templatize" + +func shouldRunE2E() bool { + return os.Getenv("RUN_TEMPLATIZE_E2E") == "true" +} + +type E2E interface { + SetConfig(updates config.Variables) + UseRandomRG() func() error + AddBicepTemplate(template, templateFileName, paramfile, paramfileName string) + AddStep(step pipeline.Step, rg int) + SetOSArgs() + EnableDryRun() + Persist() error +} + +type bicepTemplate struct { + bicepFile string + bicepFileName string + paramFile string + paramFileName string +} + +type e2eImpl struct { + config config.Variables + makefile string + pipeline pipeline.Pipeline + biceps []bicepTemplate + schema string + tmpdir string + rgName string +} + +var _ E2E = &e2eImpl{} + +func newE2E(tmpdir string) e2eImpl { + imp := e2eImpl{ + tmpdir: tmpdir, + schema: `{"type": "object"}`, + config: config.Variables{ + "$schema": "schema.json", + "defaults": config.Variables{ + "region": "westus3", + "subscription": "ARO Hosted Control Planes (EA Subscription 1)", + "rg": defaultRgName, + }, + "clouds": config.Variables{ + "public": config.Variables{ + "defaults": config.Variables{}, + "environments": config.Variables{ + "dev": config.Variables{ + "defaults": config.Variables{}, + }, + }, + }, + }, + }, + pipeline: pipeline.Pipeline{ + ServiceGroup: "Microsoft.Azure.ARO.Test", + RolloutName: "Test Rollout", + ResourceGroups: []*pipeline.ResourceGroup{ + { + Name: "{{ .rg }}", + Subscription: "{{ .subscription }}", + }, + }, + }, + rgName: defaultRgName, + biceps: []bicepTemplate{}, + } + + imp.SetOSArgs() + return imp +} + +func GenerateRandomRGName() string { + rgSuffx := "" + if jobID := os.Getenv("JOB_ID"); jobID != "" { + rgSuffx = jobID + } + chars := []rune("abcdefghijklmnopqrstuvwxyz0123456789") + for i := 0; i < 3; i++ { + rgSuffx += string(chars[rand.IntN(len(chars))]) + } + return "templatize-e2e-" + rgSuffx +} + +func (e *e2eImpl) UseRandomRG() func() error { + e.rgName = GenerateRandomRGName() + e.SetConfig(config.Variables{"defaults": config.Variables{"rg": e.rgName}}) + + return func() error { + subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") + if err != nil { + return err + } + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return err + } + rgClient, err := armresources.NewResourceGroupsClient(subsriptionID, cred, nil) + if err != nil { + return err + } + _, err = rgClient.BeginDelete(context.Background(), e.rgName, nil) + return err + } +} + +func (e *e2eImpl) SetOSArgs() { + os.Args = []string{"test", + "--cloud", "public", + "--pipeline-file", e.tmpdir + "/pipeline.yaml", + "--config-file", e.tmpdir + "/config.yaml", + "--deploy-env", "dev", + "--no-persist-tag", + "--region", "westus3", + } +} + +func (e *e2eImpl) EnableDryRun() { + os.Args = append(os.Args, "--dry-run") +} + +func (e *e2eImpl) AddResourceGroup() { + numRgs := len(e.pipeline.ResourceGroups) + e.pipeline.ResourceGroups = append(e.pipeline.ResourceGroups, &pipeline.ResourceGroup{ + Name: fmt.Sprintf("{{ .rg }}-%d", numRgs+1), + Subscription: "{{ .subscription }}", + }, + ) +} + +func (e *e2eImpl) SetAKSName(aksName string) { + e.pipeline.ResourceGroups[0].AKSCluster = aksName +} + +func (e *e2eImpl) AddStep(step pipeline.Step, rg int) { + e.pipeline.ResourceGroups[rg].Steps = append(e.pipeline.ResourceGroups[rg].Steps, step) +} + +func (e *e2eImpl) SetConfig(updates config.Variables) { + config.MergeVariables(e.config, updates) +} + +func (e *e2eImpl) AddBicepTemplate(template, templateFileName, paramfile, paramfileName string) { + e.biceps = append(e.biceps, bicepTemplate{ + bicepFile: template, + bicepFileName: templateFileName, + paramFile: paramfile, + paramFileName: paramfileName, + }) +} + +func (e *e2eImpl) Persist() error { + if len(e.biceps) != 0 { + for _, b := range e.biceps { + + err := os.WriteFile(e.tmpdir+"/"+b.bicepFileName, []byte(b.bicepFile), 0644) + if err != nil { + return err + } + + err = os.WriteFile(e.tmpdir+"/"+b.paramFileName, []byte(b.paramFile), 0644) + if err != nil { + return err + } + } + } + + if e.makefile != "" { + err := os.WriteFile(e.tmpdir+"/Makefile", []byte(e.makefile), 0644) + if err != nil { + return err + } + } + + configBytes, err := yaml.Marshal(e.config) + if err != nil { + return fmt.Errorf("failed to marshal config: %w", err) + } + + err = os.WriteFile(e.tmpdir+"/config.yaml", configBytes, 0644) + if err != nil { + return err + } + + err = os.WriteFile(e.tmpdir+"/schema.json", []byte(e.schema), 0644) + if err != nil { + return err + } + + pipelineBytes, err := yaml.Marshal(e.pipeline) + if err != nil { + return fmt.Errorf("failed to marshal pipeline: %w", err) + } + return os.WriteFile(e.tmpdir+"/pipeline.yaml", []byte(pipelineBytes), 0644) +} diff --git a/tooling/templatize/internal/end2end/e2e_test.go b/tooling/templatize/internal/end2end/e2e_test.go new file mode 100644 index 000000000..94366e5da --- /dev/null +++ b/tooling/templatize/internal/end2end/e2e_test.go @@ -0,0 +1,408 @@ +package testutil + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/run" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" +) + +func persistAndRun(t *testing.T, e2eImpl E2E) { + err := e2eImpl.Persist() + assert.NilError(t, err) + + cmd, err := run.NewCommand() + assert.NilError(t, err) + + err = cmd.Execute() + assert.NilError(t, err) +} + +func TestE2EMake(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep( + pipeline.NewShellStep("test", "make test").WithVariables(pipeline.Variable{ + Name: "TEST_ENV", + ConfigRef: "test_env", + }), + 0, + ) + + e2eImpl.SetConfig(config.Variables{"defaults": config.Variables{"test_env": "test_env"}}) + + e2eImpl.makefile = ` +test: + echo ${TEST_ENV} > env.txt +` + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "test_env\n") +} + +func TestE2EKubernetes(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewShellStep("test", "kubectl get namespaces"), 0) + e2eImpl.SetAKSName("aro-hcp-aks") + + e2eImpl.SetConfig(config.Variables{"defaults": config.Variables{"rg": "hcp-underlay-dev-svc"}}) + + persistAndRun(t, &e2eImpl) +} + +func TestE2EArmDeploy(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewARMStep("test", "test.bicep", "test.bicepparm", "ResourceGroup"), 0) + cleanup := e2eImpl.UseRandomRG() + defer func() { + err := cleanup() + assert.NilError(t, err) + }() + + bicepFile := ` +param zoneName string +resource symbolicname 'Microsoft.Network/dnsZones@2018-05-01' = { + location: 'global' + name: zoneName +}` + paramFile := ` +using 'test.bicep' +param zoneName = 'e2etestarmdeploy.foo.bar.example.com' +` + e2eImpl.AddBicepTemplate(bicepFile, "test.bicep", paramFile, "test.bicepparm") + + persistAndRun(t, &e2eImpl) + + // Todo move to e2e module, if needed more than once + subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") + assert.NilError(t, err) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + assert.NilError(t, err) + + zonesClient, err := armdns.NewZonesClient(subsriptionID, cred, nil) + assert.NilError(t, err) + + zoneResp, err := zonesClient.Get(context.Background(), e2eImpl.rgName, "e2etestarmdeploy.foo.bar.example.com", nil) + assert.NilError(t, err) + assert.Equal(t, *zoneResp.Name, "e2etestarmdeploy.foo.bar.example.com") +} + +func TestE2EShell(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir, err := filepath.EvalSymlinks(t.TempDir()) + assert.NilError(t, err) + + e2eImpl := newE2E(tmpDir) + + e2eImpl.AddStep( + pipeline.NewShellStep("readInput", "/bin/echo ${PWD} > env.txt"), + 0, + ) + + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), tmpDir+"\n") +} + +func TestE2EArmDeployWithOutput(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + + e2eImpl.AddStep(pipeline.NewARMStep("createZone", "test.bicep", "test.bicepparm", "ResourceGroup"), 0) + + e2eImpl.AddStep(pipeline.NewShellStep( + "readInput", "echo ${zoneName} > env.txt", + ).WithVariables( + pipeline.Variable{ + Name: "zoneName", + Input: &pipeline.Input{ + Name: "zoneName", + Step: "createZone", + }, + }, + ), 0) + + cleanup := e2eImpl.UseRandomRG() + defer func() { + err := cleanup() + assert.NilError(t, err) + }() + + bicepFile := ` +param zoneName string +output zoneName string = zoneName` + paramFile := ` +using 'test.bicep' +param zoneName = 'e2etestarmdeploy.foo.bar.example.com' +` + e2eImpl.AddBicepTemplate(bicepFile, "test.bicep", paramFile, "test.bicepparm") + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "e2etestarmdeploy.foo.bar.example.com\n") +} + +func TestE2EArmDeployWithOutputToArm(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewARMStep("stepA", "testa.bicep", "testa.bicepparm", "ResourceGroup"), 0) + e2eImpl.AddStep(pipeline.NewARMStep("stepB", "testb.bicep", "testb.bicepparm", "ResourceGroup").WithVariables(pipeline.Variable{ + Name: "parameterB", + Input: &pipeline.Input{ + Name: "parameterA", + Step: "stepA", + }, + }), 0) + + e2eImpl.AddStep(pipeline.NewShellStep( + "readInput", "echo ${end} > env.txt", + ).WithVariables( + pipeline.Variable{ + Name: "end", + Input: &pipeline.Input{ + Name: "parameterC", + Step: "stepB", + }, + }, + ), 0) + + e2eImpl.AddBicepTemplate(` +param parameterA string +output parameterA string = parameterA`, + "testa.bicep", + ` +using 'testa.bicep' +param parameterA = 'Hello Bicep'`, + "testa.bicepparm") + + e2eImpl.AddBicepTemplate(` +param parameterB string +output parameterC string = parameterB +`, + "testb.bicep", + ` +using 'testb.bicep' +param parameterB = '< provided at runtime >' +`, + "testb.bicepparm") + + cleanup := e2eImpl.UseRandomRG() + defer func() { + err := cleanup() + assert.NilError(t, err) + }() + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "Hello Bicep\n") +} + +func TestE2EArmDeployWithOutputRGOverlap(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewARMStep("parameterA", "testa.bicep", "testa.bicepparm", "ResourceGroup"), 0) + + e2eImpl.AddResourceGroup() + + e2eImpl.AddStep(pipeline.NewShellStep("readInput", "echo ${end} > env.txt").WithVariables( + pipeline.Variable{ + Name: "end", + Input: &pipeline.Input{ + Name: "parameterA", + Step: "parameterA", + }, + }, + ), 1) + + e2eImpl.AddBicepTemplate(` +param parameterA string +output parameterA string = parameterA`, + "testa.bicep", + ` +using 'testa.bicep' +param parameterA = 'Hello Bicep'`, + "testa.bicepparm") + + cleanup := e2eImpl.UseRandomRG() + defer func() { + err := cleanup() + assert.NilError(t, err) + }() + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "Hello Bicep\n") +} + +func TestE2EArmDeploySubscriptionScope(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewARMStep("parameterA", "testa.bicep", "testa.bicepparm", "Subscription"), 0) + rgName := GenerateRandomRGName() + e2eImpl.AddBicepTemplate(fmt.Sprintf(` +targetScope='subscription' + +resource newRG 'Microsoft.Resources/resourceGroups@2024-03-01' = { + name: '%s' + location: 'westus3' +}`, rgName), + "testa.bicep", + "using 'testa.bicep'", + "testa.bicepparm") + + persistAndRun(t, &e2eImpl) + + subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") + assert.NilError(t, err) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + assert.NilError(t, err) + + rgClient, err := armresources.NewResourceGroupsClient(subsriptionID, cred, nil) + assert.NilError(t, err) + + _, err = rgClient.BeginDelete(context.Background(), rgName, nil) + assert.NilError(t, err) +} + +func TestE2EDryRun(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + + e2eImpl.AddStep(pipeline.NewARMStep("output", "test.bicep", "test.bicepparm", "ResourceGroup"), 0) + + bicepFile := ` +param zoneName string +resource symbolicname 'Microsoft.Network/dnsZones@2018-05-01' = { + location: 'global' + name: zoneName +}` + paramFile := ` +using 'test.bicep' +param zoneName = 'e2etestarmdeploy.foo.bar.example.com' +` + e2eImpl.AddBicepTemplate(bicepFile, "test.bicep", paramFile, "test.bicepparm") + + e2eImpl.EnableDryRun() + + persistAndRun(t, &e2eImpl) + + subsriptionID, err := pipeline.LookupSubscriptionID(context.Background(), "ARO Hosted Control Planes (EA Subscription 1)") + assert.NilError(t, err) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + assert.NilError(t, err) + + zonesClient, err := armdns.NewZonesClient(subsriptionID, cred, nil) + assert.NilError(t, err) + + _, err = zonesClient.Get(context.Background(), e2eImpl.rgName, "e2etestarmdeploy.foo.bar.example.com", nil) + assert.ErrorContains(t, err, "RESPONSE 404: 404 Not Found") +} + +func TestE2EOutputOnly(t *testing.T) { + // if !shouldRunE2E() { + // t.Skip("Skipping end-to-end tests") + // } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.NewARMStep("parameterA", "testa.bicep", "testa.bicepparm", "ResourceGroup").WithOutputOnly(), 0) + + e2eImpl.AddStep(pipeline.NewShellStep( + "readInput", "echo ${end} > env.txt", + ).WithVariables( + pipeline.Variable{ + Name: "end", + Input: &pipeline.Input{ + Name: "parameterA", + Step: "parameterA", + }, + }, + ).WithDryRun(pipeline.DryRun{ + Command: "echo ${end} > env.txt"}), + 0) + + e2eImpl.AddBicepTemplate(` +param parameterA string +output parameterA string = parameterA`, + "testa.bicep", + ` +using 'testa.bicep' +param parameterA = 'Hello Bicep'`, + "testa.bicepparm") + + e2eImpl.EnableDryRun() + + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "Hello Bicep\n") + +} diff --git a/tooling/templatize/internal/naming/azure.go b/tooling/templatize/internal/naming/azure.go deleted file mode 100644 index 3c99eb933..000000000 --- a/tooling/templatize/internal/naming/azure.go +++ /dev/null @@ -1,21 +0,0 @@ -package naming - -func AzureEventGridName(prefix string, suffixLength int, suffixDigestArgs ...string) (string, error) { - return suffixedName(prefix, "-", 24, suffixLength, suffixDigestArgs...) -} - -func AzurePostgresName(prefix string, suffixLength int, suffixDigestArgs ...string) (string, error) { - return suffixedName(prefix, "-", 60, suffixLength, suffixDigestArgs...) -} - -func AzureKeyVaultName(prefix string, suffixLength int, suffixDigestArgs ...string) (string, error) { - return suffixedName(prefix, "-", 24, suffixLength, suffixDigestArgs...) -} - -func AzureStorageAccountName(prefix string, suffixLength int, suffixDigestArgs ...string) (string, error) { - return suffixedName(prefix, "", 24, suffixLength, suffixDigestArgs...) -} - -func AzureCosmosDBName(prefix string, suffixLength int, suffixDigestArgs ...string) (string, error) { - return suffixedName(prefix, "-", 44, suffixLength, suffixDigestArgs...) -} diff --git a/tooling/templatize/internal/naming/common.go b/tooling/templatize/internal/naming/common.go deleted file mode 100644 index 7822ebb87..000000000 --- a/tooling/templatize/internal/naming/common.go +++ /dev/null @@ -1,39 +0,0 @@ -package naming - -import ( - "crypto/sha256" - "encoding/hex" - "fmt" -) - -func suffixDigest(length int, strs ...string) (string, error) { - combined := "" - for _, s := range strs { - combined += s - } - hash := sha256.Sum256([]byte(combined)) - hashedString := hex.EncodeToString(hash[:]) - if len(hashedString) < length { - return "", fmt.Errorf("suffix digest does not have the required length of %d", length) - } - return hashedString[:length], nil -} - -func suffixedName(prefix string, suffixDelim string, maxLength int, suffixLength int, suffixDigestArgs ...string) (string, error) { - name := prefix - if len(suffixDigestArgs) > 0 { - suffixDigest, err := suffixDigest(suffixLength, suffixDigestArgs...) - if err != nil { - return "", err - } - name = prefix + suffixDelim + suffixDigest - } - if len(name) > maxLength { - return "", fmt.Errorf("name '%s' is too long, max length is %d", name, maxLength) - } - return name, nil -} - -func UniqueString(length int, digestArgs ...string) (string, error) { - return suffixDigest(length, digestArgs...) -} diff --git a/tooling/templatize/internal/naming/common_test.go b/tooling/templatize/internal/naming/common_test.go deleted file mode 100644 index 686c66c5c..000000000 --- a/tooling/templatize/internal/naming/common_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package naming - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSuffixedName(t *testing.T) { - for _, testCase := range []struct { - name string - prefix string - suffixDigestArgs []string - maxLength int - suffixLength int - expected string - errorExpected bool - }{ - { - name: "no suffix", - prefix: "prefix", - suffixDigestArgs: []string{}, - maxLength: 10, - expected: "prefix", - }, - { - name: "no suffix - too long", - prefix: "prefix", - suffixDigestArgs: []string{}, - maxLength: 4, - expected: "", - errorExpected: true, - }, - { - name: "with suffix", - prefix: "prefix", - suffixDigestArgs: []string{"arg1"}, - maxLength: 10, - suffixLength: 3, - expected: "prefix-84f", - }, - { - name: "with suffix - too long", - prefix: "prefix", - suffixDigestArgs: []string{"arg1"}, - maxLength: 4, - suffixLength: 3, - expected: "", - errorExpected: true, - }, - { - name: "with multiple suffix args", - prefix: "prefix", - suffixDigestArgs: []string{"arg1", "arg2"}, - maxLength: 10, - suffixLength: 3, - expected: "prefix-cb9", - }, - } { - t.Run(testCase.name, func(t *testing.T) { - resourceName, err := suffixedName(testCase.prefix, "-", testCase.maxLength, testCase.suffixLength, testCase.suffixDigestArgs...) - if testCase.errorExpected { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - assert.Equal(t, testCase.expected, resourceName) - }) - } -} diff --git a/tooling/templatize/main.go b/tooling/templatize/main.go index 3982de580..4deee1e3f 100644 --- a/tooling/templatize/main.go +++ b/tooling/templatize/main.go @@ -1,38 +1,74 @@ package main import ( - "log" + "context" + "log/slog" "os" + "os/signal" + "syscall" + "github.com/go-logr/logr" "github.com/spf13/cobra" + "github.com/dusted-go/logging/prettylog" + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/generate" "github.com/Azure/ARO-HCP/tooling/templatize/cmd/inspect" + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline" ) func main() { + logger := createLogger(0) + + // Create a root context with the logger and signal handling + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() + + var logVerbosity int + cmd := &cobra.Command{ Use: "templatize", Short: "templatize", Long: "templatize", SilenceUsage: true, TraverseChildren: true, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + ctx = logr.NewContext(ctx, createLogger(logVerbosity)) + cmd.SetContext(ctx) + }, CompletionOptions: cobra.CompletionOptions{ HiddenDefaultCmd: true, }, - RunE: func(cmd *cobra.Command, args []string) error { - err := cmd.Help() - if err != nil { - return err - } - os.Exit(1) - return nil - }, } - cmd.AddCommand(generate.NewCommand()) - cmd.AddCommand(inspect.NewCommand()) + + cmd.PersistentFlags().IntVarP(&logVerbosity, "verbosity", "v", 0, "set the verbosity level") + + commands := []func() (*cobra.Command, error){ + generate.NewCommand, + inspect.NewCommand, + pipeline.NewCommand, + } + for _, newCmd := range commands { + c, err := newCmd() + if err != nil { + logger.Error(err, "failed to create command", "command", newCmd) + } + cmd.AddCommand(c) + } + + cmd.SetHelpCommand(&cobra.Command{Hidden: true}) if err := cmd.Execute(); err != nil { - log.Fatal(err) + logger.Error(err, "command failed") + os.Exit(1) } } + +func createLogger(verbosity int) logr.Logger { + prettyHandler := prettylog.NewHandler(&slog.HandlerOptions{ + Level: slog.Level(verbosity * -1), + AddSource: false, + ReplaceAttr: nil, + }) + return logr.FromSlogHandler(prettyHandler) +} diff --git a/tooling/templatize/pkg/aks/admin.go b/tooling/templatize/pkg/aks/admin.go new file mode 100644 index 000000000..3e8700f00 --- /dev/null +++ b/tooling/templatize/pkg/aks/admin.go @@ -0,0 +1,187 @@ +package aks + +import ( + "context" + "errors" + "fmt" + "os" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + armauthorization "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3" + "github.com/google/uuid" + auth "github.com/microsoft/kiota-authentication-azure-go" + msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" +) + +const ( + clusterAdminRoleID = "b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b" // Azure Kubernetes Service RBAC Cluster Admin +) + +type ClusterAdminAssignmentOptions struct { + Timeout time.Duration + CheckFrequency time.Duration +} + +func EnsureClusterAdmin(ctx context.Context, kubeconfigPath, subscriptionID, resourceGroupName, aksClusterName string, options *ClusterAdminAssignmentOptions) error { + if options == nil { + options = &ClusterAdminAssignmentOptions{ + Timeout: time.Duration(2 * time.Minute), + CheckFrequency: time.Duration(5 * time.Second), + } + } + + // Get the current user's object ID + userObjectID, err := getCurrentUserObjectID(ctx) + if err != nil { + return fmt.Errorf("failed to get current user object ID: %w", err) + } + + // Assign the Azure Kubernetes Service RBAC Cluster Admin role to the current user + err = assignClusterAdminRBACRole(ctx, subscriptionID, resourceGroupName, aksClusterName, userObjectID, clusterAdminRoleID) + if err != nil { + return fmt.Errorf("failed to assign cluster admin role: %w", err) + } + + // Validate assignment + err = CheckClusterAdminPermissions(ctx, kubeconfigPath) + if err == nil { + return nil + } + + // Wait for role assignment to be effective + fmt.Println("Wait for role assignment to be effective") + timeout := time.After(options.Timeout) + ticker := time.NewTicker(options.CheckFrequency) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-timeout: + return fmt.Errorf("timed out waiting for role assignment to be effective") + case <-ticker.C: + err = CheckClusterAdminPermissions(ctx, kubeconfigPath) + if err == nil { + fmt.Println("Cluster admin permissions are now effective") + return nil + } + fmt.Println("Waiting for role assignment to be effective...") + } + } +} + +func CheckClusterAdminPermissions(ctx context.Context, kubeconfigPath string) error { + clientset, err := createKubeClient(kubeconfigPath) + if err != nil { + return fmt.Errorf("failed to create Kubernetes client: %w", err) + } + + // Implement the logic to test cluster admin permissions + // by checking if the user can list pods in the default namespace + _, err = clientset.CoreV1().Pods("default").List(ctx, metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("failed to list pods in the default namespace: %w", err) + } + return nil +} + +func getCurrentUserObjectID(ctx context.Context) (string, error) { + + if os.Getenv("PRINCIPAL_ID") != "" { + return os.Getenv("PRINCIPAL_ID"), nil + } + + // Create a Graph client using Azure Credentials + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return "", fmt.Errorf("failed to obtain a credential: %w", err) + } + authProvider, err := auth.NewAzureIdentityAuthenticationProviderWithScopes(cred, []string{"https://graph.microsoft.com/.default"}) + if err != nil { + return "", err + } + adapter, err := msgraphsdk.NewGraphRequestAdapter(authProvider) + if err != nil { + return "", err + } + client := msgraphsdk.NewGraphServiceClient(adapter) + + // Get the current user + user, err := client.Me().Get(ctx, nil) + if err != nil { + return "", fmt.Errorf("failed to get current user: %w", err) + } + + // Extract the user ID + userID := user.GetId() + if userID == nil { + return "", fmt.Errorf("user ID is nil") + } + + return *userID, nil +} + +func assignClusterAdminRBACRole(ctx context.Context, subscriptionID, resourceGroupName, aksClusterName, userObjectID, roleID string) error { + // Create a new Azure identity client + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return fmt.Errorf("failed to obtain a credential: %w", err) + } + + // Create a new role assignments client + client, err := armauthorization.NewRoleAssignmentsClient(subscriptionID, cred, nil) + if err != nil { + return fmt.Errorf("failed to create role assignments client: %w", err) + } + + aksID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ContainerService/managedClusters/%s", subscriptionID, resourceGroupName, aksClusterName) + roleDefinitionID := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Authorization/roleDefinitions/%s", subscriptionID, roleID) + + // Define the role assignment parameters + parameters := armauthorization.RoleAssignmentCreateParameters{ + Properties: &armauthorization.RoleAssignmentProperties{ + RoleDefinitionID: to.Ptr(roleDefinitionID), + PrincipalID: to.Ptr(userObjectID), + }, + } + + // Create the role assignment + _, err = client.Create(ctx, aksID, uuid.New().String(), parameters, nil) + if err != nil { + var respErr *azcore.ResponseError + if errors.As(err, &respErr) && respErr.ErrorCode == "RoleAssignmentExists" { + // we could check if the roleassignment exists upfront but even when + // the role exists, checking for it is not always reliably detect it + // so there is no point why we should check. all our users have + // permissions to create such role assignments anyways + return nil + } + return fmt.Errorf("failed to create role assignment: %w", err) + } + + fmt.Println("Azure Kubernetes Service RBAC Cluster Admin role assignment created successfully") + return nil +} + +func createKubeClient(kubeconfigPath string) (*kubernetes.Clientset, error) { + // Load the kubeconfig file + config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) + if err != nil { + return nil, fmt.Errorf("failed to load kubeconfig file: %w", err) + } + + // Create the Kubernetes client + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("failed to create Kubernetes client: %w", err) + } + + return clientset, nil +} diff --git a/tooling/templatize/pkg/aks/kubeconfig.go b/tooling/templatize/pkg/aks/kubeconfig.go new file mode 100644 index 000000000..3baf53503 --- /dev/null +++ b/tooling/templatize/pkg/aks/kubeconfig.go @@ -0,0 +1,61 @@ +package aks + +import ( + "context" + "fmt" + "os" + "os/exec" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice" +) + +func GetKubeConfig(ctx context.Context, subscriptionID, resourceGroupName, aksClusterName string) (string, error) { + if aksClusterName == "" { + return "", fmt.Errorf("AKSClusterName is required to build a kubeconfig") + } + + // Create a new Azure identity client + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return "", fmt.Errorf("failed to obtain a credential: %v", err) + } + + // Create a new AKS client + client, err := armcontainerservice.NewManagedClustersClient(subscriptionID, cred, nil) + if err != nil { + return "", fmt.Errorf("failed to create AKS client: %v", err) + } + + // Get the cluster access credentials + resp, err := client.ListClusterUserCredentials(ctx, resourceGroupName, aksClusterName, nil) + if err != nil { + return "", fmt.Errorf("failed to get cluster access credentials: %v", err) + } + if len(resp.Kubeconfigs) == 0 { + return "", fmt.Errorf("no kubeconfig found") + } + kubeconfigContent := resp.Kubeconfigs[0].Value + + // store the kubeconfig content into a temporary file + // generate a unique temporary filename + tmpfile, err := os.CreateTemp("", "kubeconfig-*.yaml") + if err != nil { + return "", fmt.Errorf("failed to create temporary file for kubeconfig: %v", err) + } + defer tmpfile.Close() + + // store the kubeconfig content into the temporary file + if _, err := tmpfile.Write([]byte(kubeconfigContent)); err != nil { + return "", fmt.Errorf("failed to write to temporary kubeconfigfile %s: %v", tmpfile.Name(), err) + } + + // Run kubelogin to transform the kubeconfig + cmd := exec.CommandContext(ctx, "kubelogin", "convert-kubeconfig", "-l", "azurecli", "--kubeconfig", tmpfile.Name()) + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("failed to run kubelogin: %s %v", string(output), err) + } + + return tmpfile.Name(), nil +} diff --git a/tooling/templatize/pkg/config/config.go b/tooling/templatize/pkg/config/config.go new file mode 100644 index 000000000..41b2547b0 --- /dev/null +++ b/tooling/templatize/pkg/config/config.go @@ -0,0 +1,281 @@ +package config + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "text/template" + + "github.com/santhosh-tekuri/jsonschema/v6" + "gopkg.in/yaml.v3" +) + +func DefaultConfigReplacements() *ConfigReplacements { + return NewConfigReplacements("", "", "") +} + +func NewConfigReplacements(regionReplacement, regionShortReplacement, stampReplacement string) *ConfigReplacements { + return &ConfigReplacements{ + RegionReplacement: regionReplacement, + RegionShortReplacement: regionShortReplacement, + StampReplacement: stampReplacement, + } +} + +type ConfigReplacements struct { + RegionReplacement string + RegionShortReplacement string + StampReplacement string +} + +func (c *ConfigReplacements) AsMap() map[string]interface{} { + return map[string]interface{}{ + "ctx": map[string]interface{}{ + "region": c.RegionReplacement, + "regionShort": c.RegionShortReplacement, + "stamp": c.StampReplacement, + }, + } +} + +type ConfigProvider interface { + Validate(cloud, deployEnv string) error + GetVariables(cloud, deployEnv, region string, configReplacements *ConfigReplacements) (Variables, error) + GetDeployEnvVariables(cloud, deployEnv string, configReplacements *ConfigReplacements) (Variables, error) + GetRegions(cloud, deployEnv string) ([]string, error) + GetRegionOverrides(cloud, deployEnv, region string, configReplacements *ConfigReplacements) (Variables, error) +} + +func NewConfigProvider(config string) ConfigProvider { + return &configProviderImpl{ + config: config, + } +} + +func InterfaceToVariables(i interface{}) (Variables, bool) { + // Helper, that reduces need for reflection calls, i.e. MapIndex + // from: https://github.com/peterbourgon/mergemap/blob/master/mergemap.go + value := reflect.ValueOf(i) + if value.Kind() == reflect.Map { + m := Variables{} + for _, k := range value.MapKeys() { + v := value.MapIndex(k).Interface() + if nestedMap, ok := InterfaceToVariables(v); ok { + m[k.String()] = nestedMap + } else { + m[k.String()] = v + } + } + return m, true + } + return Variables{}, false +} + +// Merges variables, returns merged variables +// However the return value is only used for recursive updates on the map +// The actual merged variables are updated in the base map +func MergeVariables(base, override Variables) Variables { + for k, newValue := range override { + if baseValue, exists := base[k]; exists { + srcMap, srcMapOk := InterfaceToVariables(newValue) + dstMap, dstMapOk := InterfaceToVariables(baseValue) + if srcMapOk && dstMapOk { + newValue = MergeVariables(dstMap, srcMap) + } + } + base[k] = newValue + } + + return base +} + +// Needed to convert Variables to map[string]interface{} for jsonschema validation +// see: https://github.com/santhosh-tekuri/jsonschema/blob/boon/schema.go#L124 +func convertToInterface(variables Variables) map[string]any { + m := map[string]any{} + for k, v := range variables { + if subMap, ok := v.(Variables); ok { + m[k] = convertToInterface(subMap) + } else { + m[k] = v + } + } + return m +} + +func (cp *configProviderImpl) loadSchema() (any, error) { + schemaPath := cp.schema + if !filepath.IsAbs(schemaPath) { + schemaPath = filepath.Join(filepath.Dir(cp.config), schemaPath) + } + reader, err := os.Open(schemaPath) + if err != nil { + return nil, fmt.Errorf("failed to open schema file: %v", err) + } + + schema, err := jsonschema.UnmarshalJSON(reader) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal schema: %v", err) + } + + return schema, nil +} + +func (cp *configProviderImpl) validateSchema(variables Variables) error { + c := jsonschema.NewCompiler() + + schema, err := cp.loadSchema() + if err != nil { + return fmt.Errorf("failed to load schema: %v", err) + } + + err = c.AddResource(cp.schema, schema) + if err != nil { + return fmt.Errorf("failed to add schema resource: %v", err) + } + sch, err := c.Compile(cp.schema) + if err != nil { + return fmt.Errorf("failed to compile schema: %v", err) + } + + err = sch.Validate(convertToInterface(variables)) + if err != nil { + return fmt.Errorf("failed to validate schema: %v", err) + } + return nil +} + +func (cp *configProviderImpl) GetVariables(cloud, deployEnv, region string, configReplacements *ConfigReplacements) (Variables, error) { + variables, err := cp.GetDeployEnvVariables(cloud, deployEnv, configReplacements) + if err != nil { + return nil, err + } + + // region overrides + regionOverrides, err := cp.GetRegionOverrides(cloud, deployEnv, region, configReplacements) + if err != nil { + return nil, err + } + MergeVariables(variables, regionOverrides) + + // validate schema + err = cp.validateSchema(variables) + if err != nil { + return nil, err + } + return variables, nil +} + +func (cp *configProviderImpl) Validate(cloud, deployEnv string) error { + config, err := cp.loadConfig(DefaultConfigReplacements()) + if err != nil { + return err + } + if ok := config.HasCloud(cloud); !ok { + return fmt.Errorf("the cloud %s is not found in the config", cloud) + } + + if ok := config.HasDeployEnv(cloud, deployEnv); !ok { + return fmt.Errorf("the deployment env %s is not found under cloud %s", deployEnv, cloud) + } + + if !config.HasSchema() { + return fmt.Errorf("$schema not found in config") + } + return nil +} + +func (cp *configProviderImpl) GetDeployEnvVariables(cloud, deployEnv string, configReplacements *ConfigReplacements) (Variables, error) { + config, err := cp.loadConfig(configReplacements) + if err != nil { + return nil, err + } + err = cp.Validate(cloud, deployEnv) + if err != nil { + return nil, err + } + + variables := Variables{} + MergeVariables(variables, config.GetDefaults()) + MergeVariables(variables, config.GetCloudOverrides(cloud)) + MergeVariables(variables, config.GetDeployEnvOverrides(cloud, deployEnv)) + + cp.schema = config.GetSchema() + + return variables, nil +} + +func (cp *configProviderImpl) GetRegions(cloud, deployEnv string) ([]string, error) { + config, err := cp.loadConfig(DefaultConfigReplacements()) + if err != nil { + return nil, err + } + err = cp.Validate(cloud, deployEnv) + if err != nil { + return nil, err + } + regions := config.GetRegions(cloud, deployEnv) + return regions, nil +} + +func (cp *configProviderImpl) GetRegionOverrides(cloud, deployEnv, region string, configReplacements *ConfigReplacements) (Variables, error) { + config, err := cp.loadConfig(configReplacements) + if err != nil { + return nil, err + } + return config.GetRegionOverrides(cloud, deployEnv, region), nil +} + +func (cp *configProviderImpl) loadConfig(configReplacements *ConfigReplacements) (VariableOverrides, error) { + // TODO validate that field names are unique regardless of casing + // parse, execute and unmarshal the config file as a template to generate the final config file + rawContent, err := PreprocessFile(cp.config, configReplacements.AsMap()) + if err != nil { + return nil, err + } + + currentVariableOverrides := NewVariableOverrides() + if err := yaml.Unmarshal(rawContent, currentVariableOverrides); err == nil { + return currentVariableOverrides, nil + } else { + return nil, err + } +} + +// PreprocessFile reads and processes a gotemplate +// The path will be read as is. It parses the file as a template, and executes it with the provided variables. +func PreprocessFile(templateFilePath string, vars map[string]any) ([]byte, error) { + content, err := os.ReadFile(templateFilePath) + if err != nil { + return nil, fmt.Errorf("failed to read file %s: %w", templateFilePath, err) + } + processedContent, err := PreprocessContent(content, vars) + if err != nil { + return nil, fmt.Errorf("failed to preprocess file %s: %w", templateFilePath, err) + } + return processedContent, nil +} + +// PreprocessContent processes a gotemplate from memory +func PreprocessContent(content []byte, vars map[string]any) ([]byte, error) { + var tmplBytes bytes.Buffer + if err := PreprocessContentIntoWriter(content, vars, &tmplBytes); err != nil { + return nil, err + } + return tmplBytes.Bytes(), nil +} + +func PreprocessContentIntoWriter(content []byte, vars map[string]any, writer io.Writer) error { + tmpl, err := template.New("file").Parse(string(content)) + if err != nil { + return fmt.Errorf("failed to parse template: %w", err) + } + + if err := tmpl.Option("missingkey=error").Execute(writer, vars); err != nil { + return fmt.Errorf("failed to execute template: %w", err) + } + return nil +} diff --git a/tooling/templatize/pkg/config/config_test.go b/tooling/templatize/pkg/config/config_test.go new file mode 100644 index 000000000..e999ec7db --- /dev/null +++ b/tooling/templatize/pkg/config/config_test.go @@ -0,0 +1,310 @@ +package config + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/Azure/ARO-HCP/tooling/templatize/internal/testutil" +) + +func TestConfigProvider(t *testing.T) { + region := "uksouth" + regionShort := "uks" + stamp := "1" + + configProvider := NewConfigProvider("../../testdata/config.yaml") + + variables, err := configProvider.GetVariables("public", "int", region, NewConfigReplacements(region, regionShort, stamp)) + assert.NoError(t, err) + assert.NotNil(t, variables) + + // key is not in the config file + assert.Nil(t, variables["svc_resourcegroup"]) + + // key is in the config file, region constant value + assert.Equal(t, "uksouth", variables["test"]) + + // key is in the config file, default in INT, constant value + assert.Equal(t, "aro-hcp-int.azurecr.io/maestro-server:the-stable-one", variables["maestro_image"]) + + // key is in the config file, default, varaible value + assert.Equal(t, fmt.Sprintf("hcp-underlay-%s", regionShort), variables["regionRG"]) +} + +func TestInterfaceToVariable(t *testing.T) { + testCases := []struct { + name string + i interface{} + ok bool + expecetedVariables Variables + }{ + { + name: "empty interface", + ok: false, + expecetedVariables: Variables{}, + }, + { + name: "empty map", + i: map[string]interface{}{}, + ok: true, + expecetedVariables: Variables{}, + }, + { + name: "map", + i: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + ok: true, + expecetedVariables: Variables{ + "key1": "value1", + "key2": "value2", + }, + }, + { + name: "nested map", + i: map[string]interface{}{ + "key1": map[string]interface{}{ + "key2": "value2", + }, + }, + ok: true, + expecetedVariables: Variables{ + "key1": Variables{ + "key2": "value2", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + vars, ok := InterfaceToVariables(tc.i) + assert.Equal(t, tc.ok, ok) + assert.Equal(t, tc.expecetedVariables, vars) + }) + } +} + +func TestMergeVariable(t *testing.T) { + testCases := []struct { + name string + base Variables + override Variables + expected Variables + }{ + { + name: "nil base", + expected: nil, + }, + { + name: "empty base and override", + base: Variables{}, + expected: Variables{}, + }, + { + name: "merge into empty base", + base: Variables{}, + override: Variables{"key1": "value1"}, + expected: Variables{"key1": "value1"}, + }, + { + name: "merge into base", + base: Variables{"key1": "value1"}, + override: Variables{"key2": "value2"}, + expected: Variables{"key1": "value1", "key2": "value2"}, + }, + { + name: "override base, change schema", + base: Variables{"key1": Variables{"key2": "value2"}}, + override: Variables{"key1": "value1"}, + expected: Variables{"key1": "value1"}, + }, + { + name: "merge into sub map", + base: Variables{"key1": Variables{"key2": "value2"}}, + override: Variables{"key1": Variables{"key3": "value3"}}, + expected: Variables{"key1": Variables{"key2": "value2", "key3": "value3"}}, + }, + { + name: "override sub map value", + base: Variables{"key1": Variables{"key2": "value2"}}, + override: Variables{"key1": Variables{"key2": "value3"}}, + expected: Variables{"key1": Variables{"key2": "value3"}}, + }, + { + name: "override nested sub map", + base: Variables{"key1": Variables{"key2": Variables{"key3": "value3"}}}, + override: Variables{"key1": Variables{"key2": Variables{"key3": "value4"}}}, + expected: Variables{"key1": Variables{"key2": Variables{"key3": "value4"}}}, + }, + { + name: "override nested sub map multiple levels", + base: Variables{"key1": Variables{"key2": Variables{"key3": "value3"}}}, + override: Variables{"key1": Variables{"key2": Variables{"key4": "value4"}}, "key5": "value5"}, + expected: Variables{"key1": Variables{"key2": Variables{"key3": "value3", "key4": "value4"}}, "key5": "value5"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := MergeVariables(tc.base, tc.override) + assert.Equal(t, tc.expected, result) + }) + } + +} + +func TestLoadSchema(t *testing.T) { + testDirs := t.TempDir() + + err := os.WriteFile(testDirs+"/schema.json", []byte(`{"type": "object"}`), 0644) + assert.Nil(t, err) + + configProvider := configProviderImpl{} + configProvider.schema = testDirs + "/schema.json" + + schema, err := configProvider.loadSchema() + assert.Nil(t, err) + assert.NotNil(t, schema) + assert.Equal(t, map[string]any{"type": "object"}, schema) +} + +func TestLoadSchemaError(t *testing.T) { + testDirs := t.TempDir() + + err := os.WriteFile(testDirs+"/schma.json", []byte(`{"type": "object"}`), 0644) + assert.Nil(t, err) + + configProvider := configProviderImpl{} + configProvider.schema = testDirs + "/schema.json" + _, err = configProvider.loadSchema() + assert.NotNil(t, err) +} + +func TestValidateSchema(t *testing.T) { + testSchema := `{ + "type": "object", + "properties": { + "key1": { + "type": "string" + } + }, + "additionalProperties": false +}` + + testDirs := t.TempDir() + + err := os.WriteFile(testDirs+"/schema.json", []byte(testSchema), 0644) + assert.Nil(t, err) + + configProvider := configProviderImpl{} + configProvider.schema = "schema.json" + configProvider.config = testDirs + "/config.yaml" + + err = configProvider.validateSchema(map[string]any{"foo": "bar"}) + assert.NotNil(t, err) + assert.ErrorContains(t, err, "additional properties 'foo' not allowed") + + err = configProvider.validateSchema(map[string]any{"key1": "bar"}) + assert.Nil(t, err) +} + +func TestConvertToInterface(t *testing.T) { + vars := Variables{ + "key1": "value1", + "key2": Variables{ + "key3": "value3", + }, + } + + expected := map[string]any{ + "key1": "value1", + "key2": map[string]any{ + "key3": "value3", + }, + } + + result := convertToInterface(vars) + assert.Equal(t, expected, result) + assert.IsType(t, expected, map[string]any{}) + assert.IsType(t, expected["key2"], map[string]any{}) +} + +func TestPreprocessContent(t *testing.T) { + fileContent, err := os.ReadFile("../../testdata/test.bicepparam") + assert.Nil(t, err) + + processed, err := PreprocessContent( + fileContent, + map[string]any{ + "regionRG": "bahamas", + "clusterService": map[string]any{ + "imageTag": "cs-image", + }, + }, + ) + assert.Nil(t, err) + testutil.CompareWithFixture(t, processed, testutil.WithExtension(".bicepparam")) +} + +func TestPreprocessContentMissingKey(t *testing.T) { + testCases := []struct { + name string + content string + vars map[string]any + shouldFail bool + }{ + { + name: "missing key", + content: "foo: {{ .bar }}", + vars: map[string]any{ + "baz": "bar", + }, + shouldFail: true, + }, + { + name: "missing nested key", + content: "foo: {{ .bar.baz }}", + vars: map[string]any{ + "baz": "bar", + }, + shouldFail: true, + }, + { + name: "no missing key", + content: "foo: {{ .bar }}", + vars: map[string]any{ + "bar": "bar", + }, + shouldFail: false, + }, + { + name: "no missing nested key", + content: "foo: {{ .bar.baz }}", + vars: map[string]any{ + "bar": map[string]any{ + "baz": "baz", + }, + }, + shouldFail: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := PreprocessContent( + []byte(tc.content), + tc.vars, + ) + if tc.shouldFail { + assert.NotNil(t, err) + } else { + assert.Nil(t, err) + } + }) + } +} diff --git a/tooling/templatize/pkg/config/types.go b/tooling/templatize/pkg/config/types.go new file mode 100644 index 000000000..00b4fec67 --- /dev/null +++ b/tooling/templatize/pkg/config/types.go @@ -0,0 +1,138 @@ +package config + +import ( + "fmt" + "strings" +) + +type configProviderImpl struct { + config string + schema string +} + +type Variables map[string]any + +func (v Variables) GetByPath(path string) (any, bool) { + keys := strings.Split(path, ".") + var current any = v + + for _, key := range keys { + if m, ok := current.(Variables); ok { + current, ok = m[key] + if !ok { + return nil, false + } + } else { + return nil, false + } + } + + return current, true +} + +func NewVariableOverrides() VariableOverrides { + return &variableOverrides{} +} + +type VariableOverrides interface { + GetDefaults() Variables + GetCloudOverrides(cloud string) Variables + GetDeployEnvOverrides(cloud, deployEnv string) Variables + GetRegionOverrides(cloud, deployEnv, region string) Variables + GetRegions(cloud, deployEnv string) []string + GetSchema() string + HasSchema() bool + HasCloud(cloud string) bool + HasDeployEnv(cloud, deployEnv string) bool +} + +type variableOverrides struct { + Schema string `yaml:"$schema"` + Defaults Variables `yaml:"defaults"` + // key is the cloud alias + Overrides map[string]*struct { + Defaults Variables `yaml:"defaults"` + // key is the deploy env + Overrides map[string]*struct { + Defaults Variables `yaml:"defaults"` + // key is the region name + Overrides map[string]Variables `yaml:"regions"` + } `yaml:"environments"` + } `yaml:"clouds"` +} + +func (vo *variableOverrides) GetSchema() string { + return vo.Schema +} + +func (vo *variableOverrides) HasSchema() bool { + return vo.Schema != "" +} + +func (vo *variableOverrides) GetDefaults() Variables { + return vo.Defaults +} + +func (vo *variableOverrides) HasCloud(cloud string) bool { + _, ok := vo.Overrides[cloud] + return ok +} + +func (vo *variableOverrides) GetCloudOverrides(cloud string) Variables { + if cloudOverride, ok := vo.Overrides[cloud]; ok { + return cloudOverride.Defaults + } + return Variables{} +} + +func (vo *variableOverrides) HasDeployEnv(cloud, deployEnv string) bool { + if cloudOverride, ok := vo.Overrides[cloud]; ok { + _, ok := cloudOverride.Overrides[deployEnv] + return ok + } + return false +} + +func (vo *variableOverrides) GetDeployEnvOverrides(cloud, deployEnv string) Variables { + if cloudOverride, ok := vo.Overrides[cloud]; ok { + if deployEnvOverride, ok := cloudOverride.Overrides[deployEnv]; ok { + return deployEnvOverride.Defaults + } + } + return Variables{} +} + +func (vo *variableOverrides) GetRegions(cloud, deployEnv string) []string { + deployEnvOverrides, err := vo.getAllDeployEnvRegionOverrides(cloud, deployEnv) + if err != nil { + return []string{} + } + regions := make([]string, 0, len(deployEnvOverrides)) + for region := range deployEnvOverrides { + regions = append(regions, region) + } + return regions +} + +func (vo *variableOverrides) getAllDeployEnvRegionOverrides(cloud, deployEnv string) (map[string]Variables, error) { + if cloudOverride, ok := vo.Overrides[cloud]; ok { + if deployEnvOverride, ok := cloudOverride.Overrides[deployEnv]; ok { + return deployEnvOverride.Overrides, nil + } else { + return nil, fmt.Errorf("deploy env %s not found under cloud %s in config", deployEnv, cloud) + } + } + return nil, fmt.Errorf("cloud %s not found in config", cloud) +} + +func (vo *variableOverrides) GetRegionOverrides(cloud, deployEnv, region string) Variables { + regionOverrides, err := vo.getAllDeployEnvRegionOverrides(cloud, deployEnv) + if err != nil { + return Variables{} + } + if regionOverrides, ok := regionOverrides[region]; ok { + return regionOverrides + } else { + return Variables{} + } +} diff --git a/tooling/templatize/pkg/config/types_test.go b/tooling/templatize/pkg/config/types_test.go new file mode 100644 index 000000000..8285e3734 --- /dev/null +++ b/tooling/templatize/pkg/config/types_test.go @@ -0,0 +1,45 @@ +package config + +import "testing" + +func TestGetByPath(t *testing.T) { + tests := []struct { + name string + vars Variables + path string + want any + found bool + }{ + { + name: "simple", + vars: Variables{ + "key": "value", + }, + path: "key", + want: "value", + found: true, + }, + { + name: "nested", + vars: Variables{ + "key": Variables{ + "key": "value", + }, + }, + path: "key.key", + want: "value", + found: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, found := tt.vars.GetByPath(tt.path) + if got != tt.want { + t.Errorf("Variables.GetByPath() got = %v, want %v", got, tt.want) + } + if found != tt.found { + t.Errorf("Variables.GetByPath() found = %v, want %v", found, tt.found) + } + }) + } +} diff --git a/tooling/templatize/pkg/ev2/mapping.go b/tooling/templatize/pkg/ev2/mapping.go new file mode 100644 index 000000000..30db47326 --- /dev/null +++ b/tooling/templatize/pkg/ev2/mapping.go @@ -0,0 +1,70 @@ +package ev2 + +import ( + "fmt" + "reflect" + "strings" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +type PlaceholderGenerator func(key []string, valueType reflect.Type) (flattenedKey string, replaceVar string) + +// NewDunderPlaceholders returns a PlaceholderGenerator function that generates +// placeholder strings by joining the provided key elements with underscores +// and surrounding them with double underscores. +// +// Example: +// +// key := []string{"foo", "bar"} +// flattenedKey, replaceVar := NewDunderPlaceholders()(key, nil) +// // flattenedKey and replaceVar will both be "__foo_bar__" +func NewDunderPlaceholders() PlaceholderGenerator { + return func(key []string, _ reflect.Type) (flattenedKey string, replaceVar string) { + flattenedKey = fmt.Sprintf("__%s__", strings.Join(key, ".")) + replaceVar = flattenedKey + return + } +} + +// NewBicepParamPlaceholders creates a new PlaceholderGenerator that generates +// placeholders for Bicep parameters. It uses DunderPlaceholders to generate +// the initial placeholders and then wraps non-string values with the "any()" +// function for general EV2 bicep happyness. +// +// Returns: +// +// A PlaceholderGenerator function that takes a key and value, and returns +// a flattened key and a replacement variable for bicep parameter usage within EV2. +func NewBicepParamPlaceholders() PlaceholderGenerator { + dunder := NewDunderPlaceholders() + return func(key []string, valueType reflect.Type) (flattenedKey string, replaceVar string) { + flattenedKey, replaceVar = dunder(key, valueType) + if valueType.Kind() != reflect.String { + replaceVar = fmt.Sprintf("any('%s')", replaceVar) + } + return + } +} + +func EV2Mapping(input config.Variables, placeholderGenerator PlaceholderGenerator, prefix []string) (map[string]string, map[string]interface{}) { + vars, _ := config.InterfaceToVariables(input) + output := map[string]string{} + replaced := map[string]interface{}{} + for key, value := range vars { + nestedKey := append(prefix, key) + nested, ok := value.(config.Variables) + if ok { + flattened, replacement := EV2Mapping(nested, placeholderGenerator, nestedKey) + for index, what := range flattened { + output[index] = what + } + replaced[key] = replacement + } else { + flattenedKey, replaceVar := placeholderGenerator(nestedKey, reflect.TypeOf(value)) + output[flattenedKey] = strings.Join(nestedKey, ".") + replaced[key] = replaceVar + } + } + return output, replaced +} diff --git a/tooling/templatize/pkg/ev2/mapping_test.go b/tooling/templatize/pkg/ev2/mapping_test.go new file mode 100644 index 000000000..f6975714f --- /dev/null +++ b/tooling/templatize/pkg/ev2/mapping_test.go @@ -0,0 +1,152 @@ +package ev2 + +import ( + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func TestMapping(t *testing.T) { + testData := config.Variables{ + "key1": "value1", + "key2": 42, + "key3": true, + "parent": map[string]interface{}{ + "nested": "nestedvalue", + "nestedInt": 42, + "deeper": map[string]interface{}{ + "deepest": "deepestvalue", + }, + }, + } + tests := []struct { + name string + generator PlaceholderGenerator + expectedFlattened map[string]string + expectedReplace map[string]interface{} + }{ + { + name: "dunder", + generator: NewDunderPlaceholders(), + expectedFlattened: map[string]string{ + "__key1__": "key1", + "__key2__": "key2", + "__key3__": "key3", + "__parent.nested__": "parent.nested", + "__parent.nestedInt__": "parent.nestedInt", + "__parent.deeper.deepest__": "parent.deeper.deepest", + }, + expectedReplace: map[string]interface{}{ + "key1": "__key1__", + "key2": "__key2__", + "key3": "__key3__", + "parent": map[string]interface{}{ + "nested": "__parent.nested__", + "nestedInt": "__parent.nestedInt__", + "deeper": map[string]interface{}{"deepest": "__parent.deeper.deepest__"}, + }, + }, + }, + { + name: "bicep", + generator: NewBicepParamPlaceholders(), + expectedFlattened: map[string]string{ + "__key1__": "key1", + "__key2__": "key2", + "__key3__": "key3", + "__parent.nested__": "parent.nested", + "__parent.nestedInt__": "parent.nestedInt", + "__parent.deeper.deepest__": "parent.deeper.deepest", + }, + expectedReplace: map[string]interface{}{ + "key1": "__key1__", + "key2": "any('__key2__')", + "key3": "any('__key3__')", + "parent": map[string]interface{}{ + "nested": "__parent.nested__", + "nestedInt": "any('__parent.nestedInt__')", + "deeper": map[string]interface{}{"deepest": "__parent.deeper.deepest__"}, + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + flattened, replace := EV2Mapping(testData, tc.generator, []string{}) + if diff := cmp.Diff(tc.expectedFlattened, flattened); diff != "" { + t.Errorf("got incorrect flattened: %v", diff) + } + if diff := cmp.Diff(tc.expectedReplace, replace); diff != "" { + t.Errorf("got incorrect replace: %v", diff) + } + }) + } +} + +func TestPlaceholderGenerators(t *testing.T) { + tests := []struct { + name string + generator PlaceholderGenerator + key []string + valueType reflect.Type + expectedFlattened string + expectedReplace string + }{ + { + name: "dunder", + generator: NewDunderPlaceholders(), + key: []string{"foo", "bar"}, + valueType: nil, + expectedFlattened: "__foo.bar__", + expectedReplace: "__foo.bar__", + }, + { + name: "bicep string param", + generator: NewBicepParamPlaceholders(), + key: []string{"foo", "bar"}, + valueType: reflect.TypeOf("baz"), + expectedFlattened: "__foo.bar__", + expectedReplace: "__foo.bar__", + }, + { + name: "bicep int param", + generator: NewBicepParamPlaceholders(), + key: []string{"foo", "bar"}, + valueType: reflect.TypeOf(42), + expectedFlattened: "__foo.bar__", + expectedReplace: "any('__foo.bar__')", + }, + { + name: "bicep bool param", + generator: NewBicepParamPlaceholders(), + key: []string{"foo", "bar"}, + valueType: reflect.TypeOf(true), + expectedFlattened: "__foo.bar__", + expectedReplace: "any('__foo.bar__')", + }, + { + name: "bicep array param", + generator: NewBicepParamPlaceholders(), + key: []string{"foo", "bar"}, + valueType: reflect.TypeOf([]any{}), + expectedFlattened: "__foo.bar__", + expectedReplace: "any('__foo.bar__')", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + flattened, replace := tc.generator(tc.key, tc.valueType) + if flattened != tc.expectedFlattened { + t.Errorf("got incorrect flattened: %v", flattened) + } + if replace != tc.expectedReplace { + t.Errorf("got incorrect replace: %v", replace) + } + }) + } +} diff --git a/tooling/templatize/pkg/ev2/pipeline.go b/tooling/templatize/pkg/ev2/pipeline.go new file mode 100644 index 000000000..cb8681c58 --- /dev/null +++ b/tooling/templatize/pkg/ev2/pipeline.go @@ -0,0 +1,121 @@ +package ev2 + +import ( + "fmt" + "os" + "path/filepath" + + "gopkg.in/yaml.v3" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +const precompiledPrefix = "ev2-precompiled-" + +func PrecompilePipelineFileForEV2(pipelineFilePath string, vars config.Variables) (string, error) { + precompiledPipeline, err := PrecompilePipelineForEV2(pipelineFilePath, vars) + if err != nil { + return "", err + } + + // store as new file + pipelineBytes, err := yaml.Marshal(precompiledPipeline) + if err != nil { + return "", err + } + err = os.WriteFile(precompiledPipeline.PipelineFilePath(), pipelineBytes, 0644) + if err != nil { + return "", err + } + + return precompiledPipeline.PipelineFilePath(), nil +} + +func PrecompilePipelineForEV2(pipelineFilePath string, vars config.Variables) (*pipeline.Pipeline, error) { + // load the pipeline and referenced files + originalPipeline, err := pipeline.NewPipelineFromFile(pipelineFilePath, vars) + if err != nil { + return nil, err + } + referencedFiles, err := readReferencedPipelineFiles(originalPipeline) + if err != nil { + return nil, fmt.Errorf("failed to read referenced files of pipeline %s: %w", originalPipeline.PipelineFilePath(), err) + } + + // precompile the pipeline and referenced files + processedPipeline, processedFiles, err := processPipelineForEV2(originalPipeline, referencedFiles, vars) + if err != nil { + return nil, err + } + + // store the processed files to disk relative to the pipeline directory + for filePath, content := range processedFiles { + absFilePath, err := processedPipeline.AbsoluteFilePath(filePath) + if err != nil { + return nil, fmt.Errorf("failed to get absolute file path for %q: %w", filePath, err) + } + err = os.WriteFile(absFilePath, content, 0644) + if err != nil { + return nil, fmt.Errorf("failed to write precompiled file %q: %w", filePath, err) + } + } + + return processedPipeline, nil +} + +func readReferencedPipelineFiles(p *pipeline.Pipeline) (map[string][]byte, error) { + referencedFiles := make(map[string][]byte) + for _, rg := range p.ResourceGroups { + for _, step := range rg.Steps { + switch concreteStep := step.(type) { + case *pipeline.ARMStep: + absFilePath, err := p.AbsoluteFilePath(concreteStep.Parameters) + if err != nil { + return nil, fmt.Errorf("failed to get absolute file path for %q: %w", concreteStep.Parameters, err) + } + paramFileContent, err := os.ReadFile(absFilePath) + if err != nil { + return nil, fmt.Errorf("failed to read parameter file %q: %w", concreteStep.Parameters, err) + } + referencedFiles[concreteStep.Parameters] = paramFileContent + } + } + } + return referencedFiles, nil +} + +func processPipelineForEV2(p *pipeline.Pipeline, referencedFiles map[string][]byte, vars config.Variables) (*pipeline.Pipeline, map[string][]byte, error) { + processingPipeline, err := p.DeepCopy(buildPrefixedFilePath(p.PipelineFilePath(), precompiledPrefix)) + if err != nil { + return nil, nil, err + } + processedFiles := make(map[string][]byte) + _, scopeBoundBicepParamVars := EV2Mapping(vars, NewBicepParamPlaceholders(), []string{}) + for _, rg := range processingPipeline.ResourceGroups { + for _, step := range rg.Steps { + // preprocess the parameters file with scopebinding variables + switch concreteStep := step.(type) { + case *pipeline.ARMStep: + paramFileContent, ok := referencedFiles[concreteStep.Parameters] + if !ok { + return nil, nil, fmt.Errorf("parameter file %q not found", concreteStep.Parameters) + } + preprocessedBytes, err := config.PreprocessContent(paramFileContent, scopeBoundBicepParamVars) + if err != nil { + return nil, nil, err + } + newParameterFilePath := buildPrefixedFilePath(concreteStep.Parameters, precompiledPrefix) + processedFiles[newParameterFilePath] = preprocessedBytes + concreteStep.Parameters = newParameterFilePath + } + } + } + return processingPipeline, processedFiles, nil +} + +func buildPrefixedFilePath(path, prefix string) string { + dir := filepath.Dir(path) + base := filepath.Base(path) + return filepath.Join(dir, prefix+base) +} diff --git a/tooling/templatize/pkg/ev2/pipeline_test.go b/tooling/templatize/pkg/ev2/pipeline_test.go new file mode 100644 index 000000000..eb1d7ee87 --- /dev/null +++ b/tooling/templatize/pkg/ev2/pipeline_test.go @@ -0,0 +1,51 @@ +package ev2 + +import ( + "strings" + "testing" + + "gopkg.in/yaml.v3" + + "github.com/Azure/ARO-HCP/tooling/templatize/internal/testutil" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func TestProcessPipelineForEV2(t *testing.T) { + configProvider := config.NewConfigProvider("../../testdata/config.yaml") + vars, err := configProvider.GetVariables("public", "int", "", NewEv2ConfigReplacements()) + if err != nil { + t.Errorf("failed to get variables: %v", err) + } + originalPipeline, err := pipeline.NewPipelineFromFile("../../testdata/pipeline.yaml", vars) + if err != nil { + t.Errorf("failed to read new pipeline: %v", err) + } + files := make(map[string][]byte) + files["test.bicepparam"] = []byte( + strings.Join( + []string{ + "param regionRG = '{{ .regionRG }}'", + "param replicas = {{ .clusterService.replicas }}", + }, + "\n", + ), + ) + + newPipeline, newFiles, err := processPipelineForEV2(originalPipeline, files, vars) + if err != nil { + t.Errorf("failed to precompile pipeline: %v", err) + } + + // verify pipeline + pipelineContent, err := yaml.Marshal(newPipeline) + if err != nil { + t.Errorf("failed to marshal processed pipeline: %v", err) + } + testutil.CompareWithFixture(t, pipelineContent, testutil.WithExtension("pipeline.yaml")) + + // verify referenced files + for filePath, content := range newFiles { + testutil.CompareWithFixture(t, content, testutil.WithExtension(filePath)) + } +} diff --git a/tooling/templatize/pkg/ev2/utils.go b/tooling/templatize/pkg/ev2/utils.go new file mode 100644 index 000000000..5b4e74c7b --- /dev/null +++ b/tooling/templatize/pkg/ev2/utils.go @@ -0,0 +1,62 @@ +package ev2 + +import ( + "fmt" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +// +// This package contains helper functions to extract EV2 conformant data from a config.yaml file. +// + +func NewEv2ConfigReplacements() *config.ConfigReplacements { + return config.NewConfigReplacements( + "$location()", + "$(regionShortName)", + "$stamp()", + ) +} + +// GetNonRegionalServiceConfigVariables returns all non-regional configuration variables of a config.yaml file. +// Non regional means: global variables + cloud overrides + deployment environment overrides - but not regional overrides. +// The variable values are formatted to contain EV2 $location(), $stamp() and $(serviceConfigVar) variables. +// This function is useful to get the variables to fill the `Settings` section of an EV2 `ServiceConfig.json“ +func GetNonRegionalServiceConfigVariables(configProvider config.ConfigProvider, cloud, deployEnv string) (config.Variables, error) { + return configProvider.GetVariables(cloud, deployEnv, "", NewEv2ConfigReplacements()) +} + +// GetRegionalServiceConfigVariableOverrides returns the regional overrides of a config.yaml file. +// The variable values are formatted to contain EV2 $location(), $stamp() and $(serviceConfigVar) variables. +// This function is useful to get the variables to fill the `Geographies/Regions` section of an EV2 `ServiceConfig.json` +func GetRegionalServiceConfigVariableOverrides(configProvider config.ConfigProvider, cloud, deployEnv string) (map[string]config.Variables, error) { + regions, err := configProvider.GetRegions(cloud, deployEnv) + if err != nil { + return nil, err + } + overrides := make(map[string]config.Variables) + for _, region := range regions { + regionOverrides, err := configProvider.GetRegionOverrides(cloud, deployEnv, region, NewEv2ConfigReplacements()) + if err != nil { + return nil, err + } + overrides[region] = regionOverrides + } + return overrides, nil +} + +// ScopeBindingVariables retrieves and processes configuration variables for a given cloud and deployment environment. +// It uses the provided configProvider to fetch the variables, flattens them into a __VAR__ = $config(var) formatted map. +// This function is useful to get the find/replace pairs for an EV2 `ScopeBinding.json` +func ScopeBindingVariables(configProvider config.ConfigProvider, cloud, deployEnv string) (map[string]string, error) { + vars, err := configProvider.GetVariables(cloud, deployEnv, "", NewEv2ConfigReplacements()) + if err != nil { + return nil, err + } + flattened, _ := EV2Mapping(vars, NewDunderPlaceholders(), []string{}) + variables := make(map[string]string) + for key, value := range flattened { + variables[key] = fmt.Sprintf("$config(%s)", value) + } + return variables, nil +} diff --git a/tooling/templatize/pkg/ev2/utils_test.go b/tooling/templatize/pkg/ev2/utils_test.go new file mode 100644 index 000000000..8296d6345 --- /dev/null +++ b/tooling/templatize/pkg/ev2/utils_test.go @@ -0,0 +1,40 @@ +package ev2 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func TestScopeBindingVariables(t *testing.T) { + configProvider := config.NewConfigProvider("../../testdata/config.yaml") + vars, err := ScopeBindingVariables(configProvider, "public", "int") + if err != nil { + t.Fatalf("ScopeBindingVariables failed: %v", err) + } + expectedVars := map[string]string{ + "__aksName__": "$config(aksName)", + "__childZone__": "$config(childZone)", + "__globalRG__": "$config(globalRG)", + "__imageSyncRG__": "$config(imageSyncRG)", + "__maestro_helm_chart__": "$config(maestro_helm_chart)", + "__maestro_image__": "$config(maestro_image)", + "__managementClusterRG__": "$config(managementClusterRG)", + "__managementClusterSubscription__": "$config(managementClusterSubscription)", + "__parentZone__": "$config(parentZone)", + "__provider__": "$config(provider)", + "__region__": "$config(region)", + "__regionRG__": "$config(regionRG)", + "__serviceClusterRG__": "$config(serviceClusterRG)", + "__serviceClusterSubscription__": "$config(serviceClusterSubscription)", + "__vaultBaseUrl__": "$config(vaultBaseUrl)", + "__clusterService.imageTag__": "$config(clusterService.imageTag)", + "__clusterService.replicas__": "$config(clusterService.replicas)", + } + + if diff := cmp.Diff(expectedVars, vars); diff != "" { + t.Errorf("got incorrect vars: %v", diff) + } +} diff --git a/tooling/templatize/pkg/pipeline/arm.go b/tooling/templatize/pkg/pipeline/arm.go new file mode 100644 index 000000000..b0637a074 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/arm.go @@ -0,0 +1,306 @@ +package pipeline + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/go-logr/logr" +) + +type armClient struct { + deploymentClient *armresources.DeploymentsClient + resourceGroupClient *armresources.ResourceGroupsClient + deploymentRetryWaitTime int + + Region string + GetDeployment func(ctx context.Context, rgName, deploymentName string) (armresources.DeploymentsClientGetResponse, error) +} + +func newArmClient(subscriptionID, region string) *armClient { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return nil + } + deploymentClient, err := armresources.NewDeploymentsClient(subscriptionID, cred, nil) + if err != nil { + return nil + } + resourceGroupClient, err := armresources.NewResourceGroupsClient(subscriptionID, cred, nil) + if err != nil { + return nil + } + return &armClient{ + deploymentClient: deploymentClient, + deploymentRetryWaitTime: 15, + resourceGroupClient: resourceGroupClient, + Region: region, + GetDeployment: func(ctx context.Context, rgName, deploymentName string) (armresources.DeploymentsClientGetResponse, error) { + return deploymentClient.Get(ctx, rgName, deploymentName, nil) + }, + } +} + +func (a *armClient) getExistingDeployment(ctx context.Context, rgName, deploymentName string) (*armresources.DeploymentsClientGetResponse, error) { + resp, err := a.GetDeployment(ctx, rgName, deploymentName) + if err != nil && !strings.Contains(err.Error(), "ERROR CODE: DeploymentNotFound") { + return nil, err + } + return &resp, nil +} + +func (a *armClient) waitForExistingDeployment(ctx context.Context, timeOutInSeconds int, rgName, deploymentName string) error { + for timeOutInSeconds > 0 { + resp, err := a.getExistingDeployment(ctx, rgName, deploymentName) + if err != nil { + return fmt.Errorf("Error getting deployment %w", err) + } + if resp.Properties == nil { + return nil + } + if *resp.Properties.ProvisioningState != armresources.ProvisioningStateRunning { + return nil + } + time.Sleep(time.Duration(a.deploymentRetryWaitTime) * time.Second) + timeOutInSeconds -= a.deploymentRetryWaitTime + } + return fmt.Errorf("Timeout exeeded waiting for deployment %s in rg %s", deploymentName, rgName) +} + +func (a *armClient) runArmStep(ctx context.Context, options *PipelineRunOptions, rgName string, step *ARMStep, input map[string]output) (output, error) { + // Ensure resourcegroup exists + err := a.ensureResourceGroupExists(ctx, rgName, options.NoPersist) + if err != nil { + return nil, fmt.Errorf("failed to ensure resource group exists: %w", err) + } + + // Run deployment + + if err := a.waitForExistingDeployment(ctx, options.DeploymentTimeoutSeconds, rgName, step.Name); err != nil { + return nil, fmt.Errorf("Error waiting for deploymenty %w", err) + } + + if !options.DryRun || (options.DryRun && step.OutputOnly) { + return doWaitForDeployment(ctx, a.deploymentClient, rgName, step, options.Vars, input) + } + + return doDryRun(ctx, a.deploymentClient, rgName, step, options.Vars, input) +} + +func recursivePrint(level int, change *armresources.WhatIfPropertyChange) { + fmt.Printf("%s%s:\n", strings.Repeat("\t", level), *change.Path) + fmt.Printf("%s\tBefore:%s\n", strings.Repeat("\t", level), change.Before) + fmt.Printf("%s\tAfter:%s\n", strings.Repeat("\t", level), change.After) + for _, child := range change.Children { + level += level + recursivePrint(level, child) + } +} + +func printChanges(t armresources.ChangeType, changes []*armresources.WhatIfChange) { + for _, change := range changes { + if *change.ChangeType == t { + fmt.Printf("%s %s\n", strings.Repeat("\t", 1), *change.ResourceID) + for _, delta := range change.Delta { + recursivePrint(2, delta) + } + } + } +} + +func printChangeReport(changes []*armresources.WhatIfChange) { + fmt.Println("Change report for WhatIf deployment") + fmt.Println("----------") + fmt.Println("Creating") + printChanges(armresources.ChangeTypeCreate, changes) + fmt.Println("----------") + fmt.Println("Deploy") + printChanges(armresources.ChangeTypeDeploy, changes) + fmt.Println("----------") + fmt.Println("Modify") + printChanges(armresources.ChangeTypeModify, changes) + fmt.Println("----------") + fmt.Println("Delete") + printChanges(armresources.ChangeTypeDelete, changes) + fmt.Println("----------") + fmt.Println("Ignoring") + printChanges(armresources.ChangeTypeIgnore, changes) + fmt.Println("----------") + fmt.Println("NoChange") + printChanges(armresources.ChangeTypeNoChange, changes) + fmt.Println("----------") + fmt.Println("Unsupported") + printChanges(armresources.ChangeTypeUnsupported, changes) +} + +func pollAndPrint[T any](ctx context.Context, p *runtime.Poller[T]) error { + resp, err := p.PollUntilDone(ctx, nil) + if err != nil { + return fmt.Errorf("failed to wait for deployment completion: %w", err) + } + switch m := any(resp).(type) { + case armresources.DeploymentsClientWhatIfResponse: + printChangeReport(m.Properties.Changes) + case armresources.DeploymentsClientWhatIfAtSubscriptionScopeResponse: + printChangeReport(m.Properties.Changes) + default: + return fmt.Errorf("Unknown type %T", m) + } + return nil +} + +func doDryRun(ctx context.Context, client *armresources.DeploymentsClient, rgName string, step *ARMStep, vars config.Variables, input map[string]output) (output, error) { + logger := logr.FromContextOrDiscard(ctx) + + inputValues, err := getInputValues(step.Variables, input) + if err != nil { + return nil, fmt.Errorf("failed to get input values: %w", err) + } + // Transform Bicep to ARM + deploymentProperties, err := transformBicepToARMWhatIfDeployment(ctx, step.Parameters, vars, inputValues) + if err != nil { + return nil, fmt.Errorf("failed to transform Bicep to ARM: %w", err) + } + + // Create the deployment + deployment := armresources.DeploymentWhatIf{ + Properties: deploymentProperties, + } + + if step.DeploymentLevel == "Subscription" { + // Hardcode until schema is adapted + deployment.Location = to.Ptr("eastus2") + poller, err := client.BeginWhatIfAtSubscriptionScope(ctx, step.Name, deployment, nil) + if err != nil { + return nil, fmt.Errorf("failed to create WhatIf Deployment: %w", err) + } + logger.Info("WhatIf Deployment started", "deployment", step.Name) + err = pollAndPrint(ctx, poller) + if err != nil { + return nil, fmt.Errorf("failed to poll and print: %w", err) + } + } else { + poller, err := client.BeginWhatIf(ctx, rgName, step.Name, deployment, nil) + if err != nil { + return nil, fmt.Errorf("failed to create WhatIf Deployment: %w", err) + } + logger.Info("WhatIf Deployment started", "deployment", step.Name) + err = pollAndPrint(ctx, poller) + if err != nil { + return nil, fmt.Errorf("failed to poll and print: %w", err) + } + } + + return nil, nil +} + +func pollAndGetOutput[T any](ctx context.Context, p *runtime.Poller[T]) (armOutput, error) { + respRaw, err := p.PollUntilDone(ctx, nil) + if err != nil { + return nil, fmt.Errorf("failed to wait for deployment completion: %w", err) + } + + var outputs any + + switch resp := any(respRaw).(type) { + case armresources.DeploymentsClientCreateOrUpdateResponse: + outputs = resp.Properties.Outputs + case armresources.DeploymentsClientCreateOrUpdateAtSubscriptionScopeResponse: + outputs = resp.Properties.Outputs + default: + return nil, fmt.Errorf("Unknown type %T", resp) + } + + if outputs != nil { + if outputMap, ok := outputs.(map[string]any); ok { + returnMap := armOutput{} + for k, v := range outputMap { + returnMap[k] = v + } + return returnMap, nil + } + } + return nil, nil +} + +func doWaitForDeployment(ctx context.Context, client *armresources.DeploymentsClient, rgName string, step *ARMStep, vars config.Variables, input map[string]output) (output, error) { + logger := logr.FromContextOrDiscard(ctx) + + inputValues, err := getInputValues(step.Variables, input) + if err != nil { + return nil, fmt.Errorf("failed to get input values: %w", err) + } + // Transform Bicep to ARM + deploymentProperties, err := transformBicepToARMDeployment(ctx, step.Parameters, vars, inputValues) + if err != nil { + return nil, fmt.Errorf("failed to transform Bicep to ARM: %w", err) + } + + if hasTemplateResources(deploymentProperties.Template) && step.OutputOnly { + return nil, fmt.Errorf("Deployment step %s is outputOnly, but contains resources", step.Name) + } + + // Create the deployment + deployment := armresources.Deployment{ + Properties: deploymentProperties, + } + + if step.DeploymentLevel == "Subscription" { + // Hardcode until schema is adapted + deployment.Location = to.Ptr("eastus2") + poller, err := client.BeginCreateOrUpdateAtSubscriptionScope(ctx, step.Name, deployment, nil) + if err != nil { + return nil, fmt.Errorf("failed to create deployment: %w", err) + } + logger.Info("Deployment started", "deployment", step.Name) + + return pollAndGetOutput(ctx, poller) + } else { + poller, err := client.BeginCreateOrUpdate(ctx, rgName, step.Name, deployment, nil) + if err != nil { + return nil, fmt.Errorf("failed to create deployment: %w", err) + } + logger.Info("Deployment started", "deployment", step.Name) + + return pollAndGetOutput(ctx, poller) + } +} + +func (a *armClient) ensureResourceGroupExists(ctx context.Context, rgName string, rgNoPersist bool) error { + // Check if the resource group exists + // todo fill tags properly + tags := map[string]*string{} + + if !rgNoPersist { + // if no-persist is set, don't set the persist tag, needs double negotiate, cause default should be true + tags["persist"] = to.Ptr("true") + } + _, err := a.resourceGroupClient.Get(ctx, rgName, nil) + if err != nil { + // Create the resource group + resourceGroup := armresources.ResourceGroup{ + Location: to.Ptr(a.Region), + Tags: tags, + } + _, err = a.resourceGroupClient.CreateOrUpdate(ctx, rgName, resourceGroup, nil) + if err != nil { + return fmt.Errorf("failed to create resource group: %w", err) + } + } else { + patchResourceGroup := armresources.ResourceGroupPatchable{ + Tags: tags, + } + _, err = a.resourceGroupClient.Update(ctx, rgName, patchResourceGroup, nil) + if err != nil { + return fmt.Errorf("failed to update resource group: %w", err) + } + } + return nil +} diff --git a/tooling/templatize/pkg/pipeline/arm_test.go b/tooling/templatize/pkg/pipeline/arm_test.go new file mode 100644 index 000000000..5edea5901 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/arm_test.go @@ -0,0 +1,90 @@ +package pipeline + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "gotest.tools/v3/assert" +) + +func TestWaitForExistingDeployment(t *testing.T) { + ctx := context.Background() + + cases := []struct { + name string + deploymentState []armresources.ProvisioningState + missing bool + expectedError *string + expecetCallCnt int + returnError *error + timeout int + }{ + { + name: "Timeout", + deploymentState: []armresources.ProvisioningState{"Running", "Running"}, + expectedError: to.Ptr("Timeout exeeded waiting for deployment test in rg rg"), + expecetCallCnt: 1, + timeout: 1, + }, + { + name: "Missing Deployment", + missing: true, + expecetCallCnt: 1, + timeout: 1, + }, + { + name: "Retrying", + deploymentState: []armresources.ProvisioningState{"Running", "Running", "Succeeded"}, + expecetCallCnt: 2, + timeout: 60, + }, + { + name: "Handle Error", + missing: true, + expecetCallCnt: 1, + returnError: to.Ptr(fmt.Errorf("Test error")), + expectedError: to.Ptr("Error getting deployment Test error"), + timeout: 1, + }, + } + + for _, c := range cases { + rg := "rg" + depl := "test" + callCnt := 0 + t.Run(c.name, func(t *testing.T) { + a := armClient{ + deploymentRetryWaitTime: 1, + GetDeployment: func(_ context.Context, rgName, deploymentName string) (armresources.DeploymentsClientGetResponse, error) { + assert.Equal(t, rgName, rg) + assert.Equal(t, deploymentName, depl) + callCnt++ + + var retErr error + if c.returnError != nil { + retErr = *c.returnError + } + + returnObj := armresources.DeploymentsClientGetResponse{ + DeploymentExtended: armresources.DeploymentExtended{}, + } + if !c.missing { + returnObj.DeploymentExtended.Properties = &armresources.DeploymentPropertiesExtended{ + ProvisioningState: &c.deploymentState[callCnt], + } + } + return returnObj, retErr + }, + } + + err := a.waitForExistingDeployment(ctx, c.timeout, rg, depl) + if c.expectedError != nil { + assert.Equal(t, err.Error(), *c.expectedError) + } + assert.Equal(t, callCnt, c.expecetCallCnt) + }) + } +} diff --git a/tooling/templatize/pkg/pipeline/bicep.go b/tooling/templatize/pkg/pipeline/bicep.go new file mode 100644 index 000000000..1e049e090 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/bicep.go @@ -0,0 +1,114 @@ +package pipeline + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func transformBicepToARMWhatIfDeployment(ctx context.Context, bicepParameterTemplateFile string, vars config.Variables, inputs map[string]any) (*armresources.DeploymentWhatIfProperties, error) { + template, params, err := transformParameters(ctx, vars, inputs, bicepParameterTemplateFile) + if err != nil { + return nil, err + } + return &armresources.DeploymentWhatIfProperties{ + Mode: to.Ptr(armresources.DeploymentModeIncremental), + Template: template, + Parameters: params, + }, nil +} + +func transformBicepToARMDeployment(ctx context.Context, bicepParameterTemplateFile string, vars config.Variables, inputs map[string]any) (*armresources.DeploymentProperties, error) { + template, params, err := transformParameters(ctx, vars, inputs, bicepParameterTemplateFile) + if err != nil { + return nil, err + } + return &armresources.DeploymentProperties{ + Mode: to.Ptr(armresources.DeploymentModeIncremental), + Template: template, + Parameters: params, + }, nil +} + +func transformParameters(ctx context.Context, vars config.Variables, inputs map[string]any, bicepParameterTemplateFile string) (map[string]interface{}, map[string]interface{}, error) { + bicepParamContent, err := config.PreprocessFile(bicepParameterTemplateFile, vars) + if err != nil { + return nil, nil, fmt.Errorf("failed to preprocess file: %w", err) + } + bicepParamBaseDir := filepath.Dir(bicepParameterTemplateFile) + bicepParamFile, err := os.CreateTemp(bicepParamBaseDir, "bicep-params-*.bicepparam") + if err != nil { + return nil, nil, fmt.Errorf("failed to create temp file: %w", err) + } + defer os.Remove(bicepParamFile.Name()) + _, err = bicepParamFile.Write(bicepParamContent) + if err != nil { + return nil, nil, fmt.Errorf("failed to write to target file: %w", err) + } + + cmd := exec.CommandContext(ctx, "az", "bicep", "build-params", "-f", bicepParamFile.Name(), "--stdout") + output, err := cmd.Output() + if err != nil { + combinedOutput, _ := cmd.CombinedOutput() + return nil, nil, fmt.Errorf("failed to get output from command: %w\n%s", err, string(combinedOutput)) + } + + var result generationResult + if err := json.Unmarshal(output, &result); err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal output: %w", err) + } + template, err := result.Template() + if err != nil { + return nil, nil, fmt.Errorf("failed to get template: %w", err) + } + params, err := result.Parameters() + if err != nil { + return nil, nil, fmt.Errorf("failed to get parameters: %w", err) + } + for k, v := range inputs { + params[k] = map[string]interface{}{ + "value": v, + } + } + return template, params, nil +} + +type generationResult struct { + ParametersJson string `json:"parametersJson"` + TemplateJson string `json:"templateJson"` +} + +func hasTemplateResources(template any) bool { + if templateAsMap, isMap := template.(map[string]interface{}); isMap { + if val, hasResources := templateAsMap["resources"]; hasResources { + if res, isList := val.([]any); isList { + return len(res) > 0 + } + } + } + return false +} + +func (gr generationResult) Parameters() (map[string]interface{}, error) { + var parameters = map[string]interface{}{} + if err := json.Unmarshal([]byte(gr.ParametersJson), ¶meters); err != nil { + return nil, fmt.Errorf("failed to unmarshal parameters: %w", err) + } + return parameters["parameters"].(map[string]interface{}), nil +} + +func (gr generationResult) Template() (map[string]interface{}, error) { + var template map[string]interface{} + if err := json.Unmarshal([]byte(gr.TemplateJson), &template); err != nil { + return nil, fmt.Errorf("failed to unmarshal template: %w", err) + } + return template, nil +} diff --git a/tooling/templatize/pkg/pipeline/common.go b/tooling/templatize/pkg/pipeline/common.go new file mode 100644 index 000000000..8d5d62577 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/common.go @@ -0,0 +1,29 @@ +package pipeline + +import ( + "fmt" + "path/filepath" + + "gopkg.in/yaml.v3" +) + +func (p *Pipeline) DeepCopy(newPipelineFilePath string) (*Pipeline, error) { + data, err := yaml.Marshal(p) + if err != nil { + return nil, fmt.Errorf("failed to marshal pipeline: %v", err) + } + + copy, err := NewPlainPipelineFromBytes(newPipelineFilePath, data) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal pipeline: %v", err) + } + return copy, nil +} + +func (p *Pipeline) PipelineFilePath() string { + return p.pipelineFilePath +} + +func (p *Pipeline) AbsoluteFilePath(filePath string) (string, error) { + return filepath.Abs(filepath.Join(filepath.Dir(p.pipelineFilePath), filePath)) +} diff --git a/tooling/templatize/pkg/pipeline/common_test.go b/tooling/templatize/pkg/pipeline/common_test.go new file mode 100644 index 000000000..cb8493797 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/common_test.go @@ -0,0 +1,86 @@ +package pipeline + +import ( + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func TestDeepCopy(t *testing.T) { + configProvider := config.NewConfigProvider("../../testdata/config.yaml") + vars, err := configProvider.GetVariables("public", "int", "", config.NewConfigReplacements("r", "sr", "s")) + if err != nil { + t.Errorf("failed to get variables: %v", err) + } + pipeline, err := NewPipelineFromFile("../../testdata/pipeline.yaml", vars) + if err != nil { + t.Errorf("failed to read new pipeline: %v", err) + } + + newPipelinePath := "new-pipeline.yaml" + pipelineCopy, err := pipeline.DeepCopy(newPipelinePath) + if err != nil { + t.Errorf("failed to copy pipeline: %v", err) + } + + assert.Assert(t, pipeline != pipelineCopy, "expected pipeline and copy to be different") + assert.Equal(t, pipelineCopy.PipelineFilePath(), newPipelinePath, "expected pipeline copy to have new path") + + if diff := cmp.Diff(pipeline, pipelineCopy, cmpopts.IgnoreUnexported(Pipeline{}, ShellStep{}, ARMStep{})); diff != "" { + t.Errorf("got diffs after pipeline deep copy: %v", diff) + } +} + +func TestAbsoluteFilePath(t *testing.T) { + configProvider := config.NewConfigProvider("../../testdata/config.yaml") + vars, err := configProvider.GetVariables("public", "int", "", config.NewConfigReplacements("r", "sr", "s")) + if err != nil { + t.Errorf("failed to get variables: %v", err) + } + pipeline, err := NewPipelineFromFile("../../testdata/pipeline.yaml", vars) + if err != nil { + t.Errorf("failed to read new pipeline: %v", err) + } + + abspath := func(path string) string { + abs, _ := filepath.Abs(path) + return abs + } + testCases := []struct { + name string + relativeFile string + absoluteFile string + }{ + { + name: "basic", + relativeFile: "test.bicepparam", + absoluteFile: abspath("../../testdata/test.bicepparam"), + }, + { + name: "go one lower", + relativeFile: "../test.bicepparam", + absoluteFile: abspath("../../test.bicepparam"), + }, + { + name: "subdir", + relativeFile: "subdir/test.bicepparam", + absoluteFile: abspath("../../testdata/subdir/test.bicepparam"), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + abs, err := pipeline.AbsoluteFilePath(tc.relativeFile) + if err != nil { + t.Errorf("failed to get absolute file path: %v", err) + } + assert.Equal(t, abs, tc.absoluteFile, "expected absolute file path to be correct") + }) + } + +} diff --git a/tooling/templatize/pkg/pipeline/executiontarget.go b/tooling/templatize/pkg/pipeline/executiontarget.go new file mode 100644 index 000000000..7964e0bce --- /dev/null +++ b/tooling/templatize/pkg/pipeline/executiontarget.go @@ -0,0 +1,92 @@ +package pipeline + +import ( + "context" + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/aks" +) + +func LookupSubscriptionID(ctx context.Context, subscriptionName string) (string, error) { + // Create a new Azure identity client + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return "", fmt.Errorf("failed to obtain a credential: %v", err) + } + + // Create a new subscriptions client + client, err := armsubscriptions.NewClient(cred, nil) + if err != nil { + return "", fmt.Errorf("failed to create subscriptions client: %v", err) + } + + // List subscriptions and find the one with the matching name + pager := client.NewListPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + return "", fmt.Errorf("failed to get next page of subscriptions: %v", err) + } + for _, sub := range page.Value { + if sub.DisplayName != nil && *sub.DisplayName == subscriptionName { + return *sub.SubscriptionID, nil + } + } + } + + return "", fmt.Errorf("subscription with name %q not found", subscriptionName) +} + +type ExecutionTarget interface { + KubeConfig(ctx context.Context) (string, error) + GetSubscriptionID() string + GetAkSClusterName() string + GetResourceGroup() string + GetRegion() string +} + +type executionTargetImpl struct { + subscriptionName string + subscriptionID string + resourceGroup string + region string + aksClusterName string +} + +func (target *executionTargetImpl) KubeConfig(ctx context.Context) (string, error) { + if target.GetAkSClusterName() == "" { + return "", nil + } + + // Get Kubeconfig + kubeconfigPath, err := aks.GetKubeConfig(ctx, target.GetSubscriptionID(), target.GetResourceGroup(), target.GetAkSClusterName()) + if err != nil { + return "", fmt.Errorf("failed to get kubeconfig: %w", err) + } + + // Make sure we have cluster admin + err = aks.EnsureClusterAdmin(ctx, kubeconfigPath, target.GetSubscriptionID(), target.GetResourceGroup(), target.GetAkSClusterName(), nil) + if err != nil { + return "", fmt.Errorf("failed to ensure cluster admin role: %w", err) + } + return kubeconfigPath, nil +} + +func (target *executionTargetImpl) GetSubscriptionID() string { + return target.subscriptionID +} + +func (target *executionTargetImpl) GetAkSClusterName() string { + return target.aksClusterName +} + +func (target *executionTargetImpl) GetResourceGroup() string { + return target.resourceGroup +} + +func (target *executionTargetImpl) GetRegion() string { + return target.region +} diff --git a/tooling/templatize/pkg/pipeline/inspect.go b/tooling/templatize/pkg/pipeline/inspect.go new file mode 100644 index 000000000..af80f0107 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/inspect.go @@ -0,0 +1,94 @@ +package pipeline + +import ( + "context" + "fmt" + "io" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +type StepInspectScope func(Step, *InspectOptions, io.Writer) error + +func NewStepInspectScopes() map[string]StepInspectScope { + return map[string]StepInspectScope{ + "vars": inspectVars, + } +} + +// InspectOptions contains the options for the Inspect method +type InspectOptions struct { + Scope string + Format string + Step string + Region string + Vars config.Variables + ScopeFunctions map[string]StepInspectScope +} + +// NewInspectOptions creates a new PipelineInspectOptions struct +func NewInspectOptions(vars config.Variables, region, step, scope, format string) *InspectOptions { + return &InspectOptions{ + Scope: scope, + Format: format, + Step: step, + Region: region, + Vars: vars, + ScopeFunctions: NewStepInspectScopes(), + } +} + +func (p *Pipeline) Inspect(ctx context.Context, options *InspectOptions, writer io.Writer) error { + for _, rg := range p.ResourceGroups { + for _, step := range rg.Steps { + if step.StepName() == options.Step { + if inspectFunc, ok := options.ScopeFunctions[options.Scope]; ok { + err := inspectFunc(step, options, writer) + if err != nil { + return err + } + } else { + return fmt.Errorf("unknown inspect scope %q", options.Scope) + } + return nil + } + } + } + return fmt.Errorf("step %q not found", options.Step) +} + +func inspectVars(s Step, options *InspectOptions, writer io.Writer) error { + var envVars map[string]string + var err error + switch step := s.(type) { + case *ShellStep: + envVars, err = step.mapStepVariables(options.Vars) + default: + return fmt.Errorf("inspecting step variables not implemented for action type %s", s.ActionType()) + } + if err != nil { + return err + } + + switch options.Format { + case "makefile": + printMakefileVars(envVars, writer) + case "shell": + printShellVars(envVars, writer) + default: + return fmt.Errorf("unknown output format %q", options.Format) + } + return nil +} + +func printMakefileVars(vars map[string]string, writer io.Writer) { + for k, v := range vars { + fmt.Fprintf(writer, "%s ?= %s\n", k, v) + } +} + +func printShellVars(vars map[string]string, writer io.Writer) { + for k, v := range vars { + fmt.Fprintf(writer, "export %s=\"%s\"\n", k, v) + } +} diff --git a/tooling/templatize/pkg/pipeline/inspect_test.go b/tooling/templatize/pkg/pipeline/inspect_test.go new file mode 100644 index 000000000..093854f1e --- /dev/null +++ b/tooling/templatize/pkg/pipeline/inspect_test.go @@ -0,0 +1,112 @@ +package pipeline + +import ( + "bytes" + "context" + "io" + "testing" + + "gotest.tools/v3/assert" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func TestInspectVars(t *testing.T) { + testCases := []struct { + name string + caseStep Step + options *InspectOptions + expected string + err string + }{ + { + name: "basic", + caseStep: NewShellStep("step", "echo hello").WithVariables(Variable{ + Name: "FOO", + ConfigRef: "foo", + }), + options: &InspectOptions{ + Vars: config.Variables{ + "foo": "bar", + }, + Format: "shell", + }, + expected: "export FOO=\"bar\"\n", + }, + { + name: "makefile", + caseStep: NewShellStep("step", "echo hello").WithVariables(Variable{ + Name: "FOO", + ConfigRef: "foo", + }), + options: &InspectOptions{ + Vars: config.Variables{ + "foo": "bar", + }, + Format: "makefile", + }, + expected: "FOO ?= bar\n", + }, + { + name: "failed action", + caseStep: NewARMStep("step", "test.bicep", "test.bicepparam", "ResourceGroup"), + err: "inspecting step variables not implemented for action type ARM", + }, + { + name: "failed format", + caseStep: NewShellStep("step", "echo hello"), + options: &InspectOptions{Format: "unknown"}, + err: "unknown output format \"unknown\"", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + buf := new(bytes.Buffer) + err := inspectVars(tc.caseStep, tc.options, buf) + if tc.err == "" { + assert.NilError(t, err) + assert.Equal(t, buf.String(), tc.expected) + } else { + assert.ErrorContains(t, err, tc.err) + } + }) + } +} + +func TestInspect(t *testing.T) { + p := Pipeline{ + ResourceGroups: []*ResourceGroup{{ + Steps: []Step{ + NewShellStep("step1", "echo hello"), + }, + }, + }, + } + opts := NewInspectOptions(config.Variables{}, "", "step1", "scope", "format") + + opts.ScopeFunctions = map[string]StepInspectScope{ + "scope": func(s Step, o *InspectOptions, w io.Writer) error { + assert.Equal(t, s.StepName(), "step1") + return nil + }, + } + + err := p.Inspect(context.Background(), opts, nil) + assert.NilError(t, err) +} + +func TestInspectWrongScope(t *testing.T) { + p := Pipeline{ + ResourceGroups: []*ResourceGroup{{ + Steps: []Step{ + NewShellStep("step1", "echo hello"), + }, + }, + }, + } + opts := NewInspectOptions(config.Variables{}, "", "step1", "foo", "format") + + err := p.Inspect(context.Background(), opts, nil) + assert.Error(t, err, "unknown inspect scope \"foo\"") +} diff --git a/tooling/templatize/pkg/pipeline/pipeline.schema.v1.json b/tooling/templatize/pkg/pipeline/pipeline.schema.v1.json new file mode 100644 index 000000000..72a6976a3 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/pipeline.schema.v1.json @@ -0,0 +1,347 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "pipeline.schema.v1", + "type": "object", + "definitions": { + "variableRef": { + "type": "object", + "properties": { + "input": { + "type": "object", + "additionalProperties": false, + "properties": { + "step": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "step", + "name" + ] + }, + "configRef": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "input" + ] + }, + { + "required": [ + "configRef" + ] + }, + { + "required": [ + "value" + ] + } + ] + }, + "variable": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "input": { + "type": "object", + "additionalProperties": false, + "properties": { + "step": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "step", + "name" + ] + }, + "configRef": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "name", + "input" + ] + }, + { + "required": [ + "name", + "configRef" + ] + }, + { + "required": [ + "name", + "value" + ] + } + ], + "required": [ + "name" + ] + } + }, + "properties": { + "serviceGroup": { + "type": "string" + }, + "rolloutName": { + "type": "string" + }, + "resourceGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "subscription": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "action": { + "type": "string", + "enum": ["ARM", "Shell", "DelegateChildZone", "SetCertificateIssuer"] + }, + "template": { + "type": "string" + }, + "parameters": { + "type": "string" + }, + "deploymentLevel": { + "type": "string", + "enum": ["ResourceGroup", "Subscription"] + }, + "command": { + "type": "string" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/variable" + } + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + } + }, + "dryRun": { + "type": "object" + }, + "vaultBaseUrl": { + "$ref": "#/definitions/variableRef" + }, + "provider": { + "$ref": "#/definitions/variableRef" + }, + "parentZone": { + "$ref": "#/definitions/variableRef" + }, + "childZone": { + "$ref": "#/definitions/variableRef" + }, + "outputOnly": { + "type": "boolean" + } + }, + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "action": { + "type": "string", + "enum": ["ARM"] + }, + "template": { + "type": "string" + }, + "parameters": { + "type": "string" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/variable" + } + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + } + }, + "deploymentLevel": { + "type": "string", + "enum": ["ResourceGroup", "Subscription"] + }, + "outputOnly": { + "type": "boolean" + } + }, + "required": [ + "template", + "parameters", + "deploymentLevel" + ] + }, + { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "action": { + "type": "string", + "enum": ["Shell"] + }, + "command": { + "type": "string" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/variable" + } + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + } + }, + "dryRun": { + "type": "object", + "additionalProperties": false, + "properties": { + "command": { + "type": "string" + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/variable" + } + } + } + } + }, + "required": [ + "command" + ] + }, + { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "action": { + "type": "string", + "enum": ["DelegateChildZone"] + }, + "parentZone": { + "$ref": "#/definitions/variableRef" + }, + "childZone": { + "$ref": "#/definitions/variableRef" + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "parentZone", + "childZone" + ] + }, + { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "action": { + "type": "string", + "enum": ["SetCertificateIssuer"] + }, + "vaultBaseUrl": { + "$ref": "#/definitions/variableRef" + }, + "provider": { + "$ref": "#/definitions/variableRef" + }, + "dependsOn": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "vaultBaseUrl", + "provider" + ] + } + ], + "required": [ + "name", + "action" + ] + } + }, + "aksCluster": { + "type": "string" + } + }, + "required": [ + "name", + "subscription", + "steps" + ] + } + } + }, + "required": [ + "serviceGroup", + "rolloutName", + "resourceGroups" + ] +} diff --git a/tooling/templatize/pkg/pipeline/run.go b/tooling/templatize/pkg/pipeline/run.go new file mode 100644 index 000000000..1615ba9e5 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/run.go @@ -0,0 +1,213 @@ +package pipeline + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/go-logr/logr" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +var DefaultDeploymentTimeoutSeconds = 30 * 60 + +func NewPipelineFromFile(pipelineFilePath string, vars config.Variables) (*Pipeline, error) { + bytes, err := config.PreprocessFile(pipelineFilePath, vars) + if err != nil { + return nil, fmt.Errorf("failed to preprocess pipeline file %w", err) + } + + err = ValidatePipelineSchema(bytes) + if err != nil { + return nil, fmt.Errorf("failed to validate pipeline schema: %w", err) + } + + absPath, err := filepath.Abs(pipelineFilePath) + if err != nil { + return nil, fmt.Errorf("failed to get absolute path for pipeline file %q: %w", pipelineFilePath, err) + } + + pipeline, err := NewPlainPipelineFromBytes(absPath, bytes) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal pipeline file %w", err) + } + err = pipeline.Validate() + if err != nil { + return nil, fmt.Errorf("pipeline file failed validation %w", err) + } + return pipeline, nil +} + +type PipelineRunOptions struct { + DryRun bool + Step string + Region string + Vars config.Variables + SubsciptionLookupFunc subsciptionLookup + NoPersist bool + DeploymentTimeoutSeconds int +} + +type armOutput map[string]any + +type output interface { + GetValue(key string) (*outPutValue, error) +} + +type outPutValue struct { + Type string `yaml:"type"` + Value any `yaml:"value"` +} + +func (o armOutput) GetValue(key string) (*outPutValue, error) { + if v, ok := o[key]; ok { + if innerValue, innerConversionOk := v.(map[string]any); innerConversionOk { + returnValue := outPutValue{ + Type: innerValue["type"].(string), + Value: innerValue["value"], + } + return &returnValue, nil + } + } + return nil, fmt.Errorf("key %q not found", key) +} + +func RunPipeline(pipeline *Pipeline, ctx context.Context, options *PipelineRunOptions) error { + logger := logr.FromContextOrDiscard(ctx) + + outPuts := make(map[string]output) + + // set working directory to the pipeline file directory for the + // duration of the execution so that all commands and file references + // within the pipeline file are resolved relative to the pipeline file + originalDir, err := os.Getwd() + if err != nil { + return err + } + dir := filepath.Dir(pipeline.pipelineFilePath) + logger.V(7).Info("switch current dir to pipeline file directory", "path", dir) + err = os.Chdir(dir) + if err != nil { + return err + } + defer func() { + logger.V(7).Info("switch back dir", "path", originalDir) + err = os.Chdir(originalDir) + if err != nil { + logger.Error(err, "failed to switch back to original directory", "path", originalDir) + } + }() + + for _, rg := range pipeline.ResourceGroups { + // prepare execution context + subscriptionID, err := options.SubsciptionLookupFunc(ctx, rg.Subscription) + if err != nil { + return fmt.Errorf("failed to lookup subscription ID for %q: %w", rg.Subscription, err) + } + executionTarget := executionTargetImpl{ + subscriptionName: rg.Subscription, + subscriptionID: subscriptionID, + region: options.Region, + resourceGroup: rg.Name, + aksClusterName: rg.AKSCluster, + } + err = RunResourceGroup(rg, ctx, options, &executionTarget, outPuts) + if err != nil { + return err + } + } + return nil +} + +func RunResourceGroup(rg *ResourceGroup, ctx context.Context, options *PipelineRunOptions, executionTarget ExecutionTarget, outputs map[string]output) error { + logger := logr.FromContextOrDiscard(ctx) + + kubeconfigFile, err := executionTarget.KubeConfig(ctx) + if kubeconfigFile != "" { + defer func() { + if err := os.Remove(kubeconfigFile); err != nil { + logger.V(5).Error(err, "failed to delete kubeconfig file", "kubeconfig", kubeconfigFile) + } + }() + } else if err != nil { + return fmt.Errorf("failed to prepare kubeconfig: %w", err) + } + + for _, step := range rg.Steps { + // execute + output, err := RunStep( + step, + logr.NewContext( + ctx, + logger.WithValues( + "step", step.StepName(), + "subscription", executionTarget.GetSubscriptionID(), + "resourceGroup", executionTarget.GetResourceGroup(), + "aksCluster", executionTarget.GetAkSClusterName(), + ), + ), + kubeconfigFile, + executionTarget, options, + outputs, + ) + if err != nil { + return err + } + if output != nil { + + outputs[step.StepName()] = output + } + } + return nil +} + +func RunStep(s Step, ctx context.Context, kubeconfigFile string, executionTarget ExecutionTarget, options *PipelineRunOptions, outPuts map[string]output) (output, error) { + if options.Step != "" && s.StepName() != options.Step { + // skip steps that don't match the specified step name + return nil, nil + } + fmt.Println("\n---------------------") + if options.DryRun { + fmt.Println("This is a dry run!") + } + fmt.Println(s.Description()) + fmt.Print("\n") + + switch step := s.(type) { + case *ShellStep: + return nil, runShellStep(step, ctx, kubeconfigFile, options, outPuts) + case *ARMStep: + a := newArmClient(executionTarget.GetSubscriptionID(), executionTarget.GetRegion()) + if a == nil { + return nil, fmt.Errorf("failed to create ARM client") + } + output, err := a.runArmStep(ctx, options, executionTarget.GetResourceGroup(), step, outPuts) + if err != nil { + return nil, fmt.Errorf("failed to run ARM step: %w", err) + } + return output, nil + default: + fmt.Println("No implementation for action type - skip", s.ActionType()) + return nil, nil + } +} + +func getInputValues(configuredVariables []Variable, inputs map[string]output) (map[string]any, error) { + values := make(map[string]any) + for _, i := range configuredVariables { + if i.Input != nil { + if v, found := inputs[i.Input.Step]; found { + value, err := v.GetValue(i.Input.Name) + if err != nil { + return nil, fmt.Errorf("failed to get value for input %s.%s: %w", i.Input.Step, i.Input.Name, err) + } + values[i.Name] = value.Value + } else { + return nil, fmt.Errorf("step %s not found in provided outputs", i.Input.Step) + } + } + } + return values, nil +} diff --git a/tooling/templatize/pkg/pipeline/run_test.go b/tooling/templatize/pkg/pipeline/run_test.go new file mode 100644 index 000000000..738974fbe --- /dev/null +++ b/tooling/templatize/pkg/pipeline/run_test.go @@ -0,0 +1,142 @@ +package pipeline + +import ( + "context" + "testing" + + "gotest.tools/v3/assert" +) + +func TestStepRun(t *testing.T) { + foundOutput := "" + s := NewShellStep("step", "echo hello").WithOutputFunc( + func(output string) { + foundOutput = output + }, + ) + _, err := RunStep(s, context.Background(), "", &executionTargetImpl{}, &PipelineRunOptions{}, nil) + assert.NilError(t, err) + assert.Equal(t, foundOutput, "hello\n") +} + +func TestResourceGroupRun(t *testing.T) { + foundOutput := "" + rg := &ResourceGroup{ + Steps: []Step{ + NewShellStep("step", "echo hello").WithOutputFunc( + func(output string) { + foundOutput = output + }, + ), + }, + } + err := RunResourceGroup(rg, context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}, make(map[string]output)) + assert.NilError(t, err) + assert.Equal(t, foundOutput, "hello\n") +} + +func TestResourceGroupError(t *testing.T) { + tmpVals := make([]string, 0) + outputFunc := func(output string) { + tmpVals = append(tmpVals, output) + } + rg := &ResourceGroup{ + Steps: []Step{ + NewShellStep("step1", "echo hello").WithOutputFunc(outputFunc), + NewShellStep("step2", "faaaaafffaa").WithOutputFunc(outputFunc), + NewShellStep("step3", "echo hallo").WithOutputFunc(outputFunc), + }, + } + err := RunResourceGroup(rg, context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}, make(map[string]output)) + assert.ErrorContains(t, err, "faaaaafffaa: command not found\n exit status 127") + // Test processing ends after first error + assert.Equal(t, len(tmpVals), 1) +} + +type testExecutionTarget struct{} + +func (t *testExecutionTarget) KubeConfig(_ context.Context) (string, error) { + return "", nil +} +func (t *testExecutionTarget) GetSubscriptionID() string { return "test" } +func (t *testExecutionTarget) GetAkSClusterName() string { return "test" } +func (t *testExecutionTarget) GetResourceGroup() string { return "test" } +func (t *testExecutionTarget) GetRegion() string { return "test" } + +func TestResourceGroupRunRequireKubeconfig(t *testing.T) { + rg := &ResourceGroup{Steps: []Step{}} + err := RunResourceGroup(rg, context.Background(), &PipelineRunOptions{}, &testExecutionTarget{}, make(map[string]output)) + assert.NilError(t, err) +} + +func TestPipelineRun(t *testing.T) { + foundOutput := "" + pipeline := &Pipeline{ + ResourceGroups: []*ResourceGroup{ + { + Name: "test", + Subscription: "test", + Steps: []Step{ + NewShellStep("step", "echo hello").WithOutputFunc( + func(output string) { + foundOutput = output + }, + ), + }, + }, + }, + } + + err := RunPipeline(pipeline, context.Background(), &PipelineRunOptions{ + SubsciptionLookupFunc: func(_ context.Context, _ string) (string, error) { + return "test", nil + }, + }) + + assert.NilError(t, err) + assert.Equal(t, foundOutput, "hello\n") +} + +func TestArmGetValue(t *testing.T) { + output := armOutput{ + "zoneName": map[string]any{ + "type": "String", + "value": "test", + }, + } + + value, err := output.GetValue("zoneName") + assert.Equal(t, value.Value, "test") + assert.Equal(t, value.Type, "String") + assert.NilError(t, err) +} + +func TestAddInputVars(t *testing.T) { + mapOutput := map[string]output{} + mapOutput["step1"] = armOutput{ + "output1": map[string]any{ + "type": "String", + "value": "value1", + }, + } + s := &ShellStep{ + Variables: []Variable{{ + Name: "input1", + Input: &Input{ + Name: "output1", + Step: "step1", + }, + }, + }} + + envVars, err := getInputValues(s.Variables, mapOutput) + assert.NilError(t, err) + assert.DeepEqual(t, envVars, map[string]any{"input1": "value1"}) + + _, err = getInputValues([]Variable{ + { + Input: &Input{Step: "foobar"}, + }, + }, mapOutput) + assert.Error(t, err, "step foobar not found in provided outputs") +} diff --git a/tooling/templatize/pkg/pipeline/shell.go b/tooling/templatize/pkg/pipeline/shell.go new file mode 100644 index 000000000..8babcae18 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/shell.go @@ -0,0 +1,100 @@ +package pipeline + +import ( + "context" + "fmt" + "maps" + "os/exec" + + "github.com/go-logr/logr" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/utils" +) + +func (s *ShellStep) createCommand(ctx context.Context, dryRun bool, envVars map[string]string) (*exec.Cmd, bool) { + var scriptCommand string = s.Command + if dryRun { + if s.DryRun.Command == "" && s.DryRun.Variables == nil { + return nil, true + } + if s.DryRun.Command != "" { + scriptCommand = s.DryRun.Command + } + for _, e := range s.DryRun.Variables { + envVars[e.Name] = e.Value + } + } + cmd := exec.CommandContext(ctx, "/bin/bash", "-c", buildBashScript(scriptCommand)) + cmd.Env = append(cmd.Env, utils.MapToEnvVarArray(envVars)...) + return cmd, false +} + +func buildBashScript(command string) string { + return fmt.Sprintf("set -o errexit -o nounset -o pipefail\n%s", command) +} + +func runShellStep(s *ShellStep, ctx context.Context, kubeconfigFile string, options *PipelineRunOptions, inputs map[string]output) error { + if s.outputFunc == nil { + s.outputFunc = func(output string) { + fmt.Println(output) + } + } + + logger := logr.FromContextOrDiscard(ctx) + + // build ENV vars + stepVars, err := s.mapStepVariables(options.Vars) + if err != nil { + return fmt.Errorf("failed to build env vars: %w", err) + } + + envVars := utils.GetOsVariable() + + maps.Copy(envVars, stepVars) + + inputValues, err := getInputValues(s.Variables, inputs) + if err != nil { + return fmt.Errorf("failed to get input values: %w", err) + } + for k, v := range inputValues { + envVars[k] = utils.AnyToString(v) + } + // execute the command + cmd, skipCommand := s.createCommand(ctx, options.DryRun, envVars) + if skipCommand { + logger.V(5).Info(fmt.Sprintf("Skipping step '%s' due to missing dry-run configuration", s.Name)) + return nil + } + + if kubeconfigFile != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("KUBECONFIG=%s", kubeconfigFile)) + } + + logger.V(5).Info(fmt.Sprintf("Executing shell command: %s\n", s.Command), "command", s.Command) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to execute shell command: %s %w", string(output), err) + } + + s.outputFunc(string(output)) + + return nil +} + +func (s *ShellStep) mapStepVariables(vars config.Variables) (map[string]string, error) { + envVars := make(map[string]string) + for _, e := range s.Variables { + if e.ConfigRef != "" { // not all Variables are Environment variables + value, found := vars.GetByPath(e.ConfigRef) + if !found { + return nil, fmt.Errorf("failed to lookup config reference %s for %s", e.ConfigRef, e.Name) + } + envVars[e.Name] = utils.AnyToString(value) + } else if e.Value != "" { + envVars[e.Name] = e.Value + } + // what about output chaining? :( + } + return envVars, nil +} diff --git a/tooling/templatize/pkg/pipeline/shell_test.go b/tooling/templatize/pkg/pipeline/shell_test.go new file mode 100644 index 000000000..831ba8d39 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/shell_test.go @@ -0,0 +1,203 @@ +package pipeline + +import ( + "context" + "fmt" + "strings" + "testing" + + "gotest.tools/v3/assert" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +func TestCreateCommand(t *testing.T) { + ctx := context.Background() + testCases := []struct { + name string + step *ShellStep + dryRun bool + envVars map[string]string + expectedScript string + expectedEnv []string + skipCommand bool + }{ + { + name: "basic", + step: &ShellStep{ + Command: "/bin/echo hello", + }, + expectedScript: buildBashScript("/bin/echo hello"), + }, + { + name: "dry-run", + step: &ShellStep{ + Command: "/bin/echo hello", + DryRun: DryRun{ + Command: "/bin/echo dry-run", + }, + }, + dryRun: true, + expectedScript: buildBashScript("/bin/echo dry-run"), + }, + { + name: "dry-run-env", + step: &ShellStep{ + Command: "/bin/echo", + DryRun: DryRun{ + Variables: []Variable{ + { + Name: "DRY_RUN", + Value: "true", + }, + }, + }, + }, + dryRun: true, + expectedScript: buildBashScript("/bin/echo"), + envVars: map[string]string{}, + expectedEnv: []string{"DRY_RUN=true"}, + }, + { + name: "dry-run fail", + step: &ShellStep{ + Command: "/bin/echo", + }, + dryRun: true, + skipCommand: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cmd, skipCommand := tc.step.createCommand(ctx, tc.dryRun, tc.envVars) + assert.Equal(t, skipCommand, tc.skipCommand) + if !tc.skipCommand { + assert.Equal(t, strings.Join(cmd.Args, " "), fmt.Sprintf("/bin/bash -c %s", tc.expectedScript)) + } + if tc.expectedEnv != nil { + assert.DeepEqual(t, cmd.Env, tc.expectedEnv) + } + }) + } + +} + +func TestMapStepVariables(t *testing.T) { + testCases := []struct { + name string + vars config.Variables + step *ShellStep + expected map[string]string + err string + }{ + { + name: "basic", + vars: config.Variables{ + "FOO": "bar", + }, + step: &ShellStep{ + Variables: []Variable{ + { + Name: "BAZ", + ConfigRef: "FOO", + }, + }, + }, + expected: map[string]string{ + "BAZ": "bar", + }, + }, + { + name: "missing", + vars: config.Variables{}, + step: &ShellStep{ + Variables: []Variable{ + { + ConfigRef: "FOO", + }, + }, + }, + err: "failed to lookup config reference FOO for ", + }, + { + name: "type conversion", + vars: config.Variables{ + "FOO": 42, + }, + step: &ShellStep{ + Variables: []Variable{ + { + Name: "BAZ", + ConfigRef: "FOO", + }, + }, + }, + expected: map[string]string{ + "BAZ": "42", + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + envVars, err := tc.step.mapStepVariables(tc.vars) + t.Log(envVars) + if tc.err != "" { + assert.Error(t, err, tc.err) + } else { + assert.NilError(t, err) + assert.DeepEqual(t, envVars, tc.expected) + } + }) + } +} + +func TestRunShellStep(t *testing.T) { + testCases := []struct { + name string + vars config.Variables + step *ShellStep + err string + }{ + { + name: "basic", + vars: config.Variables{}, + step: &ShellStep{ + Command: "echo hello", + }, + }, + { + name: "test nounset", + vars: config.Variables{}, + step: &ShellStep{ + Command: "echo $DOES_NOT_EXIST", + }, + err: "DOES_NOT_EXIST: unbound variable\n exit status 1", + }, + { + name: "test errexit", + vars: config.Variables{}, + step: &ShellStep{ + Command: "false ; echo hello", + }, + err: "failed to execute shell command: exit status 1", + }, + { + name: "test pipefail", + vars: config.Variables{}, + step: &ShellStep{ + Command: "false | echo", + }, + err: "failed to execute shell command: \n exit status 1", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := runShellStep(tc.step, context.Background(), "", &PipelineRunOptions{}, map[string]output{}) + if tc.err != "" { + assert.ErrorContains(t, err, tc.err) + } else { + assert.NilError(t, err) + } + }) + } +} diff --git a/tooling/templatize/pkg/pipeline/types.go b/tooling/templatize/pkg/pipeline/types.go new file mode 100644 index 000000000..86ad9701a --- /dev/null +++ b/tooling/templatize/pkg/pipeline/types.go @@ -0,0 +1,251 @@ +package pipeline + +import ( + "context" + "fmt" + "strings" + + "gopkg.in/yaml.v3" +) + +type subsciptionLookup func(context.Context, string) (string, error) + +type Pipeline struct { + pipelineFilePath string + ServiceGroup string `yaml:"serviceGroup"` + RolloutName string `yaml:"rolloutName"` + ResourceGroups []*ResourceGroup `yaml:"resourceGroups"` +} + +type ResourceGroup struct { + Name string `yaml:"name"` + Subscription string `yaml:"subscription"` + AKSCluster string `yaml:"aksCluster,omitempty"` + Steps []Step `yaml:"steps"` +} + +func NewPlainPipelineFromBytes(filepath string, bytes []byte) (*Pipeline, error) { + rawPipeline := &struct { + ServiceGroup string `yaml:"serviceGroup"` + RolloutName string `yaml:"rolloutName"` + ResourceGroups []struct { + Name string `yaml:"name"` + Subscription string `yaml:"subscription"` + AKSCluster string `yaml:"aksCluster,omitempty"` + Steps []any `yaml:"steps"` + } `yaml:"resourceGroups"` + }{} + err := yaml.Unmarshal(bytes, rawPipeline) + if err != nil { + return nil, err + } + pipeline := &Pipeline{ + pipelineFilePath: filepath, + ServiceGroup: rawPipeline.ServiceGroup, + RolloutName: rawPipeline.RolloutName, + ResourceGroups: make([]*ResourceGroup, len(rawPipeline.ResourceGroups)), + } + + for i, rawRg := range rawPipeline.ResourceGroups { + rg := &ResourceGroup{} + pipeline.ResourceGroups[i] = rg + rg.Name = rawRg.Name + rg.Subscription = rawRg.Subscription + rg.AKSCluster = rawRg.AKSCluster + rg.Steps = make([]Step, len(rawRg.Steps)) + for i, rawStep := range rawRg.Steps { + // unmarshal the map into a StepMeta + stepMeta := &StepMeta{} + err := mapToStruct(rawStep, stepMeta) + if err != nil { + return nil, err + } + switch stepMeta.Action { + case "Shell": + rg.Steps[i] = &ShellStep{} + case "ARM": + rg.Steps[i] = &ARMStep{} + case "DelegateChildZone": + rg.Steps[i] = &DelegateChildZoneStep{} + case "SetCertificateIssuer": + rg.Steps[i] = &SetCertificateIssuerStep{} + default: + return nil, fmt.Errorf("unknown action type %s", stepMeta.Action) + } + err = mapToStruct(rawStep, rg.Steps[i]) + if err != nil { + return nil, err + } + } + } + + return pipeline, nil +} + +func mapToStruct(m any, s interface{}) error { + bytes, err := yaml.Marshal(m) + if err != nil { + return err + } + if err := yaml.Unmarshal(bytes, s); err != nil { + return err + + } + return nil +} + +type outPutHandler func(string) + +type StepMeta struct { + Name string `yaml:"name"` + Action string `yaml:"action"` + DependsOn []string `yaml:"dependsOn,omitempty"` +} + +func (m *StepMeta) StepName() string { + return m.Name +} + +func (m *StepMeta) ActionType() string { + return m.Action +} + +func (m *StepMeta) Dependencies() []string { + return m.DependsOn +} + +type Step interface { + StepName() string + ActionType() string + Description() string + Dependencies() []string +} + +func NewShellStep(name string, command string) *ShellStep { + return &ShellStep{ + StepMeta: StepMeta{ + Name: name, + Action: "Shell", + }, + Command: command, + } +} + +type ShellStep struct { + StepMeta `yaml:",inline"` + Command string `yaml:"command,omitempty"` + Variables []Variable `yaml:"variables,omitempty"` + DryRun DryRun `yaml:"dryRun,omitempty"` + outputFunc outPutHandler +} + +func (s *ShellStep) Description() string { + return fmt.Sprintf("Step %s\n Kind: %s\n Command: %s\n", s.Name, s.Action, s.Command) +} + +func (s *ShellStep) WithDependsOn(dependsOn ...string) *ShellStep { + s.DependsOn = dependsOn + return s +} + +func (s *ShellStep) WithVariables(variables ...Variable) *ShellStep { + s.Variables = variables + return s +} + +func (s *ShellStep) WithDryRun(dryRun DryRun) *ShellStep { + s.DryRun = dryRun + return s +} + +func (s *ShellStep) WithOutputFunc(outputFunc outPutHandler) *ShellStep { + s.outputFunc = outputFunc + return s +} + +func NewARMStep(name string, template string, parameters string, deploymentLevel string) *ARMStep { + return &ARMStep{ + StepMeta: StepMeta{ + Name: name, + Action: "ARM", + }, + Template: template, + Parameters: parameters, + DeploymentLevel: deploymentLevel, + } +} + +func (s *ARMStep) WithDependsOn(dependsOn ...string) *ARMStep { + s.DependsOn = dependsOn + return s +} + +func (s *ARMStep) WithVariables(variables ...Variable) *ARMStep { + s.Variables = variables + return s +} + +func (s *ARMStep) WithOutputOnly() *ARMStep { + s.OutputOnly = true + return s +} + +type ARMStep struct { + StepMeta `yaml:",inline"` + Command string `yaml:"command,omitempty"` + Variables []Variable `yaml:"variables,omitempty"` + Template string `yaml:"template,omitempty"` + Parameters string `yaml:"parameters,omitempty"` + DeploymentLevel string `yaml:"deploymentLevel,omitempty"` + OutputOnly bool `yaml:"outputOnly,omitempty"` +} + +func (s *ARMStep) Description() string { + var details []string + details = append(details, fmt.Sprintf("Template: %s", s.Template)) + details = append(details, fmt.Sprintf("Parameters: %s", s.Parameters)) + return fmt.Sprintf("Step %s\n Kind: %s\n %s", s.Name, s.Action, strings.Join(details, "\n ")) +} + +type DelegateChildZoneStep struct { + StepMeta `yaml:",inline"` + ParentZoneName VariableRef `yaml:"parentZone"` + ChildZoneName VariableRef `yaml:"childZone"` +} + +func (s *DelegateChildZoneStep) Description() string { + return fmt.Sprintf("Step %s\n Kind: %s", s.Name, s.Action) +} + +type SetCertificateIssuerStep struct { + StepMeta `yaml:",inline"` + VaultBaseUrl VariableRef `yaml:"vaultBaseUrl"` + Provider VariableRef `yaml:"provider"` +} + +func (s *SetCertificateIssuerStep) Description() string { + return fmt.Sprintf("Step %s\n Kind: %s", s.Name, s.Action) +} + +type DryRun struct { + Variables []Variable `yaml:"variables,omitempty"` + Command string `yaml:"command,omitempty"` +} + +type Variable struct { + Name string `yaml:"name"` + ConfigRef string `yaml:"configRef,omitempty"` + Value string `yaml:"value,omitempty"` + Input *Input `yaml:"input,omitempty"` +} + +type VariableRef struct { + ConfigRef string `yaml:"configRef,omitempty"` + Value string `yaml:"value,omitempty"` + Input *Input `yaml:"input,omitempty"` +} + +type Input struct { + Name string `yaml:"name"` + Step string `yaml:"step"` +} diff --git a/tooling/templatize/pkg/pipeline/validation.go b/tooling/templatize/pkg/pipeline/validation.go new file mode 100644 index 000000000..99877a654 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/validation.go @@ -0,0 +1,117 @@ +package pipeline + +import ( + _ "embed" + "encoding/json" + "fmt" + + "github.com/santhosh-tekuri/jsonschema/v6" + "gopkg.in/yaml.v3" +) + +//go:embed pipeline.schema.v1.json +var pipelineSchemaV1Content []byte +var pipelineSchemaV1Ref = "pipeline.schema.v1" +var defaultSchemaRef = pipelineSchemaV1Ref + +func ValidatePipelineSchema(pipelineContent []byte) error { + // unmarshal pipeline content + pipelineMap := make(map[string]interface{}) + err := yaml.Unmarshal(pipelineContent, &pipelineMap) + if err != nil { + return fmt.Errorf("failed to unmarshal pipeline YAML content: %v", err) + } + + // load pipeline schema + pipelineSchema, schemaRef, err := getSchemaForPipeline(pipelineMap) + if err != nil { + return fmt.Errorf("failed to load pipeline schema: %v", err) + } + + // validate pipeline schema + err = pipelineSchema.Validate(pipelineMap) + if err != nil { + return fmt.Errorf("pipeline is not compliant with schema %s: %v", schemaRef, err) + } + return nil +} + +func getSchemaForPipeline(pipelineMap map[string]interface{}) (pipelineSchema *jsonschema.Schema, schemaRef string, err error) { + schemaRef, ok := pipelineMap["$schema"].(string) + if !ok { + schemaRef = defaultSchemaRef + } + + switch schemaRef { + case pipelineSchemaV1Ref: + pipelineSchema, err = compileSchema(schemaRef, pipelineSchemaV1Content) + default: + return nil, "", fmt.Errorf("unsupported schema reference: %s", schemaRef) + } + return +} + +func compileSchema(schemaRef string, schemaBytes []byte) (*jsonschema.Schema, error) { + // parse schema content + schemaMap := make(map[string]interface{}) + err := json.Unmarshal(schemaBytes, &schemaMap) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal schema content: %v", err) + } + + // compile schema + c := jsonschema.NewCompiler() + err = c.AddResource(schemaRef, schemaMap) + if err != nil { + return nil, fmt.Errorf("failed to add schema resource %s: %v", schemaRef, err) + } + pipelineSchema, err := c.Compile(schemaRef) + if err != nil { + return nil, fmt.Errorf("failed to compile schema %s: %v", schemaRef, err) + } + + return pipelineSchema, nil +} + +func (p *Pipeline) Validate() error { + // collect all steps from all resourcegroups and fail if there are duplicates + stepMap := make(map[string]Step) + for _, rg := range p.ResourceGroups { + for _, step := range rg.Steps { + if _, ok := stepMap[step.StepName()]; ok { + return fmt.Errorf("duplicate step name %q", step.StepName()) + } + stepMap[step.StepName()] = step + } + } + + // validate dependsOn for a step exists + for _, step := range stepMap { + for _, dep := range step.Dependencies() { + if _, ok := stepMap[dep]; !ok { + return fmt.Errorf("invalid dependency on step %s: dependency %s does not exist", step.StepName(), dep) + } + } + } + + // todo check for circular dependencies + + // validate resource groups + for _, rg := range p.ResourceGroups { + err := rg.Validate() + if err != nil { + return err + } + } + return nil +} + +func (rg *ResourceGroup) Validate() error { + if rg.Name == "" { + return fmt.Errorf("resource group name is required") + } + if rg.Subscription == "" { + return fmt.Errorf("subscription is required") + } + return nil +} diff --git a/tooling/templatize/pkg/pipeline/validation_test.go b/tooling/templatize/pkg/pipeline/validation_test.go new file mode 100644 index 000000000..3855e0db8 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/validation_test.go @@ -0,0 +1,245 @@ +package pipeline + +import ( + "testing" + + "gopkg.in/yaml.v3" + "gotest.tools/v3/assert" +) + +func TestRGValidate(t *testing.T) { + testCases := []struct { + name string + rg *ResourceGroup + err string + }{ + { + name: "missing name", + rg: &ResourceGroup{}, + err: "resource group name is required", + }, + { + name: "missing subscription", + rg: &ResourceGroup{Name: "test"}, + err: "subscription is required", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.rg.Validate() + assert.Error(t, err, tc.err) + }) + } + +} + +func TestPipelineValidate(t *testing.T) { + testCases := []struct { + name string + pipeline *Pipeline + err string + }{ + { + name: "missing name", + pipeline: &Pipeline{ + ResourceGroups: []*ResourceGroup{{}}, + }, + err: "resource group name is required", + }, + { + name: "missing subscription", + pipeline: &Pipeline{ + ResourceGroups: []*ResourceGroup{ + { + Name: "rg", + }, + }, + }, + err: "subscription is required", + }, + { + name: "missing step dependency", + pipeline: &Pipeline{ + ResourceGroups: []*ResourceGroup{ + { + Name: "rg1", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step1", "echo foo"), + }, + }, + { + Name: "rg2", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step2", "echo bar").WithDependsOn("step3"), + }, + }, + }, + }, + err: "invalid dependency on step step2: dependency step3 does not exist", + }, + { + name: "duplicate step name", + pipeline: &Pipeline{ + ResourceGroups: []*ResourceGroup{ + { + Name: "rg1", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step1", "echo foo"), + }, + }, + { + Name: "rg2", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step1", "echo bar").WithDependsOn("step1"), + }, + }, + }, + }, + err: "duplicate step name \"step1\"", + }, + { + name: "valid step dependencies", + pipeline: &Pipeline{ + ResourceGroups: []*ResourceGroup{ + { + Name: "rg1", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step1", "echo foo"), + }, + }, + { + Name: "rg2", + Subscription: "sub1", + Steps: []Step{ + NewShellStep("step2", "echo bar").WithDependsOn("step1"), + }, + }, + }, + }, + err: "", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.pipeline.Validate() + if tc.err == "" { + assert.NilError(t, err) + } else { + assert.Error(t, err, tc.err) + } + }) + } +} + +func TestGetSchemaForPipeline(t *testing.T) { + testCases := []struct { + name string + pipeline map[string]interface{} + expectedSchemaRef string + err string + }{ + { + name: "default schema", + pipeline: map[string]interface{}{}, + expectedSchemaRef: defaultSchemaRef, + }, + { + name: "explicit schema", + pipeline: map[string]interface{}{ + "$schema": pipelineSchemaV1Ref, + }, + expectedSchemaRef: pipelineSchemaV1Ref, + }, + { + name: "invalid schema", + pipeline: map[string]interface{}{ + "$schema": "invalid", + }, + expectedSchemaRef: "", + err: "unsupported schema reference: invalid", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + schema, ref, err := getSchemaForPipeline(tc.pipeline) + if tc.err == "" { + assert.NilError(t, err) + assert.Assert(t, schema != nil) + if tc.expectedSchemaRef != "" { + assert.Equal(t, ref, tc.expectedSchemaRef) + } + } else { + assert.Error(t, err, tc.err) + } + }) + } +} + +func TestValidatePipelineSchema(t *testing.T) { + testCases := []struct { + name string + pipeline map[string]interface{} + expectedSchemaRef string + err string + }{ + { + name: "valid shell", + pipeline: map[string]interface{}{ + "serviceGroup": "test", + "rolloutName": "test", + "resourceGroups": []interface{}{ + map[string]interface{}{ + "name": "rg", + "subscription": "sub", + "aksCluster": "aks", + "steps": []interface{}{ + map[string]interface{}{ + "name": "step", + "action": "Shell", + "command": "echo hello", + }, + }, + }, + }, + }, + }, + { + name: "invalid", + pipeline: map[string]interface{}{ + "serviceGroup": "test", + "rolloutName": "test", + "resourceGroups": []interface{}{ + map[string]interface{}{ + "name": "rg", + "subscription": "sub", + "aksCluster": "aks", + "steps": []interface{}{ + map[string]interface{}{ + "name": "step", + "action": "Shell", + }, + }, + }, + }, + }, + err: "pipeline is not compliant with schema pipeline.schema.v1", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + pipelineBytes, err := yaml.Marshal(tc.pipeline) + assert.NilError(t, err) + err = ValidatePipelineSchema(pipelineBytes) + if tc.err == "" { + assert.NilError(t, err) + } else { + assert.ErrorContains(t, err, tc.err) + } + }) + } +} diff --git a/tooling/templatize/pkg/utils/env.go b/tooling/templatize/pkg/utils/env.go new file mode 100644 index 000000000..2798a3746 --- /dev/null +++ b/tooling/templatize/pkg/utils/env.go @@ -0,0 +1,35 @@ +package utils + +import ( + "fmt" + "maps" + "os" + "strings" +) + +// GetOsVariable looks up OS environment variables and returns them as a map. +// It also sets a special environment variable RUNS_IN_TEMPLATIZE to 1. +func GetOsVariable() map[string]string { + envVars := make(map[string]string) + envVars["RUNS_IN_TEMPLATIZE"] = "1" + + osVars := make(map[string]string) + for _, env := range os.Environ() { + parts := strings.SplitN(env, "=", 2) + if len(parts) == 2 { + envVars[parts[0]] = parts[1] + } + } + maps.Copy(envVars, osVars) + + return envVars +} + +// MapToEnvVarArray converts a map of environment variables to an array of strings. +func MapToEnvVarArray(envVars map[string]string) []string { + envVarArray := make([]string, 0, len(envVars)) + for k, v := range envVars { + envVarArray = append(envVarArray, fmt.Sprintf("%s=%s", k, v)) + } + return envVarArray +} diff --git a/tooling/templatize/pkg/utils/env_test.go b/tooling/templatize/pkg/utils/env_test.go new file mode 100644 index 000000000..2d15ac8c0 --- /dev/null +++ b/tooling/templatize/pkg/utils/env_test.go @@ -0,0 +1,22 @@ +package utils + +import ( + "testing" + + "gotest.tools/assert" +) + +func TestGetOsVariable(t *testing.T) { + t.Setenv("FOO", "BAR") + envVars := GetOsVariable() + assert.Equal(t, "1", envVars["RUNS_IN_TEMPLATIZE"]) + assert.Equal(t, "BAR", envVars["FOO"]) +} + +func TestMapToEnvVarArray(t *testing.T) { + envVars := map[string]string{ + "FOO": "BAR", + } + envVarArray := MapToEnvVarArray(envVars) + assert.DeepEqual(t, []string{"FOO=BAR"}, envVarArray) +} diff --git a/tooling/templatize/pkg/utils/typing.go b/tooling/templatize/pkg/utils/typing.go new file mode 100644 index 000000000..dba9a4f49 --- /dev/null +++ b/tooling/templatize/pkg/utils/typing.go @@ -0,0 +1,19 @@ +package utils + +import ( + "fmt" +) + +// AnyToString maps some types to strings, as they are used in OS Env. +func AnyToString(value any) string { + switch v := value.(type) { + case string: + return v + case int: + return fmt.Sprintf("%d", v) + case bool: + return fmt.Sprintf("%t", v) + default: + return fmt.Sprintf("%v", v) + } +} diff --git a/tooling/templatize/pkg/utils/typing_test.go b/tooling/templatize/pkg/utils/typing_test.go new file mode 100644 index 000000000..9797c1455 --- /dev/null +++ b/tooling/templatize/pkg/utils/typing_test.go @@ -0,0 +1,14 @@ +package utils + +import ( + "testing" + + "gotest.tools/assert" +) + +func TestAnyToString(t *testing.T) { + assert.Equal(t, "foo", AnyToString("foo")) + assert.Equal(t, "42", AnyToString(42)) + assert.Equal(t, "true", AnyToString(true)) + assert.Equal(t, "3.14", AnyToString(3.14)) +} diff --git a/tooling/templatize/serviceconfig.json b/tooling/templatize/serviceconfig.json new file mode 100644 index 000000000..01c9b2ee7 --- /dev/null +++ b/tooling/templatize/serviceconfig.json @@ -0,0 +1,507 @@ +{ + "Settings": {}, + "Geographies": [ + { + "Name": "Asia Pacific", + "Settings": {}, + "Regions": [ + { + "Name": "apacsoutheast2", + "Settings": {} + }, + { + "Name": "eastasia", + "Settings": {} + }, + { + "Name": "southeastasia", + "Settings": {} + } + ] + }, + { + "Name": "Australia", + "Settings": {}, + "Regions": [ + { + "Name": "australiacentral", + "Settings": {} + }, + { + "Name": "australiacentral2", + "Settings": {} + }, + { + "Name": "australiaeast", + "Settings": {} + }, + { + "Name": "australiasoutheast", + "Settings": {} + } + ] + }, + { + "Name": "Austria", + "Settings": {}, + "Regions": [ + { + "Name": "austriaeast", + "Settings": {} + } + ] + }, + { + "Name": "Belgium", + "Settings": {}, + "Regions": [ + { + "Name": "belgiumcentral", + "Settings": {} + } + ] + }, + { + "Name": "Brazil", + "Settings": {}, + "Regions": [ + { + "Name": "brazilnortheast", + "Settings": {} + }, + { + "Name": "brazilsouth", + "Settings": {} + }, + { + "Name": "brazilsoutheast", + "Settings": {} + } + ] + }, + { + "Name": "Canada", + "Settings": {}, + "Regions": [ + { + "Name": "canadacentral", + "Settings": {} + }, + { + "Name": "canadaeast", + "Settings": {} + } + ] + }, + { + "Name": "Canary (US)", + "Settings": {}, + "Regions": [ + { + "Name": "centraluseuap", + "Settings": {} + }, + { + "Name": "eastus2euap", + "Settings": {} + } + ] + }, + { + "Name": "Chile", + "Settings": {}, + "Regions": [ + { + "Name": "chilecentral", + "Settings": {} + } + ] + }, + { + "Name": "Denmark", + "Settings": {}, + "Regions": [ + { + "Name": "denmarkeast", + "Settings": {} + } + ] + }, + { + "Name": "Europe", + "Settings": {}, + "Regions": [ + { + "Name": "northeurope", + "Settings": {} + }, + { + "Name": "westeurope", + "Settings": {} + } + ] + }, + { + "Name": "France", + "Settings": {}, + "Regions": [ + { + "Name": "francecentral", + "Settings": {} + }, + { + "Name": "francesouth", + "Settings": {} + } + ] + }, + { + "Name": "Germany", + "Settings": {}, + "Regions": [ + { + "Name": "germanynorth", + "Settings": {} + }, + { + "Name": "germanywestcentral", + "Settings": {} + } + ] + }, + { + "Name": "India", + "Settings": {}, + "Regions": [ + { + "Name": "centralindia", + "Settings": {} + }, + { + "Name": "jioindiacentral", + "Settings": {} + }, + { + "Name": "jioindiawest", + "Settings": {} + }, + { + "Name": "southindia", + "Settings": {} + }, + { + "Name": "westindia", + "Settings": {} + } + ] + }, + { + "Name": "Indonesia", + "Settings": {}, + "Regions": [ + { + "Name": "indonesiacentral", + "Settings": {} + } + ] + }, + { + "Name": "Israel", + "Settings": {}, + "Regions": [ + { + "Name": "israelcentral", + "Settings": {} + }, + { + "Name": "israelnorthwest", + "Settings": {} + } + ] + }, + { + "Name": "Italy", + "Settings": {}, + "Regions": [ + { + "Name": "italynorth", + "Settings": {} + } + ] + }, + { + "Name": "Japan", + "Settings": {}, + "Regions": [ + { + "Name": "japaneast", + "Settings": {} + }, + { + "Name": "japanwest", + "Settings": {} + } + ] + }, + { + "Name": "Korea", + "Settings": {}, + "Regions": [ + { + "Name": "koreacentral", + "Settings": {} + }, + { + "Name": "koreasouth", + "Settings": {} + }, + { + "Name": "koreasouth2", + "Settings": {} + } + ] + }, + { + "Name": "Malaysia", + "Settings": {}, + "Regions": [ + { + "Name": "malaysiasouth", + "Settings": {} + }, + { + "Name": "malaysiawest", + "Settings": {} + } + ] + }, + { + "Name": "Mexico", + "Settings": {}, + "Regions": [ + { + "Name": "mexicocentral", + "Settings": {} + } + ] + }, + { + "Name": "New Zealand", + "Settings": {}, + "Regions": [ + { + "Name": "newzealandnorth", + "Settings": {} + } + ] + }, + { + "Name": "Norway", + "Settings": {}, + "Regions": [ + { + "Name": "norwayeast", + "Settings": {} + }, + { + "Name": "norwaywest", + "Settings": {} + } + ] + }, + { + "Name": "Poland", + "Settings": {}, + "Regions": [ + { + "Name": "polandcentral", + "Settings": {} + } + ] + }, + { + "Name": "Qatar", + "Settings": {}, + "Regions": [ + { + "Name": "qatarcentral", + "Settings": {} + } + ] + }, + { + "Name": "South Africa", + "Settings": {}, + "Regions": [ + { + "Name": "southafricanorth", + "Settings": {} + }, + { + "Name": "southafricawest", + "Settings": {} + } + ] + }, + { + "Name": "Spain", + "Settings": {}, + "Regions": [ + { + "Name": "spaincentral", + "Settings": {} + } + ] + }, + { + "Name": "Stage (US)", + "Settings": {}, + "Regions": [ + { + "Name": "eastusslv", + "Settings": {} + }, + { + "Name": "eastusstg", + "Settings": {} + }, + { + "Name": "southcentralusstg", + "Settings": {} + } + ] + }, + { + "Name": "Sweden", + "Settings": {}, + "Regions": [ + { + "Name": "swedencentral", + "Settings": {} + }, + { + "Name": "swedensouth", + "Settings": {} + } + ] + }, + { + "Name": "Switzerland", + "Settings": {}, + "Regions": [ + { + "Name": "switzerlandnorth", + "Settings": {} + }, + { + "Name": "switzerlandwest", + "Settings": {} + } + ] + }, + { + "Name": "Taiwan", + "Settings": {}, + "Regions": [ + { + "Name": "taiwannorth", + "Settings": {} + }, + { + "Name": "taiwannorthwest", + "Settings": {} + } + ] + }, + { + "Name": "UAE", + "Settings": {}, + "Regions": [ + { + "Name": "uaecentral", + "Settings": {} + }, + { + "Name": "uaenorth", + "Settings": {} + } + ] + }, + { + "Name": "United Kingdom", + "Settings": {}, + "Regions": [ + { + "Name": "uksouth", + "Settings": {} + }, + { + "Name": "ukwest", + "Settings": {} + } + ] + }, + { + "Name": "United States", + "Settings": {}, + "Regions": [ + { + "Name": "centralus", + "Settings": {} + }, + { + "Name": "eastus", + "Settings": {} + }, + { + "Name": "eastus2", + "Settings": {} + }, + { + "Name": "northcentralus", + "Settings": {} + }, + { + "Name": "southcentralus", + "Settings": {} + }, + { + "Name": "southcentralus2", + "Settings": {} + }, + { + "Name": "southeastus", + "Settings": {} + }, + { + "Name": "southeastus3", + "Settings": {} + }, + { + "Name": "southeastus5", + "Settings": {} + }, + { + "Name": "southwestus", + "Settings": {} + }, + { + "Name": "westcentralus", + "Settings": {} + }, + { + "Name": "westus", + "Settings": {} + }, + { + "Name": "westus2", + "Settings": {} + }, + { + "Name": "westus3", + "Settings": {} + } + ] + } + ] +} diff --git a/tooling/templatize/testdata/Makefile b/tooling/templatize/testdata/Makefile new file mode 100644 index 000000000..71375ec54 --- /dev/null +++ b/tooling/templatize/testdata/Makefile @@ -0,0 +1,4 @@ +deploy: + echo ${DRY_RUN} + +.PHONE: deploy diff --git a/tooling/templatize/testdata/config.yaml b/tooling/templatize/testdata/config.yaml index 0eb03e986..ea16ffb32 100644 --- a/tooling/templatize/testdata/config.yaml +++ b/tooling/templatize/testdata/config.yaml @@ -1,9 +1,21 @@ +$schema: schema.json defaults: - tenantId: "72f988bf-86f1-41af-91ab-2d7cd011db47" - region_resourcegroup: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }} - region_eventgrid_namespace: maestro-eventgrid-{{ .ctx.region }}-{{ .ctx.regionStamp }} - aks_name: aro-hcp-aks - maestro_msi: "maestro-server" + region: {{ .ctx.region }} + serviceClusterSubscription: hcp-{{ .ctx.region }} + managementClusterSubscription: hcp-{{ .ctx.region }} + globalRG: global + regionRG: hcp-underlay-{{ .ctx.regionShort }} + serviceClusterRG: hcp-underlay-{{ .ctx.regionShort }}-svc + managementClusterRG: hcp-underlay-{{ .ctx.regionShort }}-mgmt-{{ .ctx.stamp }} + imageSyncRG: hcp-underlay-{{ .ctx.regionShort }}-imagesync + aksName: aro-hcp-aks + clusterService: + imageTag: abcdef + replicas: 3 + parentZone: example.com + childZone: child.example.com + vaultBaseUrl: myvault.azure.com + provider: Self clouds: fairfax: defaults: @@ -12,9 +24,7 @@ clouds: environments: dev: defaults: - region_resourcegroup: hcp-underlay-{{ .ctx.region }}-{{ .ctx.regionStamp }} - region_maestro_keyvault: maestro-kv-{{ .ctx.region }}-{{ .ctx.regionStamp }} - svc_resourcegroup: hcp-underlay-{{ .ctx.region }}-svc-{{ .ctx.regionStamp }} + regionRG: hcp-underlay-{{ .ctx.region }}-dev maestro_helm_chart: ../maestro/deploy/helm/server maestro_image: aro-hcp-dev.azurecr.io/maestro-server:the-new-one int: diff --git a/tooling/templatize/testdata/helm.sh b/tooling/templatize/testdata/helm.sh deleted file mode 100644 index cf099fc08..000000000 --- a/tooling/templatize/testdata/helm.sh +++ /dev/null @@ -1,26 +0,0 @@ -# copy from maestro/Makefile#L14 -deploy-server: - TENANT_ID="{{ .tenantId }}" - REGION_RG="{{ .region_resourcegroup }}" - EVENTGRID_NS="{{ .region_eventgrid_namespace }}" - MAESTRO_KV="{{ .region_maestro_keyvault }}" - SERVICE_RG="{{ .svc_resourcegroup }}" - AKS="{{ .aks_name }}" - MAESTRO_MI="{{ .maestro_msi }}" - HELM_CHART="{{ .maestro_helm_chart }}" - - EVENTGRID_HOSTNAME=$(az event namespace show -g "${REGION_RG}" -n "${EVENTGRID_NS}" --query "properties.topicSpacesConfiguration.hostname") - MAESTRO_MI_CLIENT_ID=$(az identity show -g "${SERVICE_RG}" -n "${MAESTRO_MI}" --query "clientId") - ISTO_VERSION=$(az aks show -g "${SERVICE_RG}" -n "${AKS}" --query "serviceMeshProfile.istio.revisions[-1]") - - kubectl create namespace maestro --dry-run=client -o json | kubectl apply -f - && \ - kubectl label namespace maestro "istio.io/rev=${ISTO_VERSION}" --overwrite=true && \ - helm upgrade --install maestro-server "${HELM_CHART}" \ - --namespace maestro \ - --set broker.host=${EVENTGRID_HOSTNAME} \ - --set credsKeyVault.name=${MAESTRO_KV} \ - --set azure.clientId=${MAESTRO_MI_CLIENT_ID} \ - --set azure.tenantId=${TENANT_ID} \ - --set image.base='quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro'\ - --set database.containerizedDb=true \ - --set database.ssl=disable diff --git a/tooling/templatize/testdata/pipeline.yaml b/tooling/templatize/testdata/pipeline.yaml new file mode 100644 index 000000000..546b4559b --- /dev/null +++ b/tooling/templatize/testdata/pipeline.yaml @@ -0,0 +1,42 @@ +$schema: pipeline.schema.v1 +serviceGroup: Microsoft.Azure.ARO.Test +rolloutName: Test Rollout +resourceGroups: +- name: {{ .regionRG }} + subscription: {{ .serviceClusterSubscription }} + aksCluster: {{ .aksName }} + steps: + - name: deploy + action: Shell + command: make deploy + variables: + - name: MAESTRO_IMAGE + configRef: maestro_image + - name: dry-run + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "A very dry one" + - name: svc + action: ARM + template: templates/svc-cluster.bicep + parameters: test.bicepparam + deploymentLevel: ResourceGroup + - name: cxChildZone + action: DelegateChildZone + parentZone: + configRef: parentZone + childZone: + configRef: childZone + dependsOn: + - deploy + - name: issuerTest + action: SetCertificateIssuer + vaultBaseUrl: + configRef: vaultBaseUrl + provider: + configRef: provider + dependsOn: + - deploy diff --git a/tooling/templatize/testdata/schema.json b/tooling/templatize/testdata/schema.json new file mode 100644 index 000000000..1faa0c939 --- /dev/null +++ b/tooling/templatize/testdata/schema.json @@ -0,0 +1,3 @@ +{ + "type": "object" +} \ No newline at end of file diff --git a/tooling/templatize/testdata/test.bicepparam b/tooling/templatize/testdata/test.bicepparam index 8fa281a11..360f9c706 100644 --- a/tooling/templatize/testdata/test.bicepparam +++ b/tooling/templatize/testdata/test.bicepparam @@ -5,10 +5,6 @@ using '../templates/region.bicep' param baseDNSZoneName = 'hcp.osadev.cloud' param baseDNSZoneResourceGroup = 'global' -// maestro -param maestroKeyVaultNamea = '{{ .region_maestro_keyvault }}' -param maestroEventGridNamespacesName = '{{ .region_eventgrid_namespace }}' -param maestroEventGridMaxClientSessionsPerAuthName = 4 - -// These parameters are always overriden in the Makefile -param currentUserId = '' +// CS +param csImage = '{{ .clusterService.imageTag }}' +param regionRG = '{{ .regionRG }}' diff --git a/tooling/templatize/testdata/zz_fixture_TestPreprocessContent.bicepparam b/tooling/templatize/testdata/zz_fixture_TestPreprocessContent.bicepparam new file mode 100644 index 000000000..4d6e5f22b --- /dev/null +++ b/tooling/templatize/testdata/zz_fixture_TestPreprocessContent.bicepparam @@ -0,0 +1,10 @@ +// copy from dev-infrastructure/configurations/region.bicepparam +using '../templates/region.bicep' + +// dns +param baseDNSZoneName = 'hcp.osadev.cloud' +param baseDNSZoneResourceGroup = 'global' + +// CS +param csImage = 'cs-image' +param regionRG = 'bahamas' diff --git a/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2ev2-precompiled-test.bicepparam b/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2ev2-precompiled-test.bicepparam new file mode 100644 index 000000000..f4a96c83f --- /dev/null +++ b/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2ev2-precompiled-test.bicepparam @@ -0,0 +1,2 @@ +param regionRG = '__regionRG__' +param replicas = any('__clusterService.replicas__') \ No newline at end of file diff --git a/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2pipeline.yaml b/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2pipeline.yaml new file mode 100644 index 000000000..40302a92b --- /dev/null +++ b/tooling/templatize/testdata/zz_fixture_TestProcessPipelineForEV2pipeline.yaml @@ -0,0 +1,41 @@ +serviceGroup: Microsoft.Azure.ARO.Test +rolloutName: Test Rollout +resourceGroups: + - name: hcp-underlay-$(regionShortName) + subscription: hcp-$location() + aksCluster: aro-hcp-aks + steps: + - name: deploy + action: Shell + command: make deploy + variables: + - name: MAESTRO_IMAGE + configRef: maestro_image + - name: dry-run + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: A very dry one + - name: svc + action: ARM + template: templates/svc-cluster.bicep + parameters: ev2-precompiled-test.bicepparam + deploymentLevel: ResourceGroup + - name: cxChildZone + action: DelegateChildZone + dependsOn: + - deploy + parentZone: + configRef: parentZone + childZone: + configRef: childZone + - name: issuerTest + action: SetCertificateIssuer + dependsOn: + - deploy + vaultBaseUrl: + configRef: vaultBaseUrl + provider: + configRef: provider diff --git a/tooling/templatize/testdata/zz_fixture_TestRawOptions.sh b/tooling/templatize/testdata/zz_fixture_TestRawOptions.sh deleted file mode 100644 index 198bb1a47..000000000 --- a/tooling/templatize/testdata/zz_fixture_TestRawOptions.sh +++ /dev/null @@ -1,26 +0,0 @@ -# copy from maestro/Makefile#L14 -deploy-server: - TENANT_ID="72f988bf-86f1-41af-91ab-2d7cd011db47" - REGION_RG="hcp-underlay-uksouth-1" - EVENTGRID_NS="maestro-eventgrid-uksouth-1" - MAESTRO_KV="maestro-kv-uksouth-1" - SERVICE_RG="hcp-underlay-uksouth-svc-1" - AKS="aro-hcp-aks" - MAESTRO_MI="maestro-server" - HELM_CHART="../maestro/deploy/helm/server" - - EVENTGRID_HOSTNAME=$(az event namespace show -g "${REGION_RG}" -n "${EVENTGRID_NS}" --query "properties.topicSpacesConfiguration.hostname") - MAESTRO_MI_CLIENT_ID=$(az identity show -g "${SERVICE_RG}" -n "${MAESTRO_MI}" --query "clientId") - ISTO_VERSION=$(az aks show -g "${SERVICE_RG}" -n "${AKS}" --query "serviceMeshProfile.istio.revisions[-1]") - - kubectl create namespace maestro --dry-run=client -o json | kubectl apply -f - && \ - kubectl label namespace maestro "istio.io/rev=${ISTO_VERSION}" --overwrite=true && \ - helm upgrade --install maestro-server "${HELM_CHART}" \ - --namespace maestro \ - --set broker.host=${EVENTGRID_HOSTNAME} \ - --set credsKeyVault.name=${MAESTRO_KV} \ - --set azure.clientId=${MAESTRO_MI_CLIENT_ID} \ - --set azure.tenantId=${TENANT_ID} \ - --set image.base='quay.io/redhat-user-workloads/maestro-rhtap-tenant/maestro/maestro'\ - --set database.containerizedDb=true \ - --set database.ssl=disable diff --git a/tooling/templatize/testdata/zz_fixture_TestRawOptions.yaml b/tooling/templatize/testdata/zz_fixture_TestRawOptions.yaml new file mode 100644 index 000000000..d854184db --- /dev/null +++ b/tooling/templatize/testdata/zz_fixture_TestRawOptions.yaml @@ -0,0 +1,42 @@ +$schema: pipeline.schema.v1 +serviceGroup: Microsoft.Azure.ARO.Test +rolloutName: Test Rollout +resourceGroups: +- name: hcp-underlay-uksouth-dev + subscription: hcp-uksouth + aksCluster: aro-hcp-aks + steps: + - name: deploy + action: Shell + command: make deploy + variables: + - name: MAESTRO_IMAGE + configRef: maestro_image + - name: dry-run + action: Shell + command: make deploy + dryRun: + variables: + - name: DRY_RUN + value: "A very dry one" + - name: svc + action: ARM + template: templates/svc-cluster.bicep + parameters: test.bicepparam + deploymentLevel: ResourceGroup + - name: cxChildZone + action: DelegateChildZone + parentZone: + configRef: parentZone + childZone: + configRef: childZone + dependsOn: + - deploy + - name: issuerTest + action: SetCertificateIssuer + vaultBaseUrl: + configRef: vaultBaseUrl + provider: + configRef: provider + dependsOn: + - deploy