├── .codespellignore ├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── codespell.yml │ ├── link-check.yml │ ├── lint.yml │ └── pr-gh-workflow-approve.yaml ├── .gitignore ├── .golangci.yml ├── .markdownlinkcheck.json ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── OWNERS ├── OWNERS_ALIASES ├── PROJECT ├── README.md ├── SECURITY_CONTACTS ├── Tiltfile ├── api └── v1beta1 │ ├── doc.go │ ├── endpoints.go │ ├── gcpcluster_conversion.go │ ├── gcpcluster_types.go │ ├── gcpcluster_webhook.go │ ├── gcpcluster_webhook_test.go │ ├── gcpclustertemplate_conversion.go │ ├── gcpclustertemplate_types.go │ ├── gcpclustertemplate_webhook.go │ ├── gcpclustertemplate_webhook_test.go │ ├── gcpmachine_conversion.go │ ├── gcpmachine_types.go │ ├── gcpmachine_webhook.go │ ├── gcpmachine_webhook_test.go │ ├── gcpmachinetemplate_conversion.go │ ├── gcpmachinetemplate_types.go │ ├── gcpmachinetemplate_webhook.go │ ├── gcpmachinetemplate_webhook_test.go │ ├── groupversion_info.go │ ├── labels.go │ ├── tags.go │ ├── types.go │ └── zz_generated.deepcopy.go ├── cloud ├── defaults.go ├── doc.go ├── gcperrors │ └── errors.go ├── interfaces.go ├── providerid │ ├── doc.go │ ├── providerid.go │ └── providerid_test.go ├── scope │ ├── clients.go │ ├── cluster.go │ ├── credentials.go │ ├── getters.go │ ├── machine.go │ ├── machine_test.go │ ├── managedcluster.go │ ├── managedcontrolplane.go │ ├── managedmachinepool.go │ ├── managedmachinepool_test.go │ ├── providerid.go │ └── scope_suite_test.go └── services │ ├── compute │ ├── firewalls │ │ ├── doc.go │ │ ├── reconcile.go │ │ ├── reconcile_test.go │ │ └── service.go │ ├── instances │ │ ├── doc.go │ │ ├── reconcile.go │ │ ├── reconcile_test.go │ │ └── service.go │ ├── loadbalancers │ │ ├── doc.go │ │ ├── reconcile.go │ │ ├── reconcile_test.go │ │ └── service.go │ ├── networks │ │ ├── doc.go │ │ ├── reconcile.go │ │ ├── reconcile_test.go │ │ └── service.go │ └── subnets │ │ ├── doc.go │ │ ├── reconcile.go │ │ ├── reconcile_test.go │ │ └── service.go │ ├── container │ ├── clusters │ │ ├── doc.go │ │ ├── errors.go │ │ ├── kubeconfig.go │ │ ├── reconcile.go │ │ └── service.go │ └── nodepools │ │ ├── doc.go │ │ ├── reconcile.go │ │ └── service.go │ └── shared │ ├── doc.go │ ├── machinepool.go │ └── tags.go ├── cloudbuild-nightly.yaml ├── cloudbuild.yaml ├── clusterctl-settings.json ├── code-of-conduct.md ├── config ├── certmanager │ ├── certificate.yaml │ ├── kustomization.yaml │ └── kustomizeconfig.yaml ├── crd │ ├── bases │ │ ├── infrastructure.cluster.x-k8s.io_gcpclusters.yaml │ │ ├── infrastructure.cluster.x-k8s.io_gcpclustertemplates.yaml │ │ ├── infrastructure.cluster.x-k8s.io_gcpmachines.yaml │ │ ├── infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml │ │ ├── infrastructure.cluster.x-k8s.io_gcpmanagedclusters.yaml │ │ ├── infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml │ │ └── infrastructure.cluster.x-k8s.io_gcpmanagedmachinepools.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ │ ├── cainjection_in_gcpclusters.yaml │ │ ├── cainjection_in_gcpclustertemplates.yaml │ │ ├── cainjection_in_gcpmachines.yaml │ │ ├── cainjection_in_gcpmachinetemplates.yaml │ │ ├── webhook_in_gcpclusters.yaml │ │ ├── webhook_in_gcpclustertemplates.yaml │ │ ├── webhook_in_gcpmachines.yaml │ │ └── webhook_in_gcpmachinetemplates.yaml ├── default │ ├── credentials.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── manager_credentials_patch.yaml │ ├── manager_image_patch.yaml │ ├── manager_prometheus_metrics_patch.yaml │ ├── manager_pull_policy.yaml │ ├── manager_webhook_patch.yaml │ ├── namespace.yaml │ └── webhookcainjection_patch.yaml ├── manager │ ├── kustomization.yaml │ └── manager.yaml ├── rbac │ ├── gcpclustertemplate_editor_role.yaml │ ├── gcpclustertemplate_viewer_role.yaml │ ├── kustomization.yaml │ ├── leader_election_role.yaml │ ├── leader_election_role_binding.yaml │ ├── role.yaml │ ├── role_binding.yaml │ └── service_account.yaml └── webhook │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── manifests.yaml │ └── service.yaml ├── controllers ├── gcpcluster_controller.go ├── gcpcluster_controller_test.go ├── gcpmachine_controller.go ├── gcpmachine_controller_test.go ├── gcpmachine_controller_unit_test.go └── suite_test.go ├── docs ├── README.md ├── book │ ├── Makefile │ ├── book.toml │ ├── src │ │ ├── SUMMARY.md │ │ ├── clusterclass │ │ │ ├── disabling.md │ │ │ ├── enabling.md │ │ │ ├── index.md │ │ │ └── provision.md │ │ ├── developers │ │ │ ├── cluster-creation.md │ │ │ ├── development.md │ │ │ ├── e2e.md │ │ │ ├── index.md │ │ │ ├── jobs.md │ │ │ ├── nightlies.md │ │ │ └── releasing.md │ │ ├── introduction.md │ │ ├── managed │ │ │ ├── disabling.md │ │ │ ├── enabling.md │ │ │ ├── index.md │ │ │ ├── provision.md │ │ │ └── upgrades.md │ │ ├── prerequisites.md │ │ ├── quick-start.md │ │ ├── roadmap.md │ │ ├── self-managed │ │ │ ├── cni.md │ │ │ ├── index.md │ │ │ └── provision.md │ │ └── topics │ │ │ ├── conformance.md │ │ │ ├── index.md │ │ │ ├── machine-locations.md │ │ │ └── preemptible-vms.md │ └── theme │ │ ├── css │ │ └── general.css │ │ ├── favicon.png │ │ └── head.hbs └── proposals │ └── 20221123-managed-kubernetes-in-capg.md ├── exp ├── PROJECT ├── README.md ├── api │ └── v1beta1 │ │ ├── conditions_consts.go │ │ ├── gcpmanagedcluster_types.go │ │ ├── gcpmanagedcluster_webhook.go │ │ ├── gcpmanagedcluster_webhook_test.go │ │ ├── gcpmanagedcontrolplane_types.go │ │ ├── gcpmanagedcontrolplane_webhook.go │ │ ├── gcpmanagedcontrolplane_webhook_test.go │ │ ├── gcpmanagedmachinepool_types.go │ │ ├── gcpmanagedmachinepool_webhook.go │ │ ├── gcpmanagedmachinepool_webhook_test.go │ │ ├── groupversion_info.go │ │ ├── types.go │ │ ├── webhook_suite_test.go │ │ └── zz_generated.deepcopy.go ├── controllers │ ├── doc.go │ ├── gcpmanagedcluster_controller.go │ ├── gcpmanagedcontrolplane_controller.go │ ├── gcpmanagedmachinepool_controller.go │ └── suite_test.go ├── doc.go └── hack │ └── boilerplate.go.txt ├── feature ├── feature.go └── gates.go ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt ├── boilerplate │ ├── BUILD │ ├── boilerplate.Dockerfile.txt │ ├── boilerplate.Makefile.txt │ ├── boilerplate.bzl.txt │ ├── boilerplate.generatebzl.txt │ ├── boilerplate.generatego.txt │ ├── boilerplate.go.txt │ ├── boilerplate.py │ ├── boilerplate.py.txt │ ├── boilerplate.sh.txt │ ├── boilerplate_test.py │ └── test │ │ ├── fail.go │ │ ├── fail.py │ │ ├── pass.go │ │ └── pass.py ├── checkin_account.py ├── checkout_account.py ├── ensure-go.sh ├── ensure-kustomize.sh ├── heartbeat_account.py ├── install-cert-manager.sh ├── kustomize-sub.sh ├── tools │ ├── Makefile │ ├── go.mod │ ├── go.sum │ └── tools.go ├── verify-boilerplate.sh ├── verify-shellcheck.sh ├── verify-starlark.sh └── version.sh ├── main.go ├── metadata.yaml ├── netlify.toml ├── scripts ├── ci-apidiff.sh ├── ci-build.sh ├── ci-conformance.sh ├── ci-e2e.sh ├── ci-make.sh ├── ci-test-coverage.sh ├── ci-test.sh ├── go_install.sh ├── kind-with-registry.sh └── setup-dev-enviroment.sh ├── templates ├── cluster-template-clusterclass.yaml ├── cluster-template-gke-autopilot.yaml ├── cluster-template-gke.yaml ├── cluster-template-topology.yaml ├── cluster-template.yaml ├── kustomization.yaml └── kustomizeversions.yaml ├── test └── e2e │ ├── capi_test.go │ ├── common.go │ ├── config │ └── gcp-ci.yaml │ ├── conformance_test.go │ ├── data │ ├── ccm │ │ └── gce-cloud-controller-manager.yaml │ ├── cni │ │ └── calico │ │ │ └── calico.yaml │ ├── infrastructure-gcp │ │ ├── cluster-template-ci-gke-autopilot.yaml │ │ ├── cluster-template-ci-gke-custom-subnet.yaml │ │ ├── cluster-template-ci-gke.yaml │ │ ├── cluster-template-ci-with-creds.yaml │ │ ├── cluster-template-ci-with-internal-lb.yaml │ │ ├── cluster-template-ci.yaml │ │ ├── cluster-template-kcp-remediation.yaml │ │ ├── cluster-template-md-remediation.yaml │ │ ├── cluster-template-prow-ci-version.yaml │ │ ├── cluster-template-upgrades.yaml │ │ ├── clusterclass-quick-start.yaml │ │ └── withclusterclass │ │ │ └── cluster-template-ci-topology.yaml │ ├── kubetest │ │ └── conformance.yaml │ └── shared │ │ └── v1beta1 │ │ └── metadata.yaml │ ├── e2e_gke_test.go │ ├── e2e_test.go │ ├── gke.go │ ├── helpers.go │ └── suite_test.go ├── tilt-provider.json ├── tilt_modules ├── cert_manager │ ├── README.md │ ├── Tiltfile │ └── test │ │ ├── Tiltfile │ │ └── test.sh └── extensions.json ├── util ├── hash │ └── base36.go ├── location │ └── location.go ├── reconciler │ ├── defaults.go │ └── defaults_test.go └── resourceurl │ └── parse.go └── version └── version.go /.codespellignore: -------------------------------------------------------------------------------- 1 | capi 2 | gcp 3 | gce 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .github 3 | .vscode 4 | bin/ 5 | config/ 6 | hack/ 7 | docs/ 8 | templates/ 9 | scripts/ 10 | **/.md 11 | tilt-provider.json 12 | _artifacts/ 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Tell us about a problem you are experiencing 4 | 5 | --- 6 | 7 | /kind bug 8 | 9 | **What steps did you take and what happened:** 10 | [A clear and concise description of what the bug is.] 11 | 12 | 13 | **What did you expect to happen:** 14 | 15 | 16 | **Anything else you would like to add:** 17 | [Miscellaneous information that will assist in solving the issue.] 18 | 19 | 20 | **Environment:** 21 | 22 | - Cluster-api version: 23 | - Minikube/KIND version: 24 | - Kubernetes version: (use `kubectl version`): 25 | - OS (e.g. from `/etc/os-release`): 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature enhancement request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | /kind feature 8 | 9 | **Describe the solution you'd like** 10 | [A clear and concise description of what you want to happen.] 11 | 12 | 13 | **Anything else you would like to add:** 14 | [Miscellaneous information that will assist in solving the issue.] 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | **What type of PR is this?** 5 | 6 | 19 | 20 | **What this PR does / why we need it**: 21 | 22 | **Which issue(s) this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close the issue(s) when PR gets merged)*: 23 | Fixes # 24 | 25 | **Special notes for your reviewer**: 26 | 27 | _Please confirm that if this PR changes any image versions, then that's the sole change this PR makes._ 28 | 29 | **TODOs**: 30 | 31 | 32 | - [ ] squashed commits 33 | - [ ] includes documentation 34 | - [ ] adds unit tests 35 | 36 | **Release note**: 37 | 41 | ```release-note 42 | 43 | ``` 44 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: gomod 5 | directory: "/" 6 | schedule: 7 | interval: weekly 8 | labels: 9 | - "area/dependency" 10 | - "release-note-none" 11 | - "ok-to-test" 12 | open-pull-requests-limit: 10 13 | ignore: 14 | # Ignore controller-runtime as its upgraded manually. 15 | - dependency-name: "sigs.k8s.io/controller-runtime" 16 | # Ignore sigs.k8s.io/cluster-api as its upgraded manually. 17 | - dependency-name: "sigs.k8s.io/cluster-api/*" 18 | # Ignore k8s and its transitives modules as they are upgraded manually 19 | # together with controller-runtime. 20 | - dependency-name: "k8s.io/*" 21 | groups: 22 | all: 23 | update-types: 24 | - "minor" 25 | - "patch" 26 | 27 | - package-ecosystem: "github-actions" 28 | directory: "/" 29 | schedule: 30 | interval: daily 31 | open-pull-requests-limit: 10 32 | labels: 33 | - "area/dependency" 34 | - "release-note-none" 35 | - "ok-to-test" 36 | groups: 37 | all: 38 | update-types: 39 | - "minor" 40 | - "patch" 41 | -------------------------------------------------------------------------------- /.github/workflows/codespell.yml: -------------------------------------------------------------------------------- 1 | # Helps catch spelling errors 2 | name: Codespell 3 | 4 | on: 5 | pull_request: 6 | 7 | permissions: {} 8 | 9 | jobs: 10 | codespell: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | 15 | - uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2.1 16 | with: 17 | skip: .git,_artifacts,*.sum,.golangci.yml 18 | ignore_words_file: .codespellignore 19 | check_filenames: true 20 | check_hidden: true 21 | -------------------------------------------------------------------------------- /.github/workflows/link-check.yml: -------------------------------------------------------------------------------- 1 | # Check for broken links 2 | name: Link-check 3 | 4 | on: 5 | push: 6 | paths: 7 | - "docs/**" 8 | branches: 9 | - main 10 | pull_request: 11 | paths: "docs/**" 12 | 13 | permissions: {} 14 | 15 | jobs: 16 | lint_docs: 17 | name: Broken Links 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 22 | 23 | - uses: gaurav-nelson/github-action-markdown-link-check@3c3b66f1f7d0900e37b71eca45b63ea9eedfce31 # v1.0.17 24 | with: 25 | use-quiet-mode: 'yes' 26 | config-file: ".markdownlinkcheck.json" 27 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: {} 7 | 8 | jobs: 9 | golangci: 10 | name: lint 11 | runs-on: ubuntu-latest 12 | 13 | permissions: 14 | contents: read 15 | 16 | steps: 17 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 18 | 19 | - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 20 | with: 21 | go-version: "1.23" 22 | check-latest: true 23 | cache: false 24 | 25 | - name: golangci-lint 26 | uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 27 | with: 28 | version: v1.63 29 | -------------------------------------------------------------------------------- /.github/workflows/pr-gh-workflow-approve.yaml: -------------------------------------------------------------------------------- 1 | name: PR approve GH Workflows 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - edited 7 | - labeled 8 | - reopened 9 | - synchronize 10 | 11 | jobs: 12 | approve: 13 | name: Approve ok-to-test 14 | 15 | if: contains(github.event.pull_request.labels.*.name, 'ok-to-test') 16 | 17 | runs-on: ubuntu-latest 18 | 19 | permissions: 20 | actions: write 21 | 22 | steps: 23 | - name: Update PR 24 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 25 | continue-on-error: true 26 | with: 27 | github-token: ${{ secrets.GITHUB_TOKEN }} 28 | script: | 29 | const result = await github.rest.actions.listWorkflowRunsForRepo({ 30 | owner: context.repo.owner, 31 | repo: context.repo.repo, 32 | event: "pull_request", 33 | status: "action_required", 34 | head_sha: context.payload.pull_request.head.sha, 35 | per_page: 100 36 | }); 37 | 38 | for (var run of result.data.workflow_runs) { 39 | await github.rest.actions.approveWorkflowRun({ 40 | owner: context.repo.owner, 41 | repo: context.repo.repo, 42 | run_id: run.id 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | bin 8 | cluster-api-provider-gcp 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | _artifacts/ 13 | test/e2e/config/gcp-ci-envsubst.yaml 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | coverage.* 18 | !**/coverage.go 19 | 20 | # Ansible 21 | *.retry 22 | 23 | # vim 24 | *~ 25 | *.swp 26 | 27 | # envfiles 28 | .env 29 | envfile 30 | 31 | # kubeconfigs 32 | kind.kubeconfig 33 | minikube.kubeconfig 34 | kubeconfig 35 | # keep directories named kubeconfig 36 | !**/kubeconfig/ 37 | 38 | # Example and binary output directory 39 | /out 40 | 41 | # vscode 42 | .vscode 43 | 44 | # goland 45 | .idea 46 | 47 | # Ignore output manifests 48 | config/samples 49 | manager_image_patch.yaml-e 50 | manager_pull_policy.yaml-e 51 | 52 | # junit files 53 | junit.*.xml 54 | 55 | .DS_Store 56 | 57 | # Tilt files. 58 | .tiltbuild 59 | /tilt.d 60 | tilt-settings.json 61 | tilt_config.json 62 | -------------------------------------------------------------------------------- /.markdownlinkcheck.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [{ 3 | "pattern": "^https://calendar.google.com/calendar" 4 | }], 5 | "timeout": "5s", 6 | "retryOn429": true, 7 | "retryCount": 5, 8 | "fallbackRetryDelay": "30s", 9 | "aliveStatusCodes": [200, 206] 10 | } 11 | 12 | { 13 | "httpHeaders": [ 14 | { 15 | "urls": [ 16 | "https://docs.github.com/" 17 | ], 18 | "headers": { 19 | "Accept-Encoding": "zstd, br, gzip, deflate" 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Build the manager binary 16 | FROM golang:1.23.7@sha256:7fb9682dbc6c9743cd911cedb39c84790e8dfeaaf87d229b78f3f6658fce507a as builder 17 | WORKDIR /workspace 18 | 19 | # Run this with docker build --build_arg $(go env GOPROXY) to override the goproxy 20 | ARG goproxy=https://proxy.golang.org 21 | ENV GOPROXY=$goproxy 22 | 23 | # Copy the Go Modules manifests 24 | COPY go.mod go.mod 25 | COPY go.sum go.sum 26 | # Cache deps before building and copying source so that we don't need to re-download as much 27 | # and so that source changes don't invalidate our downloaded layer 28 | RUN go mod download 29 | 30 | # Copy the sources 31 | COPY ./ ./ 32 | 33 | # Build 34 | ARG ARCH 35 | ARG LDFLAGS 36 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} \ 37 | go build -a -trimpath -ldflags "${LDFLAGS} -extldflags '-static'" \ 38 | -o manager . 39 | 40 | # Copy the controller-manager into a thin image 41 | FROM cgr.dev/chainguard/static:latest 42 | WORKDIR / 43 | COPY --from=builder /workspace/manager . 44 | USER nobody 45 | ENTRYPOINT ["/manager"] 46 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md 2 | 3 | approvers: 4 | - sig-cluster-lifecycle-leads 5 | - cluster-api-admins 6 | - cluster-api-maintainers 7 | - cluster-api-gcp-maintainers 8 | 9 | reviewers: 10 | - cluster-api-gcp-maintainers 11 | - cluster-api-gcp-reviewers 12 | 13 | emeritus_approvers: 14 | - detiber 15 | - gab-satchi 16 | - justinsb 17 | - krousey 18 | - roberthbailey 19 | - rsmitty 20 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs: https://git.k8s.io/community/docs/devel/owners.md 2 | 3 | aliases: 4 | sig-cluster-lifecycle-leads: 5 | - fabriziopandini 6 | - justinsb 7 | - neolit123 8 | - vincepri 9 | 10 | cluster-api-admins: 11 | - fabriziopandini 12 | - sbueringer 13 | - vincepri 14 | 15 | cluster-api-maintainers: 16 | - chrischdi 17 | - enxebre 18 | - fabriziopandini 19 | - sbueringer 20 | - vincepri 21 | 22 | cluster-api-gcp-maintainers: 23 | - cpanato 24 | - damdo 25 | - dims 26 | - richardcase 27 | - salasberryfin 28 | 29 | cluster-api-gcp-reviewers: 30 | 31 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | version: "3" 2 | domain: cluster.x-k8s.io 3 | repo: sigs.k8s.io/cluster-api-provider-gcp 4 | resources: 5 | # v1alpha3 types 6 | - group: infrastructure 7 | version: v1alpha3 8 | kind: GCPMachine 9 | - group: infrastructure 10 | version: v1alpha3 11 | kind: GCPCluster 12 | - group: infrastructure 13 | version: v1alpha3 14 | kind: GCPMachineTemplate 15 | # v1alpha4 types 16 | - group: infrastructure 17 | version: v1alpha4 18 | kind: GCPMachine 19 | - group: infrastructure 20 | version: v1alpha4 21 | kind: GCPCluster 22 | - group: infrastructure 23 | version: v1alpha4 24 | kind: GCPMachineTemplate 25 | - group: infrastructure 26 | version: v1alpha4 27 | kind: GCPClusterTemplate 28 | # v1beta1 types 29 | - group: infrastructure 30 | version: v1beta1 31 | kind: GCPMachine 32 | - group: infrastructure 33 | version: v1beta1 34 | kind: GCPCluster 35 | - group: infrastructure 36 | version: v1beta1 37 | kind: GCPMachineTemplate 38 | - group: infrastructure 39 | version: v1beta1 40 | kind: GCPClusterTemplate 41 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Team to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | justinsb 14 | luxas 15 | timothysc 16 | -------------------------------------------------------------------------------- /api/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | -------------------------------------------------------------------------------- /api/v1beta1/endpoints.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // ServiceEndpoints contains all the gcp service endpoints that the user may override. Each field corresponds to 20 | // a service where the expected value is the url that is used to override the default API endpoint. 21 | type ServiceEndpoints struct { 22 | // ComputeServiceEndpoint is the custom endpoint url for the Compute Service 23 | // +kubebuilder:validation:Type=string 24 | // +kubebuilder:validation:Format=uri 25 | // +kubebuilder:validation:Pattern=`^https://` 26 | // +optional 27 | ComputeServiceEndpoint string `json:"compute,omitempty"` 28 | 29 | // ContainerServiceEndpoint is the custom endpoint url for the Container Service 30 | // +kubebuilder:validation:Type=string 31 | // +kubebuilder:validation:Format=uri 32 | // +kubebuilder:validation:Pattern=`^https://` 33 | // +optional 34 | ContainerServiceEndpoint string `json:"container,omitempty"` 35 | 36 | // IAMServiceEndpoint is the custom endpoint url for the IAM Service 37 | // +kubebuilder:validation:Type=string 38 | // +kubebuilder:validation:Format=uri 39 | // +kubebuilder:validation:Pattern=`^https://` 40 | // +optional 41 | IAMServiceEndpoint string `json:"iam,omitempty"` 42 | 43 | // ResourceManagerServiceEndpoint is the custom endpoint url for the Resource Manager Service 44 | // +kubebuilder:validation:Type=string 45 | // +kubebuilder:validation:Format=uri 46 | // +kubebuilder:validation:Pattern=`^https://` 47 | // +optional 48 | ResourceManagerServiceEndpoint string `json:"resourceManager,omitempty"` 49 | } 50 | -------------------------------------------------------------------------------- /api/v1beta1/gcpcluster_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // Hub marks GCPCluster as a conversion hub. 20 | func (*GCPCluster) Hub() {} 21 | 22 | // Hub marks GCPClusterList as a conversion hub. 23 | func (*GCPClusterList) Hub() {} 24 | -------------------------------------------------------------------------------- /api/v1beta1/gcpcluster_webhook_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestGCPCluster_ValidateUpdate(t *testing.T) { 27 | g := NewWithT(t) 28 | 29 | tests := []struct { 30 | name string 31 | newCluster *GCPCluster 32 | oldCluster *GCPCluster 33 | wantErr bool 34 | }{ 35 | { 36 | name: "GCPCluster with MTU field is within the limits of more than 1300 and less than 8896", 37 | newCluster: &GCPCluster{ 38 | Spec: GCPClusterSpec{ 39 | Network: NetworkSpec{ 40 | Mtu: int64(1500), 41 | }, 42 | }, 43 | }, 44 | oldCluster: &GCPCluster{ 45 | Spec: GCPClusterSpec{ 46 | Network: NetworkSpec{ 47 | Mtu: int64(1400), 48 | }, 49 | }, 50 | }, 51 | wantErr: false, 52 | }, 53 | { 54 | name: "GCPCluster with MTU field more than 8896", 55 | newCluster: &GCPCluster{ 56 | Spec: GCPClusterSpec{ 57 | Network: NetworkSpec{ 58 | Mtu: int64(10000), 59 | }, 60 | }, 61 | }, 62 | oldCluster: &GCPCluster{ 63 | Spec: GCPClusterSpec{ 64 | Network: NetworkSpec{ 65 | Mtu: int64(1500), 66 | }, 67 | }, 68 | }, 69 | wantErr: true, 70 | }, 71 | { 72 | name: "GCPCluster with MTU field less than 8896", 73 | newCluster: &GCPCluster{ 74 | Spec: GCPClusterSpec{ 75 | Network: NetworkSpec{ 76 | Mtu: int64(1250), 77 | }, 78 | }, 79 | }, 80 | oldCluster: &GCPCluster{ 81 | Spec: GCPClusterSpec{ 82 | Network: NetworkSpec{ 83 | Mtu: int64(1500), 84 | }, 85 | }, 86 | }, 87 | wantErr: true, 88 | }, 89 | } 90 | for _, test := range tests { 91 | t.Run(test.name, func(t *testing.T) { 92 | t.Parallel() 93 | warn, err := (&gcpClusterWebhook{}).ValidateUpdate(context.Background(), test.oldCluster, test.newCluster) 94 | if test.wantErr { 95 | g.Expect(err).To(HaveOccurred()) 96 | } else { 97 | g.Expect(err).NotTo(HaveOccurred()) 98 | } 99 | g.Expect(warn).To(BeNil()) 100 | }) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /api/v1beta1/gcpclustertemplate_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // Hub marks GCPClusterTemplate as a conversion hub. 20 | func (*GCPClusterTemplate) Hub() {} 21 | 22 | // Hub marks GCPClusterTemplateList as a conversion hub. 23 | func (*GCPClusterTemplateList) Hub() {} 24 | -------------------------------------------------------------------------------- /api/v1beta1/gcpclustertemplate_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 22 | ) 23 | 24 | // GCPClusterTemplateSpec defines the desired state of GCPClusterTemplate. 25 | type GCPClusterTemplateSpec struct { 26 | Template GCPClusterTemplateResource `json:"template"` 27 | } 28 | 29 | // GCPClusterTemplateResource contains spec for GCPClusterSpec. 30 | type GCPClusterTemplateResource struct { 31 | // Standard object's metadata. 32 | // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 33 | // +optional 34 | ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` 35 | 36 | Spec GCPClusterSpec `json:"spec"` 37 | } 38 | 39 | // +kubebuilder:object:root=true 40 | // +kubebuilder:resource:path=gcpclustertemplates,scope=Namespaced,categories=cluster-api,shortName=gcpct 41 | // +kubebuilder:storageversion 42 | 43 | // GCPClusterTemplate is the Schema for the gcpclustertemplates API. 44 | type GCPClusterTemplate struct { 45 | metav1.TypeMeta `json:",inline"` 46 | metav1.ObjectMeta `json:"metadata,omitempty"` 47 | 48 | Spec GCPClusterTemplateSpec `json:"spec,omitempty"` 49 | } 50 | 51 | //+kubebuilder:object:root=true 52 | 53 | // GCPClusterTemplateList contains a list of GCPClusterTemplate. 54 | type GCPClusterTemplateList struct { 55 | metav1.TypeMeta `json:",inline"` 56 | metav1.ListMeta `json:"metadata,omitempty"` 57 | Items []GCPClusterTemplate `json:"items"` 58 | } 59 | 60 | func init() { 61 | SchemeBuilder.Register(&GCPClusterTemplate{}, &GCPClusterTemplateList{}) 62 | } 63 | -------------------------------------------------------------------------------- /api/v1beta1/gcpclustertemplate_webhook_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestGCPClusterTemplate_ValidateUpdate(t *testing.T) { 27 | g := NewWithT(t) 28 | 29 | tests := []struct { 30 | name string 31 | newTemplate *GCPClusterTemplate 32 | oldTemplate *GCPClusterTemplate 33 | wantErr bool 34 | }{ 35 | { 36 | name: "GCPClusterTemplated with immutable spec", 37 | newTemplate: &GCPClusterTemplate{ 38 | Spec: GCPClusterTemplateSpec{ 39 | Template: GCPClusterTemplateResource{ 40 | Spec: GCPClusterSpec{ 41 | Project: "test-gcp-cluster", 42 | Region: "ap-south-1", 43 | }, 44 | }, 45 | }, 46 | }, 47 | oldTemplate: &GCPClusterTemplate{ 48 | Spec: GCPClusterTemplateSpec{ 49 | Template: GCPClusterTemplateResource{ 50 | Spec: GCPClusterSpec{ 51 | Project: "test-gcp-cluster", 52 | Region: "ap-south-1", 53 | }, 54 | }, 55 | }, 56 | }, 57 | wantErr: false, 58 | }, 59 | { 60 | name: "GCPClusterTemplated with mutable spec", 61 | newTemplate: &GCPClusterTemplate{ 62 | Spec: GCPClusterTemplateSpec{ 63 | Template: GCPClusterTemplateResource{ 64 | Spec: GCPClusterSpec{ 65 | Project: "test-gcp-cluster", 66 | Region: "ap-south-1", 67 | }, 68 | }, 69 | }, 70 | }, 71 | oldTemplate: &GCPClusterTemplate{ 72 | Spec: GCPClusterTemplateSpec{ 73 | Template: GCPClusterTemplateResource{ 74 | Spec: GCPClusterSpec{ 75 | Project: "test-gcp-cluster", 76 | Region: "ap-east-1", 77 | }, 78 | }, 79 | }, 80 | }, 81 | wantErr: true, 82 | }, 83 | } 84 | for _, test := range tests { 85 | t.Run(test.name, func(t *testing.T) { 86 | t.Parallel() 87 | warn, err := (&gcpClusterTemplateWebhook{}).ValidateUpdate(context.Background(), test.oldTemplate, test.newTemplate) 88 | if test.wantErr { 89 | g.Expect(err).To(HaveOccurred()) 90 | } else { 91 | g.Expect(err).NotTo(HaveOccurred()) 92 | } 93 | g.Expect(warn).To(BeNil()) 94 | }) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /api/v1beta1/gcpmachine_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // Hub marks GCPMachine as a conversion hub. 20 | func (*GCPMachine) Hub() {} 21 | 22 | // Hub marks GCPMachineList as a conversion hub. 23 | func (*GCPMachineList) Hub() {} 24 | -------------------------------------------------------------------------------- /api/v1beta1/gcpmachinetemplate_conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // Hub marks GCPMachineTemplate as a conversion hub. 20 | func (*GCPMachineTemplate) Hub() {} 21 | 22 | // Hub marks GCPMachineTemplateList as a conversion hub. 23 | func (*GCPMachineTemplateList) Hub() {} 24 | -------------------------------------------------------------------------------- /api/v1beta1/gcpmachinetemplate_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // GCPMachineTemplateSpec defines the desired state of GCPMachineTemplate. 24 | type GCPMachineTemplateSpec struct { 25 | Template GCPMachineTemplateResource `json:"template"` 26 | } 27 | 28 | // +kubebuilder:object:root=true 29 | // +kubebuilder:resource:path=gcpmachinetemplates,scope=Namespaced,categories=cluster-api 30 | // +kubebuilder:storageversion 31 | 32 | // GCPMachineTemplate is the Schema for the gcpmachinetemplates API. 33 | type GCPMachineTemplate struct { 34 | metav1.TypeMeta `json:",inline"` 35 | metav1.ObjectMeta `json:"metadata,omitempty"` 36 | 37 | Spec GCPMachineTemplateSpec `json:"spec,omitempty"` 38 | } 39 | 40 | // +kubebuilder:object:root=true 41 | 42 | // GCPMachineTemplateList contains a list of GCPMachineTemplate. 43 | type GCPMachineTemplateList struct { 44 | metav1.TypeMeta `json:",inline"` 45 | metav1.ListMeta `json:"metadata,omitempty"` 46 | Items []GCPMachineTemplate `json:"items"` 47 | } 48 | 49 | func init() { 50 | SchemeBuilder.Register(&GCPMachineTemplate{}, &GCPMachineTemplateList{}) 51 | } 52 | -------------------------------------------------------------------------------- /api/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=infrastructure.cluster.x-k8s.io 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects. 29 | GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/v1beta1/tags.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | // ResourceManagerTags is an slice of ResourceManagerTag structs. 20 | type ResourceManagerTags []ResourceManagerTag 21 | 22 | // ResourceManagerTagsMap defines a map of key value pairs as expected by compute.InstanceParams.ResourceManagerTags. 23 | type ResourceManagerTagsMap map[string]string 24 | 25 | // ResourceManagerTag is a tag to apply to GCP resources managed by the GCP provider. 26 | type ResourceManagerTag struct { 27 | // ParentID is the ID of the hierarchical resource where the tags are defined 28 | // e.g. at the Organization or the Project level. To find the Organization or Project ID ref 29 | // https://cloud.google.com/resource-manager/docs/creating-managing-organization#retrieving_your_organization_id 30 | // https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects 31 | // An OrganizationID must consist of decimal numbers, and cannot have leading zeroes. 32 | // A ProjectID must be 6 to 30 characters in length, can only contain lowercase letters, 33 | // numbers, and hyphens, and must start with a letter, and cannot end with a hyphen. 34 | // +kubebuilder:validation:Required 35 | // +kubebuilder:validation:MinLength=1 36 | // +kubebuilder:validation:MaxLength=32 37 | // +kubebuilder:validation:Pattern=`(^[1-9][0-9]{0,31}$)|(^[a-z][a-z0-9-]{4,28}[a-z0-9]$)` 38 | ParentID string `json:"parentID"` 39 | 40 | // Key is the key part of the tag. A tag key can have a maximum of 63 characters and cannot 41 | // be empty. Tag key must begin and end with an alphanumeric character, and must contain 42 | // only uppercase, lowercase alphanumeric characters, and the following special 43 | // characters `._-`. 44 | // +kubebuilder:validation:Required 45 | // +kubebuilder:validation:MinLength=1 46 | // +kubebuilder:validation:MaxLength=63 47 | // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([0-9A-Za-z_.-]{0,61}[a-zA-Z0-9])?$` 48 | Key string `json:"key"` 49 | 50 | // Value is the value part of the tag. A tag value can have a maximum of 63 characters and 51 | // cannot be empty. Tag value must begin and end with an alphanumeric character, and must 52 | // contain only uppercase, lowercase alphanumeric characters, and the following special 53 | // characters `_-.@%=+:,*#&(){}[]` and spaces. 54 | // +kubebuilder:validation:Required 55 | // +kubebuilder:validation:MinLength=1 56 | // +kubebuilder:validation:MaxLength=63 57 | // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([0-9A-Za-z_.@%=+:,*#&()\[\]{}\-\s]{0,61}[a-zA-Z0-9])?$` 58 | Value string `json:"value"` 59 | } 60 | 61 | // Merge merges resource manager tags in receiver and other. 62 | func (t *ResourceManagerTags) Merge(other ResourceManagerTags) { 63 | *t = append(*t, other...) 64 | } 65 | -------------------------------------------------------------------------------- /cloud/defaults.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package cloud 15 | 16 | const ( 17 | // DefaultNumRegionsPerZone is the default number of zones per region. 18 | DefaultNumRegionsPerZone = 3 19 | ) 20 | -------------------------------------------------------------------------------- /cloud/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package cloud implement cloud resources lifecycle. 18 | package cloud 19 | -------------------------------------------------------------------------------- /cloud/gcperrors/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package gcperrors implements gcp errors types. 18 | package gcperrors 19 | 20 | import ( 21 | "net/http" 22 | 23 | "google.golang.org/api/googleapi" 24 | ) 25 | 26 | // IsNotFound reports whether err is a Google API error 27 | // with http.StatusNotFround. 28 | func IsNotFound(err error) bool { 29 | if err == nil { 30 | return false 31 | } 32 | ae, ok := err.(*googleapi.Error) 33 | 34 | return ok && ae.Code == http.StatusNotFound 35 | } 36 | 37 | // IgnoreNotFound ignore Google API not found error and return nil. 38 | // Otherwise return the actual error. 39 | func IgnoreNotFound(err error) error { 40 | if IsNotFound(err) { 41 | return nil 42 | } 43 | 44 | return err 45 | } 46 | -------------------------------------------------------------------------------- /cloud/providerid/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package providerid implements functionality for creating kubernetes provider ids for nodes. 18 | package providerid 19 | -------------------------------------------------------------------------------- /cloud/providerid/providerid.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package providerid 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "path" 23 | 24 | "sigs.k8s.io/cluster-api-provider-gcp/util/resourceurl" 25 | ) 26 | 27 | const ( 28 | // Prefix is the gce provider id prefix. 29 | Prefix = "gce://" 30 | ) 31 | 32 | // ProviderID represents the id for a GCP cluster. 33 | type ProviderID interface { 34 | Project() string 35 | Location() string 36 | Name() string 37 | fmt.Stringer 38 | } 39 | 40 | // NewFromResourceURL creates a provider from a GCP resource url. 41 | func NewFromResourceURL(url string) (ProviderID, error) { 42 | resourceURL, err := resourceurl.Parse(url) 43 | if err != nil { 44 | return nil, fmt.Errorf("parsing resource url %s: %w", url, err) 45 | } 46 | 47 | return New(resourceURL.Project, resourceURL.Location, resourceURL.Name) 48 | } 49 | 50 | // New creates a new provider id. 51 | func New(project, location, name string) (ProviderID, error) { 52 | if project == "" { 53 | return nil, errors.New("project required for provider id") 54 | } 55 | if location == "" { 56 | return nil, errors.New("location required for provider id") 57 | } 58 | if name == "" { 59 | return nil, errors.New("name required for provider id") 60 | } 61 | 62 | return &providerID{ 63 | project: project, 64 | location: location, 65 | name: name, 66 | }, nil 67 | } 68 | 69 | type providerID struct { 70 | project string 71 | location string 72 | name string 73 | } 74 | 75 | func (p *providerID) Project() string { 76 | return p.project 77 | } 78 | 79 | func (p *providerID) Location() string { 80 | return p.location 81 | } 82 | 83 | func (p *providerID) Name() string { 84 | return p.name 85 | } 86 | 87 | func (p *providerID) String() string { 88 | return Prefix + path.Join(p.project, p.location, p.name) 89 | } 90 | -------------------------------------------------------------------------------- /cloud/scope/getters.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scope 18 | 19 | // ClusterScopeGetter is a Service which knows how to retrieve the scope for a cluster. 20 | type ClusterScopeGetter interface { 21 | ClusterScope(params ClusterScopeParams) (*ClusterScope, error) 22 | } 23 | 24 | // ClusterScopeGetterFunc ... 25 | type ClusterScopeGetterFunc func(params ClusterScopeParams) (*ClusterScope, error) 26 | 27 | // ClusterScope returns the cluster scope. 28 | func (f ClusterScopeGetterFunc) ClusterScope(params ClusterScopeParams) (*ClusterScope, error) { 29 | return f(params) 30 | } 31 | 32 | // MachineScopeGetter ... 33 | type MachineScopeGetter interface { 34 | MachineScope(params MachineScopeParams) (*MachineScope, error) 35 | } 36 | 37 | // MachineScopeGetterFunc ... 38 | type MachineScopeGetterFunc func(params MachineScopeParams) (*MachineScope, error) 39 | 40 | // MachineScope returns the machine scope. 41 | func (f MachineScopeGetterFunc) MachineScope(params MachineScopeParams) (*MachineScope, error) { 42 | return f(params) 43 | } 44 | -------------------------------------------------------------------------------- /cloud/scope/machine_test.go: -------------------------------------------------------------------------------- 1 | package scope 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" 8 | clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 9 | "sigs.k8s.io/controller-runtime/pkg/client/fake" 10 | ) 11 | 12 | // This test verifies that if a user selects "local-ssd" 13 | // as a disk type then the MachineScope correctly detects it as such. 14 | func TestMachineLocalSSDDiskType(t *testing.T) { 15 | // Register the GCPMachine and GCPMachineList in a schema. 16 | schema, err := infrav1.SchemeBuilder.Register(&infrav1.GCPMachine{}, &infrav1.GCPMachineList{}).Build() 17 | 18 | // Make sure no errors were triggered. 19 | assert.Nil(t, err) 20 | 21 | // Create a controller fake client. 22 | // It's best to use envtest but in this case we are not really using the client 23 | // just passing it as parameter to the NewMachineScope to test the dik functionality. 24 | testClient := fake.NewClientBuilder().WithScheme(schema).Build() 25 | 26 | // New test machine, needed as parameter. 27 | failureDomain := "example.com" 28 | testMachine := clusterv1.Machine{ 29 | Spec: clusterv1.MachineSpec{ 30 | FailureDomain: &failureDomain, 31 | }, 32 | } 33 | 34 | // GCPMachine for mocking the disks. 35 | // Set the disk to local-ssd. 36 | diskType := infrav1.LocalSsdDiskType 37 | diskSize := int64(100) 38 | 39 | testGCPMachine := infrav1.GCPMachine{ 40 | Spec: infrav1.GCPMachineSpec{ 41 | AdditionalDisks: []infrav1.AttachedDiskSpec{ 42 | { 43 | DeviceType: &diskType, 44 | Size: &diskSize, 45 | }, 46 | }, 47 | }, 48 | } 49 | 50 | // Finally put together the parameters. 51 | testScopeParams := MachineScopeParams{ 52 | Client: testClient, 53 | Machine: &testMachine, 54 | GCPMachine: &testGCPMachine, 55 | } 56 | 57 | // Create the scope 58 | testMachineScope, err := NewMachineScope(testScopeParams) 59 | 60 | // Make sure the machine scope is create correctly. 61 | assert.Nil(t, err) 62 | assert.NotNil(t, testMachineScope) 63 | 64 | // Now make sure the local-ssd disk type is detected as SCRATCH. 65 | diskSpec := testMachineScope.InstanceAdditionalDiskSpec() 66 | assert.NotEmpty(t, diskSpec) 67 | 68 | // Get the local-ssd disk now. 69 | localSSDTest := diskSpec[0] 70 | assert.True(t, localSSDTest.AutoDelete) 71 | assert.Equal(t, "SCRATCH", localSSDTest.Type) 72 | assert.Equal(t, "NVME", localSSDTest.Interface) 73 | assert.Equal(t, int64(375), localSSDTest.InitializeParams.DiskSizeGb) 74 | } 75 | -------------------------------------------------------------------------------- /cloud/scope/scope_suite_test.go: -------------------------------------------------------------------------------- 1 | package scope_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo/v2" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestScope(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Scope Suite") 13 | } 14 | -------------------------------------------------------------------------------- /cloud/services/compute/firewalls/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package firewalls implements reconciler for cluster firwall components. 18 | package firewalls 19 | -------------------------------------------------------------------------------- /cloud/services/compute/firewalls/reconcile.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package firewalls 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" 23 | 24 | "sigs.k8s.io/cluster-api-provider-gcp/cloud/gcperrors" 25 | "sigs.k8s.io/controller-runtime/pkg/log" 26 | ) 27 | 28 | // Reconcile reconcile cluster firewall compoenents. 29 | func (s *Service) Reconcile(ctx context.Context) error { 30 | log := log.FromContext(ctx) 31 | if s.scope.IsSharedVpc() { 32 | log.V(2).Info("Shared VPC enabled. Ignore Reconciling firewall resources") 33 | return nil 34 | } 35 | log.Info("Reconciling firewall resources") 36 | for _, spec := range s.scope.FirewallRulesSpec() { 37 | log.V(2).Info("Looking firewall", "name", spec.Name) 38 | firewallKey := meta.GlobalKey(spec.Name) 39 | if _, err := s.firewalls.Get(ctx, firewallKey); err != nil { 40 | if !gcperrors.IsNotFound(err) { 41 | return err 42 | } 43 | 44 | log.V(2).Info("Creating firewall", "name", spec.Name) 45 | if err := s.firewalls.Insert(ctx, firewallKey, spec); err != nil { 46 | return err 47 | } 48 | } 49 | } 50 | 51 | return nil 52 | } 53 | 54 | // Delete delete cluster firewall compoenents. 55 | func (s *Service) Delete(ctx context.Context) error { 56 | log := log.FromContext(ctx) 57 | if s.scope.IsSharedVpc() { 58 | log.V(2).Info("Shared VPC enabled. Ignore Deleting firewall resources") 59 | return nil 60 | } 61 | log.Info("Deleting firewall resources") 62 | for _, spec := range s.scope.FirewallRulesSpec() { 63 | log.V(2).Info("Deleting firewall", "name", spec.Name) 64 | firewallKey := meta.GlobalKey(spec.Name) 65 | if err := s.firewalls.Delete(ctx, firewallKey); err != nil { 66 | if !gcperrors.IsNotFound(err) { 67 | log.Error(err, "Error deleting firewall", "name", spec.Name) 68 | return err 69 | } 70 | } 71 | } 72 | 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /cloud/services/compute/firewalls/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package firewalls 18 | 19 | import ( 20 | "context" 21 | 22 | k8scloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" 23 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" 24 | "google.golang.org/api/compute/v1" 25 | 26 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 27 | ) 28 | 29 | type firewallsInterface interface { 30 | Get(ctx context.Context, key *meta.Key, options ...k8scloud.Option) (*compute.Firewall, error) 31 | Insert(ctx context.Context, key *meta.Key, obj *compute.Firewall, options ...k8scloud.Option) error 32 | Update(ctx context.Context, key *meta.Key, obj *compute.Firewall, options ...k8scloud.Option) error 33 | Delete(ctx context.Context, key *meta.Key, options ...k8scloud.Option) error 34 | } 35 | 36 | // Scope is an interfaces that hold used methods. 37 | type Scope interface { 38 | cloud.ClusterGetter 39 | FirewallRulesSpec() []*compute.Firewall 40 | } 41 | 42 | // Service implements firewalls reconciler. 43 | type Service struct { 44 | scope Scope 45 | firewalls firewallsInterface 46 | } 47 | 48 | var _ cloud.Reconciler = &Service{} 49 | 50 | // New returns Service from given scope. 51 | func New(scope Scope) *Service { 52 | return &Service{ 53 | scope: scope, 54 | firewalls: scope.Cloud().Firewalls(), 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cloud/services/compute/instances/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package instances implements reconciler for machine instance components. 18 | package instances 19 | -------------------------------------------------------------------------------- /cloud/services/compute/instances/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package instances 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-logr/logr" 23 | 24 | k8scloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" 25 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/filter" 26 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" 27 | "google.golang.org/api/compute/v1" 28 | 29 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 30 | ) 31 | 32 | type instancesInterface interface { 33 | Get(ctx context.Context, key *meta.Key, options ...k8scloud.Option) (*compute.Instance, error) 34 | Insert(ctx context.Context, key *meta.Key, obj *compute.Instance, options ...k8scloud.Option) error 35 | Delete(ctx context.Context, key *meta.Key, options ...k8scloud.Option) error 36 | } 37 | 38 | type instancegroupsInterface interface { 39 | AddInstances(ctx context.Context, key *meta.Key, req *compute.InstanceGroupsAddInstancesRequest, options ...k8scloud.Option) error 40 | ListInstances(ctx context.Context, key *meta.Key, req *compute.InstanceGroupsListInstancesRequest, fl *filter.F, options ...k8scloud.Option) ([]*compute.InstanceWithNamedPorts, error) 41 | RemoveInstances(ctx context.Context, key *meta.Key, req *compute.InstanceGroupsRemoveInstancesRequest, options ...k8scloud.Option) error 42 | } 43 | 44 | // Scope is an interfaces that hold used methods. 45 | type Scope interface { 46 | cloud.Machine 47 | InstanceSpec(log logr.Logger) *compute.Instance 48 | InstanceImageSpec() *compute.AttachedDisk 49 | InstanceAdditionalDiskSpec() []*compute.AttachedDisk 50 | } 51 | 52 | // Service implements instances reconciler. 53 | type Service struct { 54 | scope Scope 55 | instances instancesInterface 56 | instancegroups instancegroupsInterface 57 | } 58 | 59 | var _ cloud.Reconciler = &Service{} 60 | 61 | // New returns Service from given scope. 62 | func New(scope Scope) *Service { 63 | return &Service{ 64 | scope: scope, 65 | instances: scope.Cloud().Instances(), 66 | instancegroups: scope.Cloud().InstanceGroups(), 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /cloud/services/compute/loadbalancers/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package loadbalancers implements reconciler for cluster control-plane loadbalancer components. 18 | package loadbalancers 19 | -------------------------------------------------------------------------------- /cloud/services/compute/networks/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package networks implements reconciler for cluster networking components. 18 | package networks 19 | -------------------------------------------------------------------------------- /cloud/services/compute/networks/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package networks 18 | 19 | import ( 20 | "context" 21 | 22 | k8scloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" 23 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" 24 | "google.golang.org/api/compute/v1" 25 | 26 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 27 | ) 28 | 29 | type networksInterface interface { 30 | Get(ctx context.Context, key *meta.Key, options ...k8scloud.Option) (*compute.Network, error) 31 | Insert(ctx context.Context, key *meta.Key, obj *compute.Network, options ...k8scloud.Option) error 32 | Delete(ctx context.Context, key *meta.Key, options ...k8scloud.Option) error 33 | } 34 | 35 | type routersInterface interface { 36 | Get(ctx context.Context, key *meta.Key, options ...k8scloud.Option) (*compute.Router, error) 37 | Insert(ctx context.Context, key *meta.Key, obj *compute.Router, options ...k8scloud.Option) error 38 | Delete(ctx context.Context, key *meta.Key, options ...k8scloud.Option) error 39 | } 40 | 41 | // Scope is an interfaces that hold used methods. 42 | type Scope interface { 43 | cloud.Cluster 44 | NetworkSpec() *compute.Network 45 | NatRouterSpec() *compute.Router 46 | } 47 | 48 | // Service implements networks reconciler. 49 | type Service struct { 50 | scope Scope 51 | networks networksInterface 52 | routers routersInterface 53 | } 54 | 55 | var _ cloud.Reconciler = &Service{} 56 | 57 | // New returns Service from given scope. 58 | func New(scope Scope) *Service { 59 | scopeCloud := scope.Cloud() 60 | if scope.IsSharedVpc() { 61 | scopeCloud = scope.NetworkCloud() 62 | } 63 | 64 | return &Service{ 65 | scope: scope, 66 | networks: scopeCloud.Networks(), 67 | routers: scopeCloud.Routers(), 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cloud/services/compute/subnets/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package subnets implements reconciler for subnetworks. 18 | package subnets 19 | -------------------------------------------------------------------------------- /cloud/services/compute/subnets/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package subnets 18 | 19 | import ( 20 | "context" 21 | 22 | k8scloud "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud" 23 | "github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta" 24 | "google.golang.org/api/compute/v1" 25 | 26 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 27 | ) 28 | 29 | type subnetsInterface interface { 30 | Get(ctx context.Context, key *meta.Key, options ...k8scloud.Option) (*compute.Subnetwork, error) 31 | Insert(ctx context.Context, key *meta.Key, obj *compute.Subnetwork, options ...k8scloud.Option) error 32 | Delete(ctx context.Context, key *meta.Key, options ...k8scloud.Option) error 33 | } 34 | 35 | // Scope is an interfaces that hold used methods. 36 | type Scope interface { 37 | cloud.Cluster 38 | SubnetSpecs() []*compute.Subnetwork 39 | } 40 | 41 | // Service implements subnets reconciler. 42 | type Service struct { 43 | scope Scope 44 | subnets subnetsInterface 45 | } 46 | 47 | var _ cloud.Reconciler = &Service{} 48 | 49 | // New returns Service from given scope. 50 | func New(scope Scope) *Service { 51 | cloudScope := scope.Cloud() 52 | if scope.IsSharedVpc() { 53 | cloudScope = scope.NetworkCloud() 54 | } 55 | 56 | return &Service{ 57 | scope: scope, 58 | subnets: cloudScope.Subnetworks(), 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cloud/services/container/clusters/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package clusters implements reconciler for GKE cluster components. 18 | package clusters 19 | -------------------------------------------------------------------------------- /cloud/services/container/clusters/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package clusters 18 | 19 | import ( 20 | "github.com/pkg/errors" 21 | ) 22 | 23 | // ErrAutopilotClusterMachinePoolsNotAllowed is used when there are machine pools specified for an autopilot enabled cluster. 24 | var ErrAutopilotClusterMachinePoolsNotAllowed = errors.New("cannot use machine pools with an autopilot enabled cluster") 25 | 26 | // NewErrUnexpectedClusterStatus creates a new error for an unexpected cluster status. 27 | func NewErrUnexpectedClusterStatus(status string) error { 28 | return &UnexpectedClusterStatusError{status} 29 | } 30 | 31 | // UnexpectedClusterStatusError is the error struct 32 | type UnexpectedClusterStatusError struct { 33 | status string 34 | } 35 | 36 | func (e *UnexpectedClusterStatusError) Error() string { 37 | return "unexpected error status: " + e.status 38 | } 39 | -------------------------------------------------------------------------------- /cloud/services/container/clusters/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package clusters 18 | 19 | import ( 20 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 21 | "sigs.k8s.io/cluster-api-provider-gcp/cloud/scope" 22 | ) 23 | 24 | // Service implements clusters reconciler. 25 | type Service struct { 26 | scope *scope.ManagedControlPlaneScope 27 | } 28 | 29 | var _ cloud.ReconcilerWithResult = &Service{} 30 | 31 | // New returns Service from given scope. 32 | func New(scope *scope.ManagedControlPlaneScope) *Service { 33 | return &Service{ 34 | scope: scope, 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cloud/services/container/nodepools/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package nodepools implements reconciler for GKE node pool components. 18 | package nodepools 19 | -------------------------------------------------------------------------------- /cloud/services/container/nodepools/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package nodepools 18 | 19 | import ( 20 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 21 | "sigs.k8s.io/cluster-api-provider-gcp/cloud/scope" 22 | ) 23 | 24 | // Service implements node pool reconciler. 25 | type Service struct { 26 | scope *scope.ManagedMachinePoolScope 27 | } 28 | 29 | var _ cloud.ReconcilerWithResult = &Service{} 30 | 31 | // New returns Service from given scope. 32 | func New(scope *scope.ManagedMachinePoolScope) *Service { 33 | return &Service{ 34 | scope: scope, 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cloud/services/shared/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package shared implements functionality that is shared across different services. 18 | package shared 19 | -------------------------------------------------------------------------------- /cloud/services/shared/machinepool.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package shared 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "strings" 23 | 24 | clusterv1exp "sigs.k8s.io/cluster-api/exp/api/v1beta1" 25 | 26 | "sigs.k8s.io/cluster-api-provider-gcp/cloud" 27 | infrav1exp "sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1" 28 | ) 29 | 30 | // ManagedMachinePoolPreflightCheck will perform checks against the machine pool before its created. 31 | func ManagedMachinePoolPreflightCheck(managedPool *infrav1exp.GCPManagedMachinePool, machinePool *clusterv1exp.MachinePool, location string) error { 32 | if machinePool.Spec.Template.Spec.InfrastructureRef.Name != managedPool.Name { 33 | return fmt.Errorf("expect machinepool infraref (%s) to match managed machine pool name (%s)", machinePool.Spec.Template.Spec.InfrastructureRef.Name, managedPool.Name) 34 | } 35 | 36 | if IsRegional(location) { 37 | var numRegionsPerZone int32 38 | if len(managedPool.Spec.NodeLocations) != 0 { 39 | numRegionsPerZone = int32(len(managedPool.Spec.NodeLocations)) 40 | } else { 41 | numRegionsPerZone = cloud.DefaultNumRegionsPerZone 42 | } 43 | if *machinePool.Spec.Replicas%numRegionsPerZone != 0 { 44 | return fmt.Errorf("a machine pool (%s) in a regional cluster with %d regions, must have replicas with a multiple of %d", machinePool.Name, numRegionsPerZone, numRegionsPerZone) 45 | } 46 | } 47 | 48 | return nil 49 | } 50 | 51 | // ManagedMachinePoolsPreflightCheck will perform checks against a slice of machine pool before they are created. 52 | func ManagedMachinePoolsPreflightCheck(managedPools []infrav1exp.GCPManagedMachinePool, machinePools []clusterv1exp.MachinePool, location string) error { 53 | if len(machinePools) != len(managedPools) { 54 | return errors.New("each machinepool must have a matching gcpmanagedmachinepool") 55 | } 56 | 57 | for i := range machinePools { 58 | machinepool := machinePools[i] 59 | managedPool := managedPools[i] 60 | 61 | if err := ManagedMachinePoolPreflightCheck(&managedPool, &machinepool, location); err != nil { 62 | return err 63 | } 64 | } 65 | 66 | return nil 67 | } 68 | 69 | // IsRegional will check if a given location is a region (if not its a zone). 70 | func IsRegional(location string) bool { 71 | return strings.Count(location, "-") == 1 72 | } 73 | -------------------------------------------------------------------------------- /cloudbuild-nightly.yaml: -------------------------------------------------------------------------------- 1 | # See https://cloud.google.com/cloud-build/docs/build-config 2 | timeout: 3600s 3 | options: 4 | substitution_option: ALLOW_LOOSE 5 | steps: 6 | - name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud@sha256:4e830b673791d5595719bc6c4ca62dce3746b4e20d749e45004254bc6ef0a140' # v20250116-2a05ea7e3d go 1.23.4 7 | entrypoint: make 8 | env: 9 | - DOCKER_CLI_EXPERIMENTAL=enabled 10 | - TAG=$_GIT_TAG 11 | - PULL_BASE_REF=$_PULL_BASE_REF 12 | args: 13 | - release-staging-nightly 14 | substitutions: 15 | # _GIT_TAG will be filled with a git-based tag for the image, of the form vYYYYMMDD-hash, and 16 | # can be used as a substitution 17 | _GIT_TAG: '12345' 18 | _PULL_BASE_REF: 'dev' 19 | -------------------------------------------------------------------------------- /cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # See https://cloud.google.com/cloud-build/docs/build-config 2 | timeout: 3600s 3 | options: 4 | substitution_option: ALLOW_LOOSE 5 | steps: 6 | - name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud@sha256:4e830b673791d5595719bc6c4ca62dce3746b4e20d749e45004254bc6ef0a140' # v20250116-2a05ea7e3d go 1.23.4 7 | entrypoint: make 8 | env: 9 | - DOCKER_CLI_EXPERIMENTAL=enabled 10 | - TAG=$_GIT_TAG 11 | - PULL_BASE_REF=$_PULL_BASE_REF 12 | args: 13 | - release-staging 14 | substitutions: 15 | # _GIT_TAG will be filled with a git-based tag for the image, of the form vYYYYMMDD-hash, and 16 | # can be used as a substitution 17 | _GIT_TAG: '12345' 18 | _PULL_BASE_REF: 'dev' 19 | -------------------------------------------------------------------------------- /clusterctl-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "infrastructure-gcp", 3 | "config": { 4 | "componentsFile": "infrastructure-components.yaml", 5 | "nextVersion": "v1.4.0" 6 | } 7 | } -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | apiVersion: cert-manager.io/v1 4 | kind: Issuer 5 | metadata: 6 | name: selfsigned-issuer 7 | namespace: system 8 | spec: 9 | selfSigned: {} 10 | --- 11 | apiVersion: cert-manager.io/v1 12 | kind: Certificate 13 | metadata: 14 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 15 | namespace: system 16 | spec: 17 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 18 | dnsNames: 19 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 20 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 21 | issuerRef: 22 | kind: Issuer 23 | name: selfsigned-issuer 24 | secretName: $(SERVICE_NAME)-cert 25 | -------------------------------------------------------------------------------- /config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - certificate.yaml 5 | 6 | configurations: 7 | - kustomizeconfig.yaml 8 | -------------------------------------------------------------------------------- /config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | - kind: Certificate 18 | group: cert-manager.io 19 | path: spec/secretName 20 | -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | commonLabels: 2 | cluster.x-k8s.io/v1beta1: v1beta1 3 | 4 | # This kustomization.yaml is not intended to be run by itself, 5 | # since it depends on service name and namespace that are out of this kustomize package. 6 | # It should be run by config/default 7 | resources: 8 | - bases/infrastructure.cluster.x-k8s.io_gcpmachines.yaml 9 | - bases/infrastructure.cluster.x-k8s.io_gcpclusters.yaml 10 | - bases/infrastructure.cluster.x-k8s.io_gcpmachinetemplates.yaml 11 | - bases/infrastructure.cluster.x-k8s.io_gcpclustertemplates.yaml 12 | - bases/infrastructure.cluster.x-k8s.io_gcpmanagedclusters.yaml 13 | - bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml 14 | - bases/infrastructure.cluster.x-k8s.io_gcpmanagedmachinepools.yaml 15 | 16 | # +kubebuilder:scaffold:crdkustomizeresource 17 | 18 | patchesStrategicMerge: 19 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 20 | # patches here are for enabling the conversion webhook for each CRD 21 | - patches/webhook_in_gcpmachines.yaml 22 | - patches/webhook_in_gcpclusters.yaml 23 | - patches/webhook_in_gcpmachinetemplates.yaml 24 | - patches/webhook_in_gcpclustertemplates.yaml 25 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 26 | 27 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 28 | # patches here are for enabling the CA injection for each CRD 29 | - patches/cainjection_in_gcpmachines.yaml 30 | - patches/cainjection_in_gcpclusters.yaml 31 | - patches/cainjection_in_gcpmachinetemplates.yaml 32 | - patches/cainjection_in_gcpclustertemplates.yaml 33 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 34 | 35 | # the following config is for teaching kustomize how to do kustomization for CRDs. 36 | configurations: 37 | - kustomizeconfig.yaml 38 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | group: apiextensions.k8s.io 8 | path: spec/conversion/webhook/clientConfig/service/name 9 | 10 | namespace: 11 | - kind: CustomResourceDefinition 12 | group: apiextensions.k8s.io 13 | path: spec/conversion/webhook/clientConfig/service/namespace 14 | create: false 15 | 16 | varReference: 17 | - path: metadata/annotations 18 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_gcpclusters.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: gcpclusters.infrastructure.cluster.x-k8s.io 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_gcpclustertemplates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: gcpclustertemplates.infrastructure.cluster.x-k8s.io 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_gcpmachines.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: gcpmachines.infrastructure.cluster.x-k8s.io 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_gcpmachinetemplates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: gcpmachinetemplates.infrastructure.cluster.x-k8s.io 9 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_gcpclusters.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: gcpclusters.infrastructure.cluster.x-k8s.io 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhook: 11 | conversionReviewVersions: ["v1", "v1beta1"] 12 | clientConfig: 13 | service: 14 | namespace: system 15 | name: webhook-service 16 | path: /convert 17 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_gcpclustertemplates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: gcpclustertemplates.infrastructure.cluster.x-k8s.io 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhook: 11 | clientConfig: 12 | service: 13 | namespace: system 14 | name: webhook-service 15 | path: /convert 16 | conversionReviewVersions: ["v1", "v1beta1"] 17 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_gcpmachines.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: gcpmachines.infrastructure.cluster.x-k8s.io 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhook: 11 | conversionReviewVersions: ["v1", "v1beta1"] 12 | clientConfig: 13 | service: 14 | namespace: system 15 | name: webhook-service 16 | path: /convert 17 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_gcpmachinetemplates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: gcpmachinetemplates.infrastructure.cluster.x-k8s.io 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhook: 11 | conversionReviewVersions: ["v1", "v1beta1"] 12 | clientConfig: 13 | service: 14 | namespace: system 15 | name: webhook-service 16 | path: /convert 17 | -------------------------------------------------------------------------------- /config/default/credentials.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: manager-bootstrap-credentials 5 | namespace: system 6 | type: Opaque 7 | data: 8 | credentials.json: ${GCP_B64ENCODED_CREDENTIALS} 9 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: capg-system 2 | 3 | namePrefix: capg- 4 | 5 | # Labels to add to all resources and selectors. 6 | commonLabels: 7 | cluster.x-k8s.io/provider: "infrastructure-gcp" 8 | 9 | resources: 10 | - namespace.yaml 11 | - credentials.yaml 12 | 13 | bases: 14 | - ../crd 15 | - ../rbac 16 | - ../manager 17 | - ../webhook 18 | - ../certmanager 19 | 20 | patchesStrategicMerge: 21 | - manager_image_patch.yaml 22 | - manager_pull_policy.yaml 23 | - manager_credentials_patch.yaml 24 | - manager_webhook_patch.yaml 25 | - webhookcainjection_patch.yaml 26 | 27 | vars: 28 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 29 | objref: 30 | kind: Certificate 31 | group: cert-manager.io 32 | version: v1 33 | name: serving-cert # this name should match the one in certificate.yaml 34 | fieldref: 35 | fieldpath: metadata.namespace 36 | - name: CERTIFICATE_NAME 37 | objref: 38 | kind: Certificate 39 | group: cert-manager.io 40 | version: v1 41 | name: serving-cert # this name should match the one in certificate.yaml 42 | - name: SERVICE_NAMESPACE # namespace of the service 43 | objref: 44 | kind: Service 45 | version: v1 46 | name: webhook-service 47 | fieldref: 48 | fieldpath: metadata.namespace 49 | - name: SERVICE_NAME 50 | objref: 51 | kind: Service 52 | version: v1 53 | name: webhook-service 54 | 55 | configurations: 56 | - kustomizeconfig.yaml 57 | -------------------------------------------------------------------------------- /config/default/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | varReference: 3 | - kind: Deployment 4 | path: spec/template/spec/volumes/secret/secretName 5 | -------------------------------------------------------------------------------- /config/default/manager_credentials_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | env: 12 | - name: GOOGLE_APPLICATION_CREDENTIALS 13 | value: /home/.gcp/credentials.json 14 | volumeMounts: 15 | - name: credentials 16 | mountPath: /home/.gcp 17 | volumes: 18 | - name: credentials 19 | secret: 20 | secretName: manager-bootstrap-credentials 21 | -------------------------------------------------------------------------------- /config/default/manager_image_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | # Change the value of image field below to your controller image URL 11 | - image: gcr.io/k8s-staging-cluster-api-gcp/cluster-api-gcp-controller:e2e 12 | name: manager 13 | -------------------------------------------------------------------------------- /config/default/manager_prometheus_metrics_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch enables Prometheus scraping for the manager pod. 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | metadata: 10 | annotations: 11 | prometheus.io/scrape: 'true' 12 | spec: 13 | containers: 14 | # Expose the prometheus metrics on default port 15 | - name: manager 16 | ports: 17 | - containerPort: 8080 18 | name: metrics 19 | protocol: TCP 20 | -------------------------------------------------------------------------------- /config/default/manager_pull_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | imagePullPolicy: IfNotPresent 12 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: $(SERVICE_NAME)-cert 24 | -------------------------------------------------------------------------------- /config/default/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: system 5 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | 2 | # This patch add annotation to admission webhook config and 3 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 4 | # uncomment the following lines to enable mutating webhook 5 | apiVersion: admissionregistration.k8s.io/v1 6 | kind: MutatingWebhookConfiguration 7 | metadata: 8 | name: mutating-webhook-configuration 9 | annotations: 10 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 11 | --- 12 | apiVersion: admissionregistration.k8s.io/v1 13 | kind: ValidatingWebhookConfiguration 14 | metadata: 15 | name: validating-webhook-configuration 16 | annotations: 17 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 18 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - manager.yaml 5 | -------------------------------------------------------------------------------- /config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | labels: 8 | control-plane: capg-controller-manager 9 | spec: 10 | selector: 11 | matchLabels: 12 | control-plane: capg-controller-manager 13 | replicas: 1 14 | template: 15 | metadata: 16 | labels: 17 | control-plane: capg-controller-manager 18 | annotations: 19 | kubectl.kubernetes.io/default-container: manager 20 | spec: 21 | containers: 22 | - args: 23 | - --leader-elect 24 | - --feature-gates=GKE=${EXP_CAPG_GKE:=false} 25 | - "--diagnostics-address=${CAPG_DIAGNOSTICS_ADDRESS:=:8443}" 26 | - "--insecure-diagnostics=${CAPG_INSECURE_DIAGNOSTICS:=false}" 27 | - "--v=${CAPG_LOGLEVEL:=0}" 28 | image: controller:latest 29 | imagePullPolicy: IfNotPresent 30 | name: manager 31 | ports: 32 | - containerPort: 9440 33 | name: healthz 34 | protocol: TCP 35 | - containerPort: 8443 36 | name: metrics 37 | protocol: TCP 38 | readinessProbe: 39 | httpGet: 40 | path: /readyz 41 | port: healthz 42 | initialDelaySeconds: 10 43 | periodSeconds: 10 44 | livenessProbe: 45 | httpGet: 46 | path: /healthz 47 | port: healthz 48 | initialDelaySeconds: 10 49 | periodSeconds: 10 50 | terminationMessagePolicy: FallbackToLogsOnError 51 | securityContext: 52 | allowPrivilegeEscalation: false 53 | capabilities: 54 | drop: 55 | - ALL 56 | privileged: false 57 | runAsUser: 65532 58 | runAsGroup: 65532 59 | env: 60 | - name: NODE_NAME 61 | valueFrom: 62 | fieldRef: 63 | fieldPath: spec.nodeName 64 | - name: POD_NAME 65 | valueFrom: 66 | fieldRef: 67 | fieldPath: metadata.name 68 | - name: POD_NAMESPACE 69 | valueFrom: 70 | fieldRef: 71 | fieldPath: metadata.namespace 72 | terminationGracePeriodSeconds: 10 73 | serviceAccountName: manager 74 | tolerations: 75 | - effect: NoSchedule 76 | key: node-role.kubernetes.io/master 77 | - effect: NoSchedule 78 | key: node-role.kubernetes.io/control-plane 79 | -------------------------------------------------------------------------------- /config/rbac/gcpclustertemplate_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit gcpclustertemplates. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: gcpclustertemplate-editor-role 6 | rules: 7 | - apiGroups: 8 | - infrastructure.cluster.x-k8s.io 9 | resources: 10 | - gcpclustertemplates 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - infrastructure.cluster.x-k8s.io 21 | resources: 22 | - gcpclustertemplates/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /config/rbac/gcpclustertemplate_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view gcpclustertemplates. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: gcpclustertemplate-viewer-role 6 | rules: 7 | - apiGroups: 8 | - infrastructure.cluster.x-k8s.io 9 | resources: 10 | - gcpclustertemplates 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - infrastructure.cluster.x-k8s.io 17 | resources: 18 | - gcpclustertemplates/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - role.yaml 5 | - role_binding.yaml 6 | - service_account.yaml 7 | - leader_election_role.yaml 8 | - leader_election_role_binding.yaml 9 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - configmaps/status 23 | verbs: 24 | - get 25 | - update 26 | - patch 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - events 31 | verbs: 32 | - create 33 | - apiGroups: 34 | - "coordination.k8s.io" 35 | resources: 36 | - leases 37 | verbs: 38 | - get 39 | - list 40 | - watch 41 | - create 42 | - update 43 | - patch 44 | - delete 45 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: manager-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - events 11 | verbs: 12 | - create 13 | - get 14 | - list 15 | - patch 16 | - update 17 | - watch 18 | - apiGroups: 19 | - "" 20 | resources: 21 | - secrets 22 | verbs: 23 | - create 24 | - delete 25 | - get 26 | - list 27 | - patch 28 | - update 29 | - watch 30 | - apiGroups: 31 | - authentication.k8s.io 32 | resources: 33 | - tokenreviews 34 | verbs: 35 | - create 36 | - apiGroups: 37 | - authorization.k8s.io 38 | resources: 39 | - subjectaccessreviews 40 | verbs: 41 | - create 42 | - apiGroups: 43 | - cluster.x-k8s.io 44 | resources: 45 | - clusters 46 | - clusters/status 47 | - machinepools 48 | - machinepools/status 49 | - machines 50 | - machines/status 51 | verbs: 52 | - get 53 | - list 54 | - watch 55 | - apiGroups: 56 | - infrastructure.cluster.x-k8s.io 57 | resources: 58 | - gcpclusters 59 | - gcpmachines 60 | - gcpmanagedclusters 61 | - gcpmanagedcontrolplanes 62 | - gcpmanagedmachinepools 63 | verbs: 64 | - create 65 | - delete 66 | - get 67 | - list 68 | - patch 69 | - update 70 | - watch 71 | - apiGroups: 72 | - infrastructure.cluster.x-k8s.io 73 | resources: 74 | - gcpclusters/status 75 | - gcpmachines/status 76 | - gcpmanagedclusters/status 77 | - gcpmanagedcontrolplanes/status 78 | - gcpmanagedmachinepools/status 79 | verbs: 80 | - get 81 | - patch 82 | - update 83 | - apiGroups: 84 | - infrastructure.cluster.x-k8s.io 85 | resources: 86 | - gcpmanagedclusters/finalizers 87 | - gcpmanagedcontrolplanes/finalizers 88 | - gcpmanagedmachinepools/finalizers 89 | verbs: 90 | - update 91 | -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | 27 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: webhook-service 5 | namespace: system 6 | spec: 7 | ports: 8 | - port: 443 9 | targetPort: webhook-server 10 | -------------------------------------------------------------------------------- /controllers/gcpcluster_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "golang.org/x/net/context" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" 25 | ctrl "sigs.k8s.io/controller-runtime" 26 | "sigs.k8s.io/controller-runtime/pkg/client" 27 | ) 28 | 29 | var _ = Describe("GCPClusterReconciler", func() { 30 | BeforeEach(func() {}) 31 | AfterEach(func() {}) 32 | 33 | Context("Reconcile an GCPCluster", func() { 34 | It("should not error and not requeue the request with insufficient set up", func() { 35 | ctx := context.Background() 36 | 37 | reconciler := &GCPClusterReconciler{ 38 | Client: k8sClient, 39 | } 40 | 41 | instance := &infrav1.GCPCluster{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}} 42 | 43 | // Create the GCPCluster object and expect the Reconcile and Deployment to be created 44 | Expect(k8sClient.Create(ctx, instance)).To(Succeed()) 45 | defer func() { 46 | err := k8sClient.Delete(ctx, instance) 47 | Expect(err).NotTo(HaveOccurred()) 48 | }() 49 | 50 | result, err := reconciler.Reconcile(ctx, ctrl.Request{ 51 | NamespacedName: client.ObjectKey{ 52 | Namespace: instance.Namespace, 53 | Name: instance.Name, 54 | }, 55 | }) 56 | Expect(err).NotTo(HaveOccurred()) 57 | Expect(result.RequeueAfter).To(BeZero()) 58 | Expect(result.Requeue).To(BeFalse()) 59 | }) 60 | }) 61 | }) 62 | -------------------------------------------------------------------------------- /controllers/gcpmachine_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "context" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" 26 | ctrl "sigs.k8s.io/controller-runtime" 27 | "sigs.k8s.io/controller-runtime/pkg/client" 28 | ) 29 | 30 | var _ = Describe("GCPMachineReconciler", func() { 31 | BeforeEach(func() {}) 32 | AfterEach(func() {}) 33 | 34 | Context("Reconcile an GCPMachine", func() { 35 | It("should not error with minimal set up", func() { 36 | reconciler := &GCPMachineReconciler{ 37 | Client: k8sClient, 38 | } 39 | By("Calling reconcile") 40 | ctx := context.Background() 41 | instance := &infrav1.GCPMachine{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}} 42 | result, err := reconciler.Reconcile(ctx, ctrl.Request{ 43 | NamespacedName: client.ObjectKey{ 44 | Namespace: instance.Namespace, 45 | Name: instance.Name, 46 | }, 47 | }) 48 | Expect(err).NotTo(HaveOccurred()) 49 | Expect(result.RequeueAfter).To(BeZero()) 50 | Expect(result.Requeue).To(BeFalse()) 51 | }) 52 | }) 53 | }) 54 | -------------------------------------------------------------------------------- /controllers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "path/filepath" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes/scheme" 26 | "k8s.io/client-go/rest" 27 | "k8s.io/klog/v2" 28 | infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" 29 | clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 30 | "sigs.k8s.io/controller-runtime/pkg/client" 31 | "sigs.k8s.io/controller-runtime/pkg/envtest" 32 | logf "sigs.k8s.io/controller-runtime/pkg/log" 33 | ) 34 | 35 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 36 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 37 | 38 | var ( 39 | cfg *rest.Config 40 | k8sClient client.Client 41 | testEnv *envtest.Environment 42 | ) 43 | 44 | func init() { 45 | klog.InitFlags(nil) 46 | klog.SetOutput(GinkgoWriter) 47 | logf.SetLogger(klog.Background()) 48 | } 49 | 50 | func TestAPIs(t *testing.T) { 51 | RegisterFailHandler(Fail) 52 | // fetch the current config 53 | _, reporterConfig := GinkgoConfiguration() 54 | // adjust it 55 | reporterConfig.FullTrace = true 56 | RunSpecs(t, "Controller Suite", reporterConfig) 57 | } 58 | 59 | var _ = BeforeSuite(func() { 60 | By("bootstrapping test environment") 61 | testEnv = &envtest.Environment{ 62 | CRDDirectoryPaths: []string{ 63 | filepath.Join("..", "config", "crd", "bases"), 64 | }, 65 | } 66 | 67 | var err error 68 | cfg, err = testEnv.Start() 69 | Expect(err).NotTo(HaveOccurred()) 70 | Expect(cfg).ToNot(BeNil()) 71 | 72 | Expect(clusterv1.AddToScheme(scheme.Scheme)).To(Succeed()) 73 | Expect(infrav1.AddToScheme(scheme.Scheme)).To(Succeed()) 74 | 75 | // +kubebuilder:scaffold:scheme 76 | 77 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 78 | Expect(err).NotTo(HaveOccurred()) 79 | Expect(k8sClient).ToNot(BeNil()) 80 | }) 81 | 82 | var _ = AfterSuite(func() { 83 | By("tearing down the test environment") 84 | err := testEnv.Stop() 85 | Expect(err).NotTo(HaveOccurred()) 86 | }) 87 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation Index 2 | 3 | ## Quick Start 4 | 5 | - [Getting Started](./book/src/topics/prerequisites.md) 6 | - [Cluster API Quick Start](https://cluster-api.sigs.k8s.io/user/quick-start.html) 7 | 8 | ## Development 9 | 10 | - [Development Guide](./book/src/developers/development.md) 11 | - [Releasing](./book/src/developers/releasing.md) 12 | 13 | ## Testing 14 | - [Conformance](./book/src/topics/conformance.md) 15 | -------------------------------------------------------------------------------- /docs/book/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2024 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Directories. 16 | ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 17 | TOOLS_DIR := $(realpath ../../hack/tools) 18 | TOOLS_BIN_DIR := $(TOOLS_DIR)/bin 19 | BIN_DIR := bin 20 | MDBOOK_INSTALL := $(realpath ../../scripts/ci-install-mdbook.sh) 21 | TABULATE := $(TOOLS_BIN_DIR)/mdbook-tabulate 22 | EMBED := $(TOOLS_BIN_DIR)/mdbook-embed 23 | RELEASELINK := $(TOOLS_BIN_DIR)/mdbook-releaselink 24 | MDBOOK := $(TOOLS_BIN_DIR)/mdbook 25 | 26 | export PATH := $(TOOLS_BIN_DIR):$(PATH) 27 | 28 | BOOK_DEPS := $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK) 29 | 30 | $(TOOLS_BIN_DIR)/%: $(TOOLS_DIR_DEPS) 31 | make -C $(TOOLS_DIR) $(subst $(TOOLS_DIR)/,,$@) 32 | 33 | .PHONY: serve 34 | serve: $(BOOK_DEPS) ## Run a local web server with the compiled book 35 | $(MDBOOK) serve 36 | 37 | .PHONY: build 38 | build: $(BOOK_DEPS) ## Build the book 39 | $(MDBOOK) build 40 | 41 | .PHONY: clean 42 | clean: 43 | rm -rf book 44 | -------------------------------------------------------------------------------- /docs/book/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["The Cluster API Provider GCP Maintainers"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "Kubernetes Cluster API Provider GCP" 7 | 8 | [output.html] 9 | curly-quotes = true 10 | git-repository-url = "https://sigs.k8s.io/cluster-api-provider-gcp" 11 | no-section-label = true 12 | 13 | [output.html.redirect] 14 | "/agenda.html" = "/agenda/2024.html" 15 | "/agenda/2024.html" = "https://docs.google.com/document/d/1l8B947Je79ZJX7zmKnJyMcOMIWjNidvp5FMTnPAY72I/" 16 | 17 | [preprocessor.tabulate] 18 | command = "mdbook-tabulate" 19 | 20 | [preprocessor.embed] 21 | command = "mdbook-embed" 22 | 23 | [preprocessor.releaselink] 24 | command = "mdbook-releaselink" 25 | -------------------------------------------------------------------------------- /docs/book/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | [Introduction](./introduction.md) 4 | - [Quick Start](./quick-start.md) 5 | - [Prerequisites](./prerequisites.md) 6 | - [Self-managed clusters](./self-managed/index.md) 7 | - [Provisioning a Cluster](./self-managed/provision.md) 8 | - [CNI](./self-managed/cni.md) 9 | - [Managed clusters - GKE](./managed/index.md) 10 | - [Provisioning a Cluster](./managed/provision.md) 11 | - [Cluster Upgrades](./managed/upgrades.md) 12 | - [Enabling](./managed/enabling.md) 13 | - [Disabling](./managed/disabling.md) 14 | - [ClusterClass](./clusterclass/index.md) 15 | - [Provisioning a Cluster](./clusterclass/provision.md) 16 | - [Enabling](./clusterclass/enabling.md) 17 | - [Disabling](./clusterclass/disabling.md) 18 | - [General Topics](./topics/index.md) 19 | - [Conformance](./topics/conformance.md) 20 | - [Machine Locations](./topics/machine-locations.md) 21 | - [Preemptible VMs](./topics/preemptible-vms.md) 22 | - [Developer Guide](./developers/index.md) 23 | - [Development](./developers/development.md) 24 | - [Try unreleased changes with Nightly Builds](./developers/nightlies.md) 25 | - [Creating a cluster](./developers/cluster-creation.md) 26 | - [CI Jobs](./developers/jobs.md) 27 | - [Adding new E2E test](./developers/e2e.md) 28 | - [Releasing](./developers/releasing.md) 29 | - [Roadmap](./roadmap.md) 30 | -------------------------------------------------------------------------------- /docs/book/src/clusterclass/disabling.md: -------------------------------------------------------------------------------- 1 | # Disabling ClusterClass Support 2 | 3 | Support for ClusterClass is disabled by default when you use the GCP infrastructure provider. 4 | -------------------------------------------------------------------------------- /docs/book/src/clusterclass/enabling.md: -------------------------------------------------------------------------------- 1 | # Enabling ClusterClass Support 2 | 3 | Enabling ClusterClass support is done via the **ClusterTopology** feature flag by setting it to true. This can be done before running `clusterctl init` by using the **CLUSTER_TOPOLOGY** environment variable: 4 | 5 | ```shell 6 | export CLUSTER_TOPOLOGY=true 7 | clusterctl init --infrastructure gcp 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/book/src/clusterclass/index.md: -------------------------------------------------------------------------------- 1 | # ClusterClass 2 | 3 | - **Feature status:** Experimental 4 | - **Feature gate:** `ClusterTopology=true` 5 | 6 | [ClusterClass](https://cluster-api.sigs.k8s.io/tasks/experimental-features/cluster-class/index.html) is a collection of templates that define a topology (control plane and machine deployments) to be used to continuously reconcile one or more Clusters. It is built on top of the existing Cluster API resources and provides a set of tools and operations to streamline cluster lifecycle management while maintaining the same underlying API. 7 | 8 | 15 | 16 | CAPG supports the creation of clusters via Cluster Topology for **self-managed clusters only**. 17 | -------------------------------------------------------------------------------- /docs/book/src/developers/cluster-creation.md: -------------------------------------------------------------------------------- 1 | # Creating cluster without clusterctl 2 | 3 | This document describes how to create a management cluster and workload cluster without using clusterctl. 4 | For creating a cluster with clusterctl, checkout our [Cluster API Quick Start](https://cluster-api.sigs.k8s.io/user/quick-start.html) 5 | 6 | ## For creating a Management cluster 7 | 8 | 1. Build required images by using the following commands: 9 | 10 | - `docker build --tag=gcr.io/k8s-staging-cluster-api-gcp/cluster-api-gcp-controller:e2e .` 11 | - `make docker-build-all` 12 | 13 | 2. Set the required environment variables. For example: 14 | 15 | ```sh 16 | export GCP_REGION=us-east4 17 | export GCP_PROJECT=k8s-staging-cluster-api-gcp 18 | export CONTROL_PLANE_MACHINE_COUNT=1 19 | export WORKER_MACHINE_COUNT=1 20 | export KUBERNETES_VERSION=1.21.6 21 | export GCP_CONTROL_PLANE_MACHINE_TYPE=n1-standard-2 22 | export GCP_NODE_MACHINE_TYPE=n1-standard-2 23 | export GCP_NETWORK_NAME=default 24 | export GCP_B64ENCODED_CREDENTIALS=$( cat /path/to/gcp_credentials.json | base64 | tr -d '\n' ) 25 | export CLUSTER_NAME="capg-test" 26 | export IMAGE_ID=projects/k8s-staging-cluster-api-gcp/global/images/cluster-api-ubuntu-2204-v1-27-3-nightly 27 | ``` 28 | 29 | You can check for other images to set the `IMAGE_ID` of your choice. 30 | 31 | 3. Run `make create-management-cluster` from root directory. 32 | 33 | -------------------------------------------------------------------------------- /docs/book/src/developers/e2e.md: -------------------------------------------------------------------------------- 1 | # Adding new E2E test 2 | 3 | E2E tests verify a complete, real-world workflow ensuring that all parts of the system work together as expected. If you are introducing a new feature that interconnects with other parts of the software, you will likely be required to add a verification step for this functionality with a new E2E scenario (unless it is already covered by existing test suites). 4 | 5 | 12 | 13 | ## Create a cluster template 14 | 15 | The test suite will provision a cluster based on a pre-defined yaml template (stored in `./test/e2e/data`) which is then sourced in `./test/e2e/config/gcp-ci.yaml`. New cluster definitions for E2E tests have to be added and sourced before being available to use in the E2E workflow. 16 | 17 | ## Add test case 18 | 19 | When the template is available, you can reference it as a flavor in Go. For example, adding a new test for self-managed cluster provisioning would look like the following: 20 | 21 | ```golang 22 | Context("Creating a control-plane cluster with an internal load balancer", func() { 23 | It("Should create a cluster with 1 control-plane and 1 worker node with an internal load balancer", func() { 24 | By("Creating a cluster with internal load balancer") 25 | clusterctl.ApplyClusterTemplateAndWait(ctx, clusterctl.ApplyClusterTemplateAndWaitInput{ 26 | ClusterProxy: bootstrapClusterProxy, 27 | ConfigCluster: clusterctl.ConfigClusterInput{ 28 | LogFolder: clusterctlLogFolder, 29 | ClusterctlConfigPath: clusterctlConfigPath, 30 | KubeconfigPath: bootstrapClusterProxy.GetKubeconfigPath(), 31 | InfrastructureProvider: clusterctl.DefaultInfrastructureProvider, 32 | Flavor: "ci-with-internal-lb", 33 | Namespace: namespace.Name, 34 | ClusterName: clusterName, 35 | KubernetesVersion: e2eConfig.GetVariable(KubernetesVersion), 36 | ControlPlaneMachineCount: ptr.To[int64](1), 37 | WorkerMachineCount: ptr.To[int64](1), 38 | }, 39 | WaitForClusterIntervals: e2eConfig.GetIntervals(specName, "wait-cluster"), 40 | WaitForControlPlaneIntervals: e2eConfig.GetIntervals(specName, "wait-control-plane"), 41 | WaitForMachineDeployments: e2eConfig.GetIntervals(specName, "wait-worker-nodes"), 42 | }, result) 43 | }) 44 | }) 45 | ``` 46 | 47 | In this case, the flavor `ci-with-internal-lb` is a reference to the template `cluster-template-ci-with-internal-lb.yaml` which is available in `./test/e2e/data/infrastructure-gcp/cluster-template-ci-with-internal-lb.yaml`. 48 | -------------------------------------------------------------------------------- /docs/book/src/developers/index.md: -------------------------------------------------------------------------------- 1 | Everything you need to know about contributing to CAPG. 2 | 3 | If you are new to the project and want to help but don't know where to start, you can refer to the [Cluster API contributing guide](https://github.com/kubernetes-sigs/cluster-api/blob/main/CONTRIBUTING.md). 4 | -------------------------------------------------------------------------------- /docs/book/src/developers/nightlies.md: -------------------------------------------------------------------------------- 1 | # Nightly Builds 2 | 3 | Nightly builds are regular automated builds of the CAPG source code that occur every night. 4 | 5 | These builds are generated directly from the latest commit of source code on the main branch. 6 | 7 | Nightly builds serve several purposes: 8 | 9 | - **Early Testing**: They provide an opportunity for developers and testers to access the most recent changes in the codebase and identify any issues or bugs that may have been introduced. 10 | - **Feedback Loop**: They facilitate a rapid feedback loop, enabling developers to receive feedback on their changes quickly, allowing them to iterate and improve the code more efficiently. 11 | - **Preview of New Features**: Users and can get a preview of upcoming features or changes by testing nightly builds, although these builds may not always be stable enough for production use. 12 | 13 | Overall, nightly builds play a crucial role in software development by promoting user testing, early bug detection, and rapid iteration. 14 | 15 | CAPG Nightly build jobs run in Prow. 16 | 17 | ## Usage 18 | 19 | To try a nightly build, you can download the latest built nightly CAPG manifests, you can find the available ones by executing the following command: 20 | ```bash 21 | curl -sL -H 'Accept: application/json' "https://storage.googleapis.com/storage/v1/b/k8s-staging-cluster-api-gcp/o" | jq -r '.items | map(select(.name | startswith("components/nightly_main"))) | .[] | [.timeCreated,.mediaLink] | @tsv' 22 | ``` 23 | The output should look something like this: 24 | ``` 25 | 2024-05-03T08:03:09.087Z https://storage.googleapis.com/download/storage/v1/b/k8s-staging-cluster-api-gcp/o/components%2Fnightly_main_2024050x?generation=1714723389033961&alt=media 26 | 2024-05-04T08:02:52.517Z https://storage.googleapis.com/download/storage/v1/b/k8s-staging-cluster-api-gcp/o/components%2Fnightly_main_2024050y?generation=1714809772486582&alt=media 27 | 2024-05-05T08:02:45.840Z https://storage.googleapis.com/download/storage/v1/b/k8s-staging-cluster-api-gcp/o/components%2Fnightly_main_2024050z?generation=1714896165803510&alt=media 28 | ``` 29 | 30 | Now visit the link for the manifest you want to download. This will automatically download the manifest for you. 31 | 32 | Once downloaded you can apply the manifest directly to your testing CAPI management cluster/namespace (e.g. with kubectl), as the downloaded CAPG manifest 33 | will already contain the correct, corresponding CAPG nightly image reference. 34 | -------------------------------------------------------------------------------- /docs/book/src/introduction.md: -------------------------------------------------------------------------------- 1 | {{#include ../../../README.md}} 2 | -------------------------------------------------------------------------------- /docs/book/src/managed/disabling.md: -------------------------------------------------------------------------------- 1 | # Disabling GKE Support 2 | 3 | Support for GKE is disabled by default when you use the GCP infrastructure provider. 4 | -------------------------------------------------------------------------------- /docs/book/src/managed/enabling.md: -------------------------------------------------------------------------------- 1 | # Enabling GKE Support 2 | 3 | Enabling GKE support is done via the **GKE** feature flag by setting it to true. This can be done before running `clusterctl init` by using the **EXP_CAPG_GKE** environment variable: 4 | 5 | ```shell 6 | export EXP_CAPG_GKE=true 7 | clusterctl init --infrastructure gcp 8 | ``` 9 | 10 | > IMPORTANT: To use GKE the service account used for CAPG will need the `iam.serviceAccountTokenCreator` role assigned. 11 | -------------------------------------------------------------------------------- /docs/book/src/managed/index.md: -------------------------------------------------------------------------------- 1 | # GKE Support in the GCP Provider 2 | 3 | - **Feature status:** Experimental 4 | - **Feature gate (required):** GKE=true 5 | 6 | 13 | 14 | ## Overview 15 | 16 | The GCP provider supports creating GKE based cluster. Currently the following features are supported: 17 | 18 | - Provisioning/managing a GCP GKE Cluster 19 | - Upgrading the Kubernetes version of the GKE Cluster 20 | - Creating a managed node pool and attaching it to the GKE cluster 21 | 22 | The implementation introduces the following CRD kinds: 23 | 24 | - GCPManagedCluster - presents the properties needed to provision and manage the general GCP operating infrastructure for the cluster (i.e project, networking, iam) 25 | - GCPManagedControlPlane - specifies the GKE Cluster in GCP and used by the Cluster API GCP Managed Control plane 26 | - GCPManagedMachinePool - defines the managed node pool for the cluster 27 | 28 | And a new template is available in the templates folder for creating a managed workload cluster. 29 | 30 | ## SEE ALSO 31 | 32 | * [Enabling GKE Support](enabling.md) 33 | * [Disabling GKE Support](disabling.md) 34 | * [Creating a cluster](provision.md) 35 | * [Cluster Upgrades](upgrades.md) 36 | -------------------------------------------------------------------------------- /docs/book/src/managed/provision.md: -------------------------------------------------------------------------------- 1 | # Provisioning a GKE cluster 2 | 3 | 10 | 11 | **This guide uses an example from the `./templates` folder of the CAPG repository. You can inspect the yaml file [here](https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-gcp/refs/heads/main/templates/cluster-template-gke.yaml).** 12 | 13 | ## Configure cluster parameters 14 | 15 | While inspecting the cluster definition in `./templates/cluster-template-gke.yaml` you probably noticed that it contains a number of parameterized values that must be substituted with the specifics of your use case. This can be done via environment variables and `clusterctl` and effectively makes the template more flexible to adapt to different provisioning scenarios. These are the environment variables that you'll be required to set before deploying a workload cluster: 16 | 17 | ```sh 18 | export GCP_PROJECT=cluster-api-gcp-project 19 | export GCP_REGION=us-east4 20 | export GCP_NETWORK_NAME=default 21 | export WORKER_MACHINE_COUNT=1 22 | ``` 23 | 24 | ## Generate cluster definition 25 | 26 | The sample cluster templates are already prepared so that you can use them with `clusterctl` to create a GKE cluster with CAPG. 27 | 28 | To create a GKE cluster with a managed node group (a.k.a managed machine pool): 29 | 30 | ```bash 31 | clusterctl generate cluster capi-gke-quickstart --flavor gke -i gcp > capi-gke-quickstart.yaml 32 | ``` 33 | 34 | In this example, `capi-gke-quickstart` will be used as cluster name. 35 | 36 | ## Create cluster 37 | 38 | The resulting file represents the workload cluster definition and you simply need to apply it to your cluster to trigger cluster creation: 39 | 40 | ``` 41 | kubectl apply -f capi-gke-quickstart.yaml 42 | ``` 43 | 44 | ## Kubeconfig 45 | 46 | When creating an GKE cluster 2 kubeconfigs are generated and stored as secrets in the management cluster. 47 | 48 | ### User kubeconfig 49 | 50 | This should be used by users that want to connect to the newly created GKE cluster. The name of the secret that contains the kubeconfig will be `[cluster-name]-user-kubeconfig` where you need to replace **[cluster-name]** with the name of your cluster. The **-user-kubeconfig** in the name indicates that the kubeconfig is for the user use. 51 | 52 | To get the user kubeconfig for a cluster named `managed-test` you can run a command similar to: 53 | 54 | ```bash 55 | kubectl --namespace=default get secret managed-test-user-kubeconfig \ 56 | -o jsonpath={.data.value} | base64 --decode \ 57 | > managed-test.kubeconfig 58 | ``` 59 | 60 | ### Cluster API (CAPI) kubeconfig 61 | 62 | This kubeconfig is used internally by CAPI and shouldn't be used outside of the management server. It is used by CAPI to perform operations, such as draining a node. The name of the secret that contains the kubeconfig will be `[cluster-name]-kubeconfig` where you need to replace **[cluster-name]** with the name of your cluster. Note that there is NO `-user` in the name. 63 | 64 | The kubeconfig is regenerated every `sync-period` as the token that is embedded in the kubeconfig is only valid for a short period of time. 65 | -------------------------------------------------------------------------------- /docs/book/src/managed/upgrades.md: -------------------------------------------------------------------------------- 1 | # GKE Cluster Upgrades 2 | 3 | ## Control Plane Upgrade 4 | 5 | Upgrading the Kubernetes version of the control plane is supported by the provider. To perform an upgrade you need to update the `controlPlaneVersion` in the spec of the `GCPManagedControlPlane`. Once the version has changed the provider will handle the upgrade for you. 6 | -------------------------------------------------------------------------------- /docs/book/src/roadmap.md: -------------------------------------------------------------------------------- 1 | # Cluster API GCP roadmap 2 | 3 | This roadmap is a constant work in progress, subject to frequent revision. Dates are approximations. Features are listed in no particular order. 4 | 5 | ## v0.4 (v1Alpha4) 6 | 7 | |Description|Issue/Proposal/PR| 8 | |--|--| 9 | 10 | 11 | 12 | ## v1beta1/v1 13 | 14 | Proposal awaits. 15 | 16 | ## Lifecycle frozen 17 | 18 | > Items within this category have been identified as potential candidates for the project 19 | > and can be moved up into a milestone if there is enough interest. 20 | 21 | | Description | Issue/Proposal/PR | 22 | |--|--| 23 | | Enabling GPU enabled clusters | [#289](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/289) | 24 | | Publish images in GCP | [#152](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/152) | 25 | | Proper bootstrap of manually deleted worker VMs | [#173](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/173) | 26 | | Correct URI for subnetwork setup | [#278](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/278) | 27 | | Workload identity support | [#311](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/311) | 28 | | Implement GCPMachinePool using MIGs | [#297](https://github.com/kubernetes-sigs/cluster-api-provider-gcp/issues/297) | 29 | -------------------------------------------------------------------------------- /docs/book/src/self-managed/cni.md: -------------------------------------------------------------------------------- 1 | # CNI 2 | 3 | By default, no CNI plugin is installed when a self-managed cluster is provisioned. As a user, you need to [install your own](https://cluster-api.sigs.k8s.io/user/quick-start.html#deploy-a-cni-solution) CNI (e.g. Calico with VXLAN) for the control plane of the cluster to become ready. 4 | 5 | This document describes how to use [Flannel](https://github.com/flannel-io/flannel) as your CNI solution. 6 | 7 | ## Modify the Cluster resources 8 | 9 | Before deploying the cluster, change the `KubeadmControlPlane` value at `spec.kubeadmConfigSpec.clusterConfiguration.controllerManager.extraArgs.allocate-node-cidrs` to `"true"` 10 | 11 | ```yaml 12 | apiVersion: controlplane.cluster.x-k8s.io/v1beta1 13 | kind: KubeadmControlPlane 14 | spec: 15 | kubeadmConfigSpec: 16 | clusterConfiguration: 17 | controllerManager: 18 | extraArgs: 19 | allocate-node-cidrs: "true" 20 | ``` 21 | 22 | ## Modify Flannel Config 23 | 24 | *(NOTE)*: This is based off of the instruction at: [deploying-flannel-manually](https://github.com/flannel-io/flannel#deploying-flannel-manually) 25 | 26 | You need to make an adjustment to the default flannel configuration so that the CIDR inside your CAPG cluster matches the Flannel Network CIDR. 27 | 28 | View your capi-cluster.yaml and make note of the Cluster Network CIDR Block. For example: 29 | 30 | ```yaml 31 | apiVersion: cluster.x-k8s.io/v1beta1 32 | kind: Cluster 33 | spec: 34 | clusterNetwork: 35 | pods: 36 | cidrBlocks: 37 | - 192.168.0.0/16 38 | ``` 39 | 40 | Download the file at `https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml` and modify the `kube-flannel-cfg` ConfigMap. Set the value at `data.net-conf.json.Network` value to match your Cluster Network CIDR Block. 41 | 42 | ```sh 43 | wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 44 | ``` 45 | 46 | Edit kube-flannel.yml and change this section so that the Network section matches your Cluster CIDR 47 | 48 | ```yaml 49 | kind: ConfigMap 50 | apiVersion: v1 51 | metadata: 52 | name: kube-flannel-cfg 53 | data: 54 | net-conf.json: | 55 | { 56 | "Network": "192.168.0.0/16", 57 | "Backend": { 58 | "Type": "vxlan" 59 | } 60 | } 61 | ``` 62 | 63 | Apply kube-flannel.yml 64 | 65 | ```sh 66 | kubectl apply -f kube-flannel.yml 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/book/src/self-managed/index.md: -------------------------------------------------------------------------------- 1 | # Self-managed clusters 2 | 3 | This section contains information about how you can provision self-managed Kubernetes clusters hosted in GCP's Compute Engine. 4 | -------------------------------------------------------------------------------- /docs/book/src/topics/conformance.md: -------------------------------------------------------------------------------- 1 | # Running Conformance tests 2 | 3 | ## Required environment variables 4 | - Set the GCP region 5 | 6 | ```console 7 | export GCP_REGION=us-east4 8 | ``` 9 | 10 | - Set the GCP project to use 11 | 12 | ```console 13 | export GCP_PROJECT=your-project-id 14 | ``` 15 | 16 | - Set the path to the service account 17 | 18 | ```console 19 | export GOOGLE_APPLICATION_CREDENTIALS=path/to/your/service-account.json 20 | ``` 21 | 22 | ## Optional environment variables 23 | 24 | - Set a specific name for your cluster 25 | 26 | ```console 27 | export CLUSTER_NAME=test1 28 | ``` 29 | 30 | - Set a specific name for your network 31 | 32 | ```console 33 | export NETWORK_NAME=test1-mynetwork 34 | ``` 35 | 36 | - Skip cleaning up the project resources 37 | 38 | ```console 39 | export SKIP_CLEANUP=1 40 | ``` 41 | 42 | ## Running the conformance tests 43 | 44 | ```console 45 | scripts/ci-conformance.sh 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/book/src/topics/index.md: -------------------------------------------------------------------------------- 1 | This section contains information about relevant CAPG features and how to use them. 2 | -------------------------------------------------------------------------------- /docs/book/src/topics/machine-locations.md: -------------------------------------------------------------------------------- 1 | # Machine Locations 2 | 3 | This document describes how to configure the location of a CAPG cluster's compute resources. By default, CAPG requires the user to specify a [GCP region](https://cloud.google.com/compute/docs/regions-zones#available) for the cluster's machines by setting the `GCP_REGION` environment variable as outlined in the [CAPI quickstart guide](https://cluster-api.sigs.k8s.io/user/quick-start.html#required-configuration-for-common-providers). The provider then picks a zone to deploy the control plane and worker nodes in and generates the according portions of the cluster's YAML manifests. 4 | 5 | It is possible to override this default behaviour and exercise more fine-grained control over machine locations as outlined in the rest of this document. 6 | 7 | ## Control Plane Machine Location 8 | 9 | Before deploying the cluster, add a `failureDomains` field to the `spec` of your `GCPCluster` definition, containing a list of allowed zones: 10 | 11 | ```diff 12 | apiVersion: infrastructure.cluster.x-k8s.io/v1alpha4 13 | kind: GCPCluster 14 | metadata: 15 | name: capi-quickstart 16 | spec: 17 | network: 18 | name: default 19 | project: cyberscan2 20 | region: europe-west3 21 | + failureDomains: 22 | + - europe-west3-b 23 | ``` 24 | 25 | In this example configuration, only a single zone has been added, ensuring the control plane is provisioned in `europe-west3-b`. 26 | 27 | ## Node Pool Location 28 | 29 | Similar to the above, you can override the auto-generated GCP zone for your `MachineDeployment`, by changing the value of the `failureDomain` field at `spec.template.spec.failureDomain`: 30 | 31 | ```diff 32 | apiVersion: cluster.x-k8s.io/v1alpha4 33 | kind: MachineDeployment 34 | metadata: 35 | name: capi-quickstart-md-0 36 | spec: 37 | clusterName: capi-quickstart 38 | # [...] 39 | template: 40 | spec: 41 | # [...] 42 | clusterName: capi-quickstart 43 | - failureDomain: europe-west3-a 44 | + failureDomain: europe-west3-b 45 | ``` 46 | 47 | When combined like this, the above configuration effectively instructs CAPG to deploy the CAPI equivalent of a [zonal GKE cluster](https://cloud.google.com/kubernetes-engine/docs/concepts/types-of-clusters#availability). -------------------------------------------------------------------------------- /docs/book/src/topics/preemptible-vms.md: -------------------------------------------------------------------------------- 1 | # Preemptible Virtual Machines 2 | 3 | [GCP Preemptible Virtual Machines](https://cloud.google.com/compute/docs/instances/preemptible) allows user to run a VM instance at a much lower price when compared to normal VM instances. 4 | 5 | Compute Engine might stop (preempt) these instances if it requires access to those resources for other tasks. Preemptible instances will always stop after 24 hours. 6 | 7 | ## When do I use Preemptible Virtual Machines? 8 | 9 | A Preemptible VM works best for applications or systems that distribute processes across multiple instances in a cluster. While a shutdown would be disruptive for common enterprise applications, such as databases, it’s hardly noticeable in distributed systems that run across clusters of machines and are designed to tolerate failures. 10 | 11 | ## How do I use Preemptible Virtual Machines? 12 | 13 | To enable a machine to be backed by Preemptible Virtual Machine, add `preemptible` option to `GCPMachineTemplate` and set it to True. 14 | 15 | ```yaml 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | kind: GCPMachineTemplate 18 | metadata: 19 | name: capg-md-0 20 | spec: 21 | region: us-west-1 22 | template: 23 | osDisk: 24 | diskSizeGB: 30 25 | managedDisk: 26 | storageAccountType: STANDARD 27 | osType: Linux 28 | vmSize: E2 29 | preemptible: true 30 | ``` 31 | 32 | ## Spot VMs 33 | [Spot VMs are the latest version of preemptible VMs.](https://cloud.google.com/compute/docs/instances/spot) 34 | 35 | To use a Spot VM instead of a Preemptible VM, add `provisioningModel` to `GCPMachineTemplate` and set it to `Spot`. 36 | 37 | ```yaml 38 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 39 | kind: GCPMachineTemplate 40 | metadata: 41 | name: capg-md-0 42 | spec: 43 | region: us-west-1 44 | template: 45 | osDisk: 46 | diskSizeGB: 30 47 | managedDisk: 48 | storageAccountType: STANDARD 49 | osType: Linux 50 | vmSize: E2 51 | provisioningModel: Spot 52 | ``` 53 | 54 | NOTE: specifying `preemptible: true` and `provisioningModel: Spot` is equivalent to only `provisioningModel: Spot`. Spot takes priority. 55 | -------------------------------------------------------------------------------- /docs/book/theme/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-gcp/7aa05f2d534e21b780b44d0012b7941db73a6f45/docs/book/theme/favicon.png -------------------------------------------------------------------------------- /docs/book/theme/head.hbs: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /exp/PROJECT: -------------------------------------------------------------------------------- 1 | domain: cluster.x-k8s.io 2 | layout: 3 | - go.kubebuilder.io/v3 4 | repo: sigs.k8s.io/cluster-api-provider-gcp/exp 5 | resources: 6 | - api: 7 | crdVersion: v1 8 | namespaced: true 9 | controller: true 10 | domain: cluster.x-k8s.io 11 | group: infrastructure 12 | kind: GCPManagedCluster 13 | path: sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1 14 | version: v1beta1 15 | webhooks: 16 | defaulting: true 17 | validation: true 18 | webhookVersion: v1 19 | - api: 20 | crdVersion: v1 21 | namespaced: true 22 | controller: true 23 | domain: cluster.x-k8s.io 24 | group: infrastructure 25 | kind: GCPManagedControlPlane 26 | path: sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1 27 | version: v1beta1 28 | webhooks: 29 | defaulting: true 30 | validation: true 31 | webhookVersion: v1 32 | - api: 33 | crdVersion: v1 34 | namespaced: true 35 | controller: true 36 | domain: cluster.x-k8s.io 37 | group: infrastructure 38 | kind: GCPManagedMachinePool 39 | path: sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1 40 | version: v1beta1 41 | webhooks: 42 | defaulting: true 43 | validation: true 44 | webhookVersion: v1 45 | version: "3" 46 | -------------------------------------------------------------------------------- /exp/README.md: -------------------------------------------------------------------------------- 1 | # Experimental 2 | 3 | This repository holds experimental code and API types. 4 | 5 | **Warning**: Packages here are experimental and unreliable. Some may one day be promoted to the main repository, or they may be modified arbitrarily or even disappear altogether. 6 | 7 | In short, code in this repository is not subject to any compatibility or deprecation promise. 8 | 9 | 10 | For policy around graduation timeline, see [Cluster API Exp](https://github.com/kubernetes-sigs/cluster-api/tree/master/exp). -------------------------------------------------------------------------------- /exp/api/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the infrastructure v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=infrastructure.cluster.x-k8s.io 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects. 29 | GroupVersion = schema.GroupVersion{Group: "infrastructure.cluster.x-k8s.io", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /exp/controllers/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package controllers contains experimental controllers. 18 | package controllers 19 | -------------------------------------------------------------------------------- /exp/controllers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "path/filepath" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes/scheme" 26 | "k8s.io/client-go/rest" 27 | infrastructurev1beta1 "sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1" 28 | "sigs.k8s.io/controller-runtime/pkg/client" 29 | "sigs.k8s.io/controller-runtime/pkg/envtest" 30 | logf "sigs.k8s.io/controller-runtime/pkg/log" 31 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 32 | ) 33 | 34 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 35 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 36 | 37 | var ( 38 | cfg *rest.Config 39 | k8sClient client.Client 40 | testEnv *envtest.Environment 41 | ) 42 | 43 | func TestAPIs(t *testing.T) { 44 | RegisterFailHandler(Fail) 45 | 46 | RunSpecs(t, "Controller Suite") 47 | } 48 | 49 | var _ = BeforeSuite(func() { 50 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 51 | 52 | By("bootstrapping test environment") 53 | testEnv = &envtest.Environment{ 54 | CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, 55 | ErrorIfCRDPathMissing: true, 56 | } 57 | 58 | var err error 59 | // cfg is defined in this file globally. 60 | cfg, err = testEnv.Start() 61 | Expect(err).NotTo(HaveOccurred()) 62 | Expect(cfg).NotTo(BeNil()) 63 | 64 | err = infrastructurev1beta1.AddToScheme(scheme.Scheme) 65 | Expect(err).NotTo(HaveOccurred()) 66 | 67 | //+kubebuilder:scaffold:scheme 68 | 69 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 70 | Expect(err).NotTo(HaveOccurred()) 71 | Expect(k8sClient).NotTo(BeNil()) 72 | }) 73 | 74 | var _ = AfterSuite(func() { 75 | By("tearing down the test environment") 76 | err := testEnv.Stop() 77 | Expect(err).NotTo(HaveOccurred()) 78 | }) 79 | -------------------------------------------------------------------------------- /exp/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package exp contains experimental functionality. 18 | package exp 19 | -------------------------------------------------------------------------------- /exp/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /feature/feature.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | // Package feature implements feature functionality. 15 | package feature 16 | 17 | import ( 18 | "k8s.io/apimachinery/pkg/util/runtime" 19 | "k8s.io/component-base/featuregate" 20 | ) 21 | 22 | const ( 23 | // Every capg-specific feature gate should add method here following this template: 24 | // 25 | // // owner: @username 26 | // // alpha: v1.X 27 | // MyFeature featuregate.Feature = "MyFeature". 28 | 29 | // GKE is used to enable GKE support 30 | // owner: @richardchen331 & @richardcase 31 | // alpha: v0.1 32 | GKE featuregate.Feature = "GKE" 33 | ) 34 | 35 | func init() { 36 | runtime.Must(MutableGates.Add(defaultCAPGFeatureGates)) 37 | } 38 | 39 | // defaultCAPGFeatureGates consists of all known capg-specific feature keys. 40 | // To add a new feature, define a key for it above and add it here. 41 | var defaultCAPGFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ 42 | GKE: {Default: false, PreRelease: featuregate.Alpha}, 43 | } 44 | -------------------------------------------------------------------------------- /feature/gates.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package feature 15 | 16 | import ( 17 | "k8s.io/component-base/featuregate" 18 | "sigs.k8s.io/cluster-api/feature" 19 | ) 20 | 21 | var ( 22 | // MutableGates is a mutable version of DefaultFeatureGate. 23 | // Only top-level commands/options setup and the k8s.io/component-base/featuregate/testing package should make use of this. 24 | // Tests that need to modify featuregate gates for the duration of their test should use: 25 | // defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features., )() 26 | MutableGates featuregate.MutableFeatureGate = feature.MutableGates 27 | 28 | // Gates is a shared global FeatureGate. 29 | // Top-level commands/options setup that needs to modify this featuregate gate should use DefaultMutableFeatureGate. 30 | Gates featuregate.FeatureGate = MutableGates 31 | ) 32 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /hack/boilerplate/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | exports_files(glob(["*.txt"])) 4 | 5 | py_test( 6 | name = "boilerplate_test", 7 | srcs = [ 8 | "boilerplate.py", 9 | "boilerplate_test.py", 10 | ], 11 | data = glob([ 12 | "*.txt", 13 | "test/*", 14 | ]), 15 | ) 16 | 17 | filegroup( 18 | name = "package-srcs", 19 | srcs = glob(["**"]), 20 | tags = ["automanaged"], 21 | visibility = ["//visibility:private"], 22 | ) 23 | 24 | filegroup( 25 | name = "all-srcs", 26 | srcs = [ 27 | ":package-srcs", 28 | "//hack/boilerplate/test:all-srcs", 29 | ], 30 | tags = ["automanaged"], 31 | ) 32 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.Dockerfile.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.Makefile.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.bzl.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.generatebzl.txt: -------------------------------------------------------------------------------- 1 | # Copyright The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.generatego.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright YEAR The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.py.txt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright YEAR The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate.sh.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /hack/boilerplate/boilerplate_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2016 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import boilerplate 18 | import unittest 19 | import StringIO 20 | import os 21 | import sys 22 | 23 | class TestBoilerplate(unittest.TestCase): 24 | """ 25 | Note: run this test from the hack/boilerplate directory. 26 | 27 | $ python -m unittest boilerplate_test 28 | """ 29 | 30 | def test_boilerplate(self): 31 | os.chdir("test/") 32 | 33 | class Args(object): 34 | def __init__(self): 35 | self.filenames = [] 36 | self.rootdir = "." 37 | self.boilerplate_dir = "../" 38 | self.verbose = True 39 | 40 | # capture stdout 41 | old_stdout = sys.stdout 42 | sys.stdout = StringIO.StringIO() 43 | 44 | boilerplate.args = Args() 45 | ret = boilerplate.main() 46 | 47 | output = sorted(sys.stdout.getvalue().split()) 48 | 49 | sys.stdout = old_stdout 50 | 51 | self.assertEquals( 52 | output, ['././fail.go', '././fail.py']) 53 | -------------------------------------------------------------------------------- /hack/boilerplate/test/fail.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Kubernetes Authors. 3 | 4 | fail 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // Package test implements all things for testing. 20 | package test 21 | -------------------------------------------------------------------------------- /hack/boilerplate/test/fail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # failed 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | -------------------------------------------------------------------------------- /hack/boilerplate/test/pass.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package test 18 | -------------------------------------------------------------------------------- /hack/boilerplate/test/pass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | True 18 | -------------------------------------------------------------------------------- /hack/checkin_account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2019 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from urllib.parse import urlencode 18 | import sys 19 | import http.client as httplib 20 | import os 21 | 22 | BOSKOS_HOST=os.environ.get("BOSKOS_HOST", "boskos") 23 | BOSKOS_RESOURCE_NAME=os.environ['BOSKOS_RESOURCE_NAME'] 24 | 25 | USER = "cluster-api-provider-gcp" 26 | 27 | if __name__ == "__main__": 28 | conn = httplib.HTTPConnection(BOSKOS_HOST) 29 | conn.request("POST", "/release?%s" % urlencode({ 30 | 'name': BOSKOS_RESOURCE_NAME, 31 | 'dest': 'dirty', 32 | 'owner': USER, 33 | })) 34 | 35 | resp = conn.getresponse() 36 | if resp.status != 200: 37 | sys.exit("boskos: checkin_account: Got invalid response while checking for 'release': %d: %s, %r" % (resp.status, resp.reason, resp)) 38 | conn.close() 39 | -------------------------------------------------------------------------------- /hack/checkout_account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2019 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """Checks out a gcp account from E2E""" 18 | 19 | from urllib.parse import urlencode 20 | import http.client as httplib 21 | import os 22 | import sys 23 | import json 24 | 25 | BOSKOS_HOST=os.environ.get("BOSKOS_HOST", "boskos") 26 | 27 | RESOURCE_TYPE = "gce-project" 28 | USER = "cluster-api-provider-gcp" 29 | 30 | def post_request(host, input_state = "clean"): 31 | conn = httplib.HTTPConnection(host) 32 | conn.request("POST", "/acquire?%s" % urlencode({ 33 | 'type': RESOURCE_TYPE, 34 | 'owner': USER, 35 | 'state': input_state, 36 | 'dest': 'busy', 37 | }) 38 | 39 | ) 40 | resp = conn.getresponse() 41 | status = resp.status 42 | reason = resp.reason 43 | body = resp.read() 44 | conn.close() 45 | return status, reason, body 46 | 47 | if __name__ == "__main__": 48 | status, reason, result = post_request(BOSKOS_HOST) 49 | # we're working around an issue with the data in boskos. 50 | # We'll remove the code that tries both free and clean once all the data is good. 51 | # Afterwards we should just check for free 52 | if status == 404: 53 | status, reason, result = post_request(BOSKOS_HOST, "free") 54 | 55 | if status != 200: 56 | sys.exit("boskos: checkout_account: Got invalid response while checking for 'free': %d: %s, %r" % (status, reason, result)) 57 | 58 | body = json.loads(result) 59 | print('export BOSKOS_RESOURCE_NAME="%s";' % body['name']) 60 | print('export GCP_PROJECT="%s";' % body['name']) 61 | -------------------------------------------------------------------------------- /hack/ensure-go.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # Ensure the go tool exists and is a viable version. 22 | verify_go_version() { 23 | if [[ -z "$(command -v go)" ]]; then 24 | cat <&2 35 | done 36 | 37 | exit 1 38 | fi 39 | -------------------------------------------------------------------------------- /hack/verify-starlark.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2022 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" 21 | ROOT_PATH="$(cd "${SCRIPT_DIR}"/.. && pwd)" 22 | 23 | VERSION="0.29.0" 24 | 25 | MODE="check" 26 | 27 | if [[ "$*" == "fix" ]]; then 28 | MODE="fix" 29 | fi 30 | 31 | if [[ "${OSTYPE}" == "linux"* ]]; then 32 | BINARY="buildifier" 33 | elif [[ "${OSTYPE}" == "darwin"* ]]; then 34 | BINARY="buildifier.mac" 35 | fi 36 | 37 | # create a temporary directory 38 | TMP_DIR=$(mktemp -d) 39 | OUT="${TMP_DIR}/out.log" 40 | 41 | # cleanup on exit 42 | cleanup() { 43 | ret=0 44 | if [[ -s "${OUT}" ]]; then 45 | echo "Found errors:" 46 | cat "${OUT}" 47 | echo "" 48 | echo "run make format-tiltfile to fix the errors" 49 | ret=1 50 | fi 51 | echo "Cleaning up..." 52 | rm -rf "${TMP_DIR}" 53 | exit ${ret} 54 | } 55 | trap cleanup EXIT 56 | 57 | BUILDIFIER="${SCRIPT_DIR}/tools/bin/buildifier/${VERSION}/buildifier" 58 | 59 | if [ ! -f "$BUILDIFIER" ]; then 60 | # install buildifier 61 | cd "${TMP_DIR}" || exit 62 | curl -L "https://github.com/bazelbuild/buildtools/releases/download/${VERSION}/${BINARY}" -o "${TMP_DIR}/buildifier" 63 | chmod +x "${TMP_DIR}/buildifier" 64 | cd "${ROOT_PATH}" 65 | mkdir -p "$(dirname "$0")/tools/bin/buildifier/${VERSION}" 66 | mv "${TMP_DIR}/buildifier" "$BUILDIFIER" 67 | fi 68 | 69 | echo "Running buildifier..." 70 | cd "${ROOT_PATH}" || exit 71 | "${BUILDIFIER}" -mode=${MODE} Tiltfile >> "${OUT}" 2>&1 72 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | # maps release series of major.minor to cluster-api contract version 2 | # the contract version may change between minor or major versions, but *not* 3 | # between patch versions. 4 | # 5 | # update this file only when a new major or minor version is released 6 | apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 7 | releaseSeries: 8 | - major: 0 9 | minor: 3 10 | contract: v1alpha3 11 | - major: 0 12 | minor: 4 13 | contract: v1alpha4 14 | - major: 1 15 | minor: 0 16 | contract: v1beta1 17 | - major: 1 18 | minor: 1 19 | contract: v1beta1 20 | - major: 1 21 | minor: 2 22 | contract: v1beta1 23 | - major: 1 24 | minor: 3 25 | contract: v1beta1 26 | - major: 1 27 | minor: 4 28 | contract: v1beta1 29 | - major: 1 30 | minor: 5 31 | contract: v1beta1 32 | - major: 1 33 | minor: 6 34 | contract: v1beta1 35 | - major: 1 36 | minor: 7 37 | contract: v1beta1 38 | - major: 1 39 | minor: 8 40 | contract: v1beta1 41 | - major: 1 42 | minor: 9 43 | contract: v1beta1 44 | - major: 1 45 | minor: 10 46 | contract: v1beta1 47 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Netlify build instructions 2 | [build] 3 | command = "make -C docs/book build" 4 | publish = "docs/book/book" 5 | 6 | [build.environment] 7 | GO_VERSION = "1.21.10" 8 | 9 | # Standard Netlify redirects 10 | [[redirects]] 11 | from = "https://main--cluster-api-gcp.netlify.com/*" 12 | to = "https://main.cluster-api-gcp.sigs.k8s.io/:splat" 13 | status = 301 14 | force = true 15 | 16 | # HTTP-to-HTTPS rules 17 | [[redirects]] 18 | from = "http://main.cluster-api-gcp.sigs.k8s.io/*" 19 | to = "https://main.cluster-api-gcp.sigs.k8s.io/:splat" 20 | status = 301 21 | force = true 22 | 23 | [[redirects]] 24 | from = "http://main--cluster-api-gcp.netlify.com/*" 25 | to = "http://main.cluster-api-gcp.sigs.k8s.io/:splat" 26 | status = 301 27 | force = true 28 | -------------------------------------------------------------------------------- /scripts/ci-apidiff.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | 23 | APIDIFF="${REPO_ROOT}/hack/tools/bin/go-apidiff" 24 | 25 | cd "${REPO_ROOT}" && make "${APIDIFF##*/}" 26 | echo "*** Running go-apidiff ***" 27 | 28 | ${APIDIFF} "${PULL_BASE_SHA}" --print-compatible 29 | -------------------------------------------------------------------------------- /scripts/ci-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | # shellcheck source=hack/ensure-go.sh 23 | source "${REPO_ROOT}/hack/ensure-go.sh" 24 | 25 | cd "${REPO_ROOT}" && make binaries 26 | -------------------------------------------------------------------------------- /scripts/ci-make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | # shellcheck source=hack/ensure-go.sh 23 | source "${REPO_ROOT}/hack/ensure-go.sh" 24 | 25 | export CONTROLLER_IMG="gcr.io/k8s-staging-cluster-api-gcp/cluster-api-gcp-controller" 26 | cd "${REPO_ROOT}" && make docker-build 27 | -------------------------------------------------------------------------------- /scripts/ci-test-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | # shellcheck source=hack/ensure-go.sh 23 | source "${REPO_ROOT}/hack/ensure-go.sh" 24 | 25 | make --directory="${REPO_ROOT}" test-cover 26 | -------------------------------------------------------------------------------- /scripts/ci-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | # shellcheck source=hack/ensure-go.sh 23 | source "${REPO_ROOT}/hack/ensure-go.sh" 24 | 25 | cd "${REPO_ROOT}" && \ 26 | make test-junit 27 | -------------------------------------------------------------------------------- /scripts/go_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2020 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | if [[ -z "${1}" ]]; then 21 | echo "must provide module as first parameter" 22 | exit 1 23 | fi 24 | 25 | if [[ -z "${2}" ]]; then 26 | echo "must provide binary name as second parameter" 27 | exit 1 28 | fi 29 | 30 | if [[ -z "${3}" ]]; then 31 | echo "must provide version as third parameter" 32 | exit 1 33 | fi 34 | 35 | if [[ -z "${GOBIN}" ]]; then 36 | echo "GOBIN is not set. Must set GOBIN to install the bin in a specified directory." 37 | exit 1 38 | fi 39 | 40 | rm "${GOBIN}/${2}"* || true 41 | 42 | # install the golang module specified as the first argument 43 | go install -tags capgtools "${1}@${3}" 44 | mv "${GOBIN}/${2}" "${GOBIN}/${2}-${3}" 45 | ln -sf "${GOBIN}/${2}-${3}" "${GOBIN}/${2}" 46 | -------------------------------------------------------------------------------- /templates/cluster-template-gke-autopilot.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | spec: 7 | clusterNetwork: 8 | pods: 9 | cidrBlocks: ["192.168.0.0/16"] 10 | infrastructureRef: 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPManagedCluster 13 | name: "${CLUSTER_NAME}" 14 | controlPlaneRef: 15 | kind: GCPManagedControlPlane 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | name: "${CLUSTER_NAME}-control-plane" 18 | --- 19 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 20 | kind: GCPManagedCluster 21 | metadata: 22 | name: "${CLUSTER_NAME}" 23 | spec: 24 | project: "${GCP_PROJECT}" 25 | region: "${GCP_REGION}" 26 | network: 27 | name: "${GCP_NETWORK_NAME}" 28 | --- 29 | kind: GCPManagedControlPlane 30 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 31 | metadata: 32 | name: "${CLUSTER_NAME}-control-plane" 33 | spec: 34 | project: "${GCP_PROJECT}" 35 | location: "${GCP_REGION}" 36 | enableAutopilot: true 37 | -------------------------------------------------------------------------------- /templates/cluster-template-gke.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | spec: 7 | clusterNetwork: 8 | pods: 9 | cidrBlocks: ["192.168.0.0/16"] 10 | infrastructureRef: 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPManagedCluster 13 | name: "${CLUSTER_NAME}" 14 | controlPlaneRef: 15 | kind: GCPManagedControlPlane 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | name: "${CLUSTER_NAME}-control-plane" 18 | --- 19 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 20 | kind: GCPManagedCluster 21 | metadata: 22 | name: "${CLUSTER_NAME}" 23 | spec: 24 | project: "${GCP_PROJECT}" 25 | region: "${GCP_REGION}" 26 | network: 27 | name: "${GCP_NETWORK_NAME}" 28 | --- 29 | kind: GCPManagedControlPlane 30 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 31 | metadata: 32 | name: "${CLUSTER_NAME}-control-plane" 33 | spec: 34 | project: "${GCP_PROJECT}" 35 | location: "${GCP_REGION}" 36 | --- 37 | apiVersion: cluster.x-k8s.io/v1beta1 38 | kind: MachinePool 39 | metadata: 40 | name: "${CLUSTER_NAME}-mp-0" 41 | spec: 42 | clusterName: "${CLUSTER_NAME}" 43 | replicas: ${WORKER_MACHINE_COUNT} 44 | template: 45 | spec: 46 | bootstrap: 47 | dataSecretName: "" 48 | clusterName: "${CLUSTER_NAME}" 49 | infrastructureRef: 50 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 51 | kind: GCPManagedMachinePool 52 | name: "${CLUSTER_NAME}-mp-0" 53 | --- 54 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 55 | kind: GCPManagedMachinePool 56 | metadata: 57 | name: "${CLUSTER_NAME}-mp-0" 58 | spec: {} 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /templates/cluster-template-topology.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | labels: 7 | cni: "${CLUSTER_NAME}-crs-cni" 8 | spec: 9 | clusterNetwork: 10 | pods: 11 | cidrBlocks: ["192.168.0.0/16"] 12 | topology: 13 | class: ${CLUSTER_CLASS_NAME} 14 | version: "${KUBERNETES_VERSION}" 15 | controlPlane: 16 | replicas: ${CONTROL_PLANE_MACHINE_COUNT} 17 | workers: 18 | machineDeployments: 19 | - class: "default-worker" 20 | name: "md-0" 21 | replicas: ${WORKER_MACHINE_COUNT} 22 | variables: 23 | - name: region 24 | value: ${GCP_REGION} 25 | - name: controlPlaneMachineType 26 | value: ${GCP_CONTROL_PLANE_MACHINE_TYPE} 27 | - name: workerMachineType 28 | value: ${GCP_NODE_MACHINE_TYPE} 29 | --- 30 | apiVersion: v1 31 | kind: ConfigMap 32 | metadata: 33 | name: "${CLUSTER_NAME}-crs-cni" 34 | data: ${CNI_RESOURCES} 35 | --- 36 | apiVersion: addons.cluster.x-k8s.io/v1beta1 37 | kind: ClusterResourceSet 38 | metadata: 39 | name: "${CLUSTER_NAME}-crs-cni" 40 | spec: 41 | strategy: ApplyOnce 42 | clusterSelector: 43 | matchLabels: 44 | cni: "${CLUSTER_NAME}-crs-cni" 45 | resources: 46 | - name: "${CLUSTER_NAME}-crs-cni" 47 | kind: ConfigMap 48 | -------------------------------------------------------------------------------- /templates/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: default 4 | resources: 5 | - cluster-template.yaml 6 | -------------------------------------------------------------------------------- /templates/kustomizeversions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controlplane.cluster.x-k8s.io/v1beta1 2 | kind: KubeadmControlPlane 3 | metadata: 4 | name: "${CLUSTER_NAME}-control-plane" 5 | spec: 6 | kubeadmConfigSpec: 7 | useExperimentalRetryJoin: true 8 | clusterConfiguration: 9 | kubernetesVersion: "ci/${CI_VERSION}" 10 | --- 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPMachineTemplate 13 | metadata: 14 | name: "${CLUSTER_NAME}-control-plane" 15 | spec: 16 | template: 17 | spec: 18 | image: ${IMAGE_ID} 19 | --- 20 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 21 | kind: GCPMachineTemplate 22 | metadata: 23 | name: "${CLUSTER_NAME}-md-0" 24 | spec: 25 | template: 26 | spec: 27 | image: ${IMAGE_ID} 28 | -------------------------------------------------------------------------------- /test/e2e/data/infrastructure-gcp/cluster-template-ci-gke-autopilot.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | spec: 7 | clusterNetwork: 8 | pods: 9 | cidrBlocks: ["192.168.0.0/16"] 10 | infrastructureRef: 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPManagedCluster 13 | name: "${CLUSTER_NAME}" 14 | controlPlaneRef: 15 | kind: GCPManagedControlPlane 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | name: "${CLUSTER_NAME}-control-plane" 18 | --- 19 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 20 | kind: GCPManagedCluster 21 | metadata: 22 | name: "${CLUSTER_NAME}" 23 | spec: 24 | project: "${GCP_PROJECT}" 25 | region: "${GCP_REGION}" 26 | network: 27 | name: "${GCP_NETWORK_NAME}" 28 | --- 29 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 30 | kind: GCPManagedControlPlane 31 | metadata: 32 | name: "${CLUSTER_NAME}-control-plane" 33 | spec: 34 | project: "${GCP_PROJECT}" 35 | location: "${GCP_REGION}" 36 | enableAutopilot: true 37 | releaseChannel: "regular" 38 | -------------------------------------------------------------------------------- /test/e2e/data/infrastructure-gcp/cluster-template-ci-gke-custom-subnet.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | spec: 7 | clusterNetwork: 8 | pods: 9 | cidrBlocks: ["192.168.0.0/16"] 10 | infrastructureRef: 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPManagedCluster 13 | name: "${CLUSTER_NAME}" 14 | controlPlaneRef: 15 | kind: GCPManagedControlPlane 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | name: "${CLUSTER_NAME}-control-plane" 18 | --- 19 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 20 | kind: GCPManagedCluster 21 | metadata: 22 | name: "${CLUSTER_NAME}" 23 | spec: 24 | project: "${GCP_PROJECT}" 25 | region: "${GCP_REGION}" 26 | network: 27 | name: "${GCP_NETWORK_NAME}" 28 | autoCreateSubnetworks: false 29 | subnets: 30 | - name: "${GCP_SUBNET_NAME}" 31 | cidrBlock: "${GCP_SUBNET_CIDR}" 32 | region: "${GCP_REGION}" 33 | --- 34 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 35 | kind: GCPManagedControlPlane 36 | metadata: 37 | name: "${CLUSTER_NAME}-control-plane" 38 | spec: 39 | project: "${GCP_PROJECT}" 40 | location: "${GCP_REGION}" 41 | --- 42 | apiVersion: cluster.x-k8s.io/v1beta1 43 | kind: MachinePool 44 | metadata: 45 | name: ${CLUSTER_NAME}-mp-0 46 | spec: 47 | clusterName: ${CLUSTER_NAME} 48 | replicas: ${WORKER_MACHINE_COUNT} 49 | template: 50 | spec: 51 | bootstrap: 52 | dataSecretName: "" 53 | clusterName: ${CLUSTER_NAME} 54 | infrastructureRef: 55 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 56 | kind: GCPManagedMachinePool 57 | name: ${CLUSTER_NAME}-mp-0 58 | --- 59 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 60 | kind: GCPManagedMachinePool 61 | metadata: 62 | name: ${CLUSTER_NAME}-mp-0 63 | spec: {} 64 | 65 | -------------------------------------------------------------------------------- /test/e2e/data/infrastructure-gcp/cluster-template-ci-gke.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cluster.x-k8s.io/v1beta1 3 | kind: Cluster 4 | metadata: 5 | name: "${CLUSTER_NAME}" 6 | spec: 7 | clusterNetwork: 8 | pods: 9 | cidrBlocks: ["192.168.0.0/16"] 10 | infrastructureRef: 11 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 12 | kind: GCPManagedCluster 13 | name: "${CLUSTER_NAME}" 14 | controlPlaneRef: 15 | kind: GCPManagedControlPlane 16 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 17 | name: "${CLUSTER_NAME}-control-plane" 18 | --- 19 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 20 | kind: GCPManagedCluster 21 | metadata: 22 | name: "${CLUSTER_NAME}" 23 | spec: 24 | project: "${GCP_PROJECT}" 25 | region: "${GCP_REGION}" 26 | network: 27 | name: "${GCP_NETWORK_NAME}" 28 | --- 29 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 30 | kind: GCPManagedControlPlane 31 | metadata: 32 | name: "${CLUSTER_NAME}-control-plane" 33 | spec: 34 | project: "${GCP_PROJECT}" 35 | location: "${GCP_REGION}" 36 | version: "${KUBERNETES_VERSION}" 37 | releaseChannel: "regular" 38 | --- 39 | apiVersion: cluster.x-k8s.io/v1beta1 40 | kind: MachinePool 41 | metadata: 42 | name: ${CLUSTER_NAME}-mp-0 43 | spec: 44 | clusterName: ${CLUSTER_NAME} 45 | replicas: ${WORKER_MACHINE_COUNT} 46 | template: 47 | spec: 48 | bootstrap: 49 | dataSecretName: "" 50 | clusterName: ${CLUSTER_NAME} 51 | infrastructureRef: 52 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 53 | kind: GCPManagedMachinePool 54 | name: ${CLUSTER_NAME}-mp-0 55 | --- 56 | apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 57 | kind: GCPManagedMachinePool 58 | metadata: 59 | name: ${CLUSTER_NAME}-mp-0 60 | spec: 61 | scaling: 62 | minCount: ${GKE_MACHINE_POOL_MIN} 63 | maxCount: ${GKE_MACHINE_POOL_MAX} 64 | 65 | -------------------------------------------------------------------------------- /test/e2e/data/kubetest/conformance.yaml: -------------------------------------------------------------------------------- 1 | ginkgo.focus: \[Conformance\] 2 | disable-log-dump: true 3 | ginkgo.progress: true 4 | ginkgo.slowSpecThreshold: 120.0 5 | ginkgo.flakeAttempts: 3 6 | ginkgo.trace: true 7 | ginkgo.v: true 8 | -------------------------------------------------------------------------------- /test/e2e/data/shared/v1beta1/metadata.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 2 | kind: Metadata 3 | releaseSeries: 4 | - major: 1 5 | minor: 10 6 | contract: v1beta1 7 | - major: 1 8 | minor: 9 9 | contract: v1beta1 10 | - major: 1 11 | minor: 8 12 | contract: v1beta1 13 | - major: 1 14 | minor: 7 15 | contract: v1beta1 16 | - major: 1 17 | minor: 6 18 | contract: v1beta1 19 | - major: 1 20 | minor: 5 21 | contract: v1beta1 22 | - major: 1 23 | minor: 4 24 | contract: v1beta1 25 | - major: 1 26 | minor: 3 27 | contract: v1beta1 28 | - major: 1 29 | minor: 2 30 | contract: v1beta1 31 | - major: 1 32 | minor: 1 33 | contract: v1beta1 34 | - major: 1 35 | minor: 0 36 | contract: v1beta1 37 | - major: 0 38 | minor: 4 39 | contract: v1alpha4 40 | - major: 0 41 | minor: 3 42 | contract: v1alpha3 43 | - major: 0 44 | minor: 2 45 | contract: v1alpha2 46 | -------------------------------------------------------------------------------- /test/e2e/helpers.go: -------------------------------------------------------------------------------- 1 | //go:build e2e 2 | // +build e2e 3 | 4 | /* 5 | Copyright 2021 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package e2e 21 | 22 | import ( 23 | "fmt" 24 | "io" 25 | "net/http" 26 | "os" 27 | "strings" 28 | 29 | "sigs.k8s.io/cluster-api/test/framework/kubernetesversions" 30 | ) 31 | 32 | // resolveCIVersion resolves kubernetes version labels (e.g. latest, latest-1.xx) to the corresponding CI version numbers. 33 | // Go implementation of https://github.com/kubernetes-sigs/cluster-api/blob/d1dc87d5df3ab12a15ae5b63e50541a191b7fec4/scripts/ci-e2e-lib.sh#L75-L95. 34 | func resolveCIVersion(label string) (string, error) { 35 | if ciVersion, ok := os.LookupEnv("CI_VERSION"); ok { 36 | return ciVersion, nil 37 | } 38 | 39 | if strings.HasPrefix(label, "latest") { 40 | if kubernetesVersion, err := latestCIVersion(label); err == nil { 41 | return kubernetesVersion, nil 42 | } 43 | } 44 | // default to https://dl.k8s.io/ci/latest.txt if the label can't be resolved 45 | return kubernetesversions.LatestCIRelease() 46 | } 47 | 48 | // latestCIVersion returns the latest CI version of a given label in the form of latest-1.xx. 49 | func latestCIVersion(label string) (string, error) { 50 | ciVersionURL := fmt.Sprintf("https://dl.k8s.io/ci/%s.txt", label) 51 | resp, err := http.Get(ciVersionURL) 52 | if err != nil { 53 | return "", err 54 | } 55 | defer resp.Body.Close() 56 | 57 | b, err := io.ReadAll(resp.Body) 58 | if err != nil { 59 | return "", err 60 | } 61 | 62 | return strings.TrimSpace(string(b)), nil 63 | } 64 | -------------------------------------------------------------------------------- /tilt-provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcp", 3 | "config": { 4 | "image": "gcr.io/k8s-staging-cluster-api-gcp/cluster-api-gcp-controller", 5 | "live_reload_deps": [ 6 | "main.go", 7 | "go.mod", 8 | "go.sum", 9 | "api", 10 | "cloud", 11 | "controllers", 12 | "exp" 13 | ], 14 | "label": "CAPG" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tilt_modules/cert_manager/README.md: -------------------------------------------------------------------------------- 1 | # Cert-manager 2 | 3 | This extension deploys cert-manager. 4 | 5 | ## Usage 6 | 7 | Basic usage 8 | 9 | ``` 10 | load('ext://cert_manager', 'deploy_cert_manager') 11 | 12 | deploy_cert_manager() 13 | ``` 14 | 15 | This will deploy cert-manager to your cluster and check that it actually works. 16 | 17 | If working with Kind, it's possible to pass `load_to_kind=True` to `deploy_cert_manager` so 18 | all the cert-manager images will be pre-pulled to your local environment and then loaded into Kind before installing. 19 | This speeds up your workflow if you're repeatedly destroying and recreating your kind cluster, as it doesn't 20 | have to pull the images over the network each time. 21 | 22 | The full list of parameters accepted by `deploy_cert_manager` includes: 23 | - `registry` from which images should be pulled, defaults to `quay.io/jetstack` 24 | - `version` of cert-manager to install, defaults to `v1.3.1` 25 | - `load_to_kind` (see above), defaults to `False` 26 | - `kind_cluster_name`, defaults to `kind` 27 | -------------------------------------------------------------------------------- /tilt_modules/cert_manager/test/Tiltfile: -------------------------------------------------------------------------------- 1 | load('../Tiltfile', 'deploy_cert_manager') 2 | 3 | is_kind = k8s_context().startswith('kind-') 4 | deploy_cert_manager(load_to_kind=is_kind) 5 | 6 | local_resource( 7 | name='verify-cert-manager', 8 | cmd='kubectl wait --for=condition=Available --timeout=300s -n cert-manager deployment/cert-manager') 9 | -------------------------------------------------------------------------------- /tilt_modules/cert_manager/test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | cd "$(dirname "$0")" 18 | 19 | set -ex 20 | tilt ci 21 | tilt down --delete-namespaces 22 | -------------------------------------------------------------------------------- /tilt_modules/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Extensions": [ 3 | { 4 | "Name": "cert_manager", 5 | "ExtensionRegistry": "https://github.com/tilt-dev/tilt-extensions", 6 | "TimeFetched": "2021-06-18T15:44:50.729341+02:00" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /util/hash/base36.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package hash implements hashing utilities. 18 | package hash 19 | 20 | import ( 21 | "github.com/pkg/errors" 22 | "golang.org/x/crypto/blake2b" 23 | 24 | // keep the blank import to include intstr. 25 | _ "k8s.io/apimachinery/pkg/util/intstr" 26 | ) 27 | 28 | const base36set = "0123456789abcdefghijklmnopqrstuvwxyz" 29 | 30 | // Base36TruncatedHash returns a consistent hash using blake2b 31 | // and truncating the byte values to alphanumeric only 32 | // of a fixed length specified by the consumer. 33 | func Base36TruncatedHash(str string, hashLen int) (string, error) { 34 | hasher, err := blake2b.New(hashLen, nil) 35 | if err != nil { 36 | return "", errors.Wrap(err, "unable to create hash function") 37 | } 38 | 39 | if _, err := hasher.Write([]byte(str)); err != nil { 40 | return "", errors.Wrap(err, "unable to write hash") 41 | } 42 | return base36Truncate(hasher.Sum(nil)), nil 43 | } 44 | 45 | // base36Truncate returns a string that is base36 compliant 46 | // It is not an encoding since it returns a same-length string 47 | // for any byte value. 48 | func base36Truncate(bytes []byte) string { 49 | var chars string 50 | for _, bite := range bytes { 51 | idx := int(bite) % 36 52 | chars += string(base36set[idx]) 53 | } 54 | 55 | return chars 56 | } 57 | -------------------------------------------------------------------------------- /util/location/location.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package location implements location parsing utilities. 18 | package location 19 | 20 | import ( 21 | "strings" 22 | 23 | "github.com/pkg/errors" 24 | ) 25 | 26 | // Location captures the region and zone of a GCP location. 27 | // Examples of GCP location: 28 | // us-central1 (region). 29 | // us-central1-c (region with zone). 30 | type Location struct { 31 | Region string 32 | Zone *string 33 | } 34 | 35 | // Parse parses a location string. 36 | func Parse(location string) (Location, error) { 37 | parts := strings.Split(location, "-") 38 | if len(parts) < 2 { 39 | return Location{}, errors.New("invalid location") 40 | } 41 | region := strings.Join(parts[:2], "-") 42 | var zone *string 43 | if len(parts) == 3 { 44 | zone = &parts[2] 45 | } 46 | return Location{ 47 | Region: region, 48 | Zone: zone, 49 | }, nil 50 | } 51 | -------------------------------------------------------------------------------- /util/reconciler/defaults.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package reconciler implements the reconciler logic. 18 | package reconciler 19 | 20 | import ( 21 | "time" 22 | ) 23 | 24 | const ( 25 | // DefaultLoopTimeout is the default timeout for a reconcile loop (defaulted to the max ARM template duration). 26 | DefaultLoopTimeout = 90 * time.Minute 27 | // DefaultMappingTimeout is the default timeout for a controller request mapping func. 28 | DefaultMappingTimeout = 60 * time.Second 29 | // DefaultRetryTime is the default time to retry when certain conditions are not met. 30 | DefaultRetryTime = 1 * time.Minute 31 | ) 32 | 33 | // DefaultedLoopTimeout will default the timeout if it is zero valued. 34 | func DefaultedLoopTimeout(timeout time.Duration) time.Duration { 35 | if timeout <= 0 { 36 | return DefaultLoopTimeout 37 | } 38 | 39 | return timeout 40 | } 41 | -------------------------------------------------------------------------------- /util/reconciler/defaults_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package reconciler_test 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | "github.com/onsi/gomega" 24 | "sigs.k8s.io/cluster-api-provider-gcp/util/reconciler" 25 | ) 26 | 27 | func TestDefaultedTimeout(t *testing.T) { 28 | cases := []struct { 29 | Name string 30 | Subject time.Duration 31 | Expected time.Duration 32 | }{ 33 | { 34 | Name: "WithZeroValueDefaults", 35 | Subject: time.Duration(0), 36 | Expected: reconciler.DefaultLoopTimeout, 37 | }, 38 | { 39 | Name: "WithRealValue", 40 | Subject: 2 * time.Hour, 41 | Expected: 2 * time.Hour, 42 | }, 43 | { 44 | Name: "WithNegativeValue", 45 | Subject: time.Duration(-2), 46 | Expected: reconciler.DefaultLoopTimeout, 47 | }, 48 | } 49 | 50 | for _, c := range cases { 51 | t.Run(c.Name, func(t *testing.T) { 52 | t.Parallel() 53 | g := gomega.NewWithT(t) 54 | g.Expect(reconciler.DefaultedLoopTimeout(c.Subject)).To(gomega.Equal(c.Expected)) 55 | }) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /util/resourceurl/parse.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package resourceurl implements resource url parsing utilities. 18 | package resourceurl 19 | 20 | import ( 21 | "strings" 22 | 23 | "github.com/pkg/errors" 24 | ) 25 | 26 | const ( 27 | // ResourcePrefix is the prefix of a resource URL. 28 | ResourcePrefix = "https://www.googleapis.com/" 29 | // NumParts is the number of parts in a resource URL. 30 | NumParts = 8 31 | // ResourceCategoryIndex is the index of the resource category in resource URL parts. 32 | ResourceCategoryIndex = 0 33 | // ProjectIndex is the index of the project in resource URL parts. 34 | ProjectIndex = 3 35 | // LocationIndex is the index of the location in resource URL parts. 36 | LocationIndex = 5 37 | // SubResourceIndex is the index of the sub resource in resource URL parts. 38 | SubResourceIndex = 6 39 | // NameIndex is the index of the name in resource URL parts. 40 | NameIndex = 7 41 | ) 42 | 43 | // ResourceURL captures the individual fields of a GCP resource URL. 44 | // An example of GCP resource URL: 45 | // https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-b/instanceGroupManagers/gke-capg-gke-demo-mypool-aa1282e0-grp 46 | type ResourceURL struct { 47 | // The resource category (e.g. compute) 48 | ResourceCategory string 49 | // The project where the resource lives in (e.g. my-project) 50 | Project string 51 | // The location where the resource lives in (e.g. us-central1-b) 52 | Location string 53 | // The sub-type of the resource (e.g. instanceGroupManagers) 54 | SubResource string 55 | // The name of the resource (e.g. gke-capg-gke-demo-mypool-aa1282e0-grp) 56 | Name string 57 | } 58 | 59 | // Parse parses a resource url. 60 | func Parse(url string) (ResourceURL, error) { 61 | if !strings.HasPrefix(url, ResourcePrefix) { 62 | return ResourceURL{}, errors.New("invalid resource url") 63 | } 64 | parts := strings.Split(url[len(ResourcePrefix):], "/") 65 | if len(parts) != NumParts { 66 | return ResourceURL{}, errors.New("invalid resource url") 67 | } 68 | return ResourceURL{ 69 | ResourceCategory: parts[ResourceCategoryIndex], 70 | Project: parts[ProjectIndex], 71 | Location: parts[LocationIndex], 72 | SubResource: parts[SubResourceIndex], 73 | Name: parts[NameIndex], 74 | }, nil 75 | } 76 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package version implements the version :). 18 | package version 19 | 20 | import ( 21 | "fmt" 22 | "runtime" 23 | ) 24 | 25 | var ( 26 | gitMajor string // major version, always numeric 27 | gitMinor string // minor version, numeric possibly followed by "+" 28 | gitVersion string // semantic version, derived by build scripts 29 | gitCommit string // sha1 from git, output of $(git rev-parse HEAD) 30 | gitTreeState string // state of git tree, either "clean" or "dirty" 31 | buildDate string // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') 32 | ) 33 | 34 | // Info contains all version-related information. 35 | type Info struct { 36 | Major string `json:"major,omitempty"` 37 | Minor string `json:"minor,omitempty"` 38 | GitVersion string `json:"gitVersion,omitempty"` 39 | GitCommit string `json:"gitCommit,omitempty"` 40 | GitTreeState string `json:"gitTreeState,omitempty"` 41 | BuildDate string `json:"buildDate,omitempty"` 42 | GoVersion string `json:"goVersion,omitempty"` 43 | Compiler string `json:"compiler,omitempty"` 44 | Platform string `json:"platform,omitempty"` 45 | } 46 | 47 | // Get returns version info initialized from defaults and the runtime environment. 48 | func Get() Info { 49 | return Info{ 50 | Major: gitMajor, 51 | Minor: gitMinor, 52 | GitVersion: gitVersion, 53 | GitCommit: gitCommit, 54 | GitTreeState: gitTreeState, 55 | BuildDate: buildDate, 56 | GoVersion: runtime.Version(), 57 | Compiler: runtime.Compiler, 58 | Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), 59 | } 60 | } 61 | 62 | // String returns version info in a human-friendly format. 63 | func (info Info) String() string { 64 | return info.GitVersion 65 | } 66 | --------------------------------------------------------------------------------