Repository: terraform-google-modules/terraform-google-github-actions-runners Branch: main Commit: 9fef9375cbd3 Files: 129 Total size: 279.1 KB Directory structure: gitextract_4sc7vs8z/ ├── .dockerignore ├── .github/ │ ├── release-please.yml │ ├── renovate.json │ ├── trusted-contribution.yml │ └── workflows/ │ ├── lint.yaml │ └── stale.yml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── build/ │ ├── int.cloudbuild.yaml │ └── lint.cloudbuild.yaml ├── docs/ │ └── upgrading_to_v4.0.md ├── examples/ │ ├── gh-org-runner-mig-native-simple/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── providers.tf │ │ └── variables.tf │ ├── gh-runner-gke-dind/ │ │ ├── .dockerignore │ │ ├── .gcloudignore │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── providers.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-gke-dind-rootless/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── providers.tf │ │ ├── values.yaml │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-gke-simple/ │ │ ├── .dockerignore │ │ ├── .gcloudignore │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── providers.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-mig-container-vm-dind/ │ │ ├── .dockerignore │ │ ├── .gcloudignore │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── cloudbuild.yaml │ │ ├── entrypoint.sh │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-mig-container-vm-simple/ │ │ ├── .dockerignore │ │ ├── .gcloudignore │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── cloudbuild.yaml │ │ ├── entrypoint.sh │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-mig-native-packer/ │ │ ├── .gcloudignore │ │ ├── README.md │ │ ├── cloudbuild.yaml │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── packer.json │ │ ├── shutdown.sh │ │ ├── startup.sh │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-mig-native-simple/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ └── oidc-simple/ │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── metadata.yaml ├── modules/ │ ├── gh-oidc/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── metadata.yaml │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-gke/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── metadata.yaml │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── gh-runner-mig-container-vm/ │ │ ├── README.md │ │ ├── main.tf │ │ ├── metadata.yaml │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ └── gh-runner-mig-vm/ │ ├── README.md │ ├── main.tf │ ├── metadata.yaml │ ├── outputs.tf │ ├── scripts/ │ │ ├── shutdown.sh │ │ └── startup.sh │ ├── variables.tf │ └── versions.tf └── test/ ├── .gitignore ├── fixtures/ │ └── gh-runner-mig-container-vm/ │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── integration/ │ ├── discover_test.go │ ├── gh-runner-gke-dind/ │ │ └── gh_runner_gke_dind_test.go │ ├── gh-runner-gke-dind-rootless/ │ │ └── gh_runner_gke_dind_rootless_test.go │ ├── gh-runner-gke-simple/ │ │ └── gh_runner_gke_simple_test.go │ ├── gh-runner-mig-container-vm/ │ │ └── gh_runner_mig_container_vm_test.go │ ├── go.mod │ ├── go.sum │ └── oidc-simple/ │ └── oidc_simple_test.go └── setup/ ├── .gitignore ├── iam.tf ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ .git .terraform .terraform.d .kitchen terraform.tfstate.d test/fixtures/*/.terraform test/fixtures/*/terraform.tfstate.d examples/.kitchen examples/*/.terraform examples/*/terraform.tfstate.d ================================================ FILE: .github/release-please.yml ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. releaseType: terraform-module handleGHRelease: true ================================================ FILE: .github/renovate.json ================================================ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["github>GoogleCloudPlatform/cloud-foundation-toolkit//infra/terraform/test-org/github/resources/renovate"] } ================================================ FILE: .github/trusted-contribution.yml ================================================ # Copyright 2023-2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # NOTE: This file is automatically generated from: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github annotations: - type: comment text: "/gcbrun" trustedContributors: - release-please[bot] - renovate[bot] - renovate-bot - forking-renovate[bot] - dependabot[bot] ================================================ FILE: .github/workflows/lint.yaml ================================================ # Copyright 2023-2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # NOTE: This file is automatically generated from values at: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf name: 'lint' on: workflow_dispatch: pull_request: types: [opened, edited, reopened, synchronize] branches: [main] permissions: contents: read concurrency: group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}' cancel-in-progress: true jobs: lint: name: 'lint' runs-on: 'ubuntu-latest' steps: - uses: 'actions/checkout@v6' - id: variables run: | MAKEFILE=$(find . -name Makefile -print -quit) if [ -z "$MAKEFILE" ]; then echo dev-tools=gcr.io/cloud-foundation-cicd/cft/developer-tools:1 >> "$GITHUB_OUTPUT" else VERSION=$(grep "DOCKER_TAG_VERSION_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) IMAGE=$(grep "DOCKER_IMAGE_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) REGISTRY=$(grep "REGISTRY_URL := " $MAKEFILE | cut -d\ -f3) echo dev-tools=${REGISTRY}/${IMAGE}:${VERSION} >> "$GITHUB_OUTPUT" fi - run: docker run --rm -v ${{ github.workspace }}:/workspace ${STEPS_VARIABLES_OUTPUTS_DEV_TOOLS} module-swapper env: STEPS_VARIABLES_OUTPUTS_DEV_TOOLS: ${{ steps.variables.outputs.dev-tools }} - run: docker run --rm -v ${{ github.workspace }}:/workspace ${STEPS_VARIABLES_OUTPUTS_DEV_TOOLS} /usr/local/bin/test_lint.sh env: STEPS_VARIABLES_OUTPUTS_DEV_TOOLS: ${{ steps.variables.outputs.dev-tools }} commitlint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup node uses: actions/setup-node@v6 with: node-version: lts/* - name: Install commitlint run: | npm install -D @commitlint/cli@20.2.0 @commitlint/config-conventional@20.2.0 echo "module.exports = { extends: ['@commitlint/config-conventional'], rules: {'subject-case': [0], 'header-max-length': [0]} };" > commitlint.config.js npx commitlint --version - name: Validate PR commits with commitlint if: github.event_name == 'pull_request' env: TITLE: ${{ github.event.pull_request.title }} run: 'echo "$TITLE" | npx commitlint --verbose' ================================================ FILE: .github/workflows/stale.yml ================================================ # Copyright 2022-2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # NOTE: This file is automatically generated from: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github name: "Close stale issues" on: schedule: - cron: "0 23 * * *" permissions: contents: read issues: write pull-requests: write actions: write jobs: stale: if: github.repository_owner == 'GoogleCloudPlatform' || github.repository_owner == 'terraform-google-modules' runs-on: ubuntu-latest steps: - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' exempt-issue-labels: 'triaged' exempt-pr-labels: 'dependencies,autorelease: pending' operations-per-run: 100 ================================================ FILE: .gitignore ================================================ # OSX leaves these everywhere on SMB shares ._* # OSX trash .DS_Store # Python *.pyc # Emacs save files *~ \#*\# .\#* # Vim-related files [._]*.s[a-w][a-z] [._]s[a-w][a-z] *.un~ Session.vim .netrwhist ### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore # Local .terraform directories **/.terraform/* # .tfstate files *.tfstate *.tfstate.* # test.out files test.out # Crash log files crash.log # Kitchen files **/inspec.lock **/.kitchen **/kitchen.local.yml **/Gemfile.lock # Ignore any .tfvars files that are generated automatically for each Terraform run. Most # .tfvars files are managed as part of configuration and so should be included in # version control. **/*.tfvars credentials.json # tf lock file .terraform.lock.hcl ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). This changelog is generated automatically based on [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). ## [5.1.0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v5.0.0...v5.1.0) (2025-09-09) ### Features * **deps:** Update Terraform Google Provider to v7 (major) ([#223](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/223)) ([411f391](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/411f39135eab709760c0fd9894f04c7cdcd9a6b4)) ## [5.0.0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v4.0.0...v5.0.0) (2025-01-10) ### ⚠ BREAKING CHANGES * **TF>=1.3:** Update Terraform ([#201](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/201)) * **deps:** Update Terraform terraform-google-modules/vm/google to v13 ([#204](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/204)) * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v35 ([#205](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/205)) * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v33 ([#183](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/183)) * **deps:** Update Terraform terraform-google-modules/vm/google to v12 ([#184](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/184)) ### Features * **deps:** Update Terraform Google Provider to v6 (major) ([#191](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/191)) ([0364375](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/0364375e2b90f407ea526df3c0bddedee1fc1bc3)) * support private GKE nodes ([#192](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/192)) ([730f92b](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/730f92b8e207cb35acbdc4c134c954f011f877d3)) ### Bug Fixes * add real attribute condition for OIDC example ([658acb0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/658acb014d06e54757e60302aa9da91c37669c13)) * constrain provider version for GKE examples to <5.44 ([658acb0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/658acb014d06e54757e60302aa9da91c37669c13)) * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v33 ([#183](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/183)) ([a47589e](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/a47589e5b10eab4d3f639fb42ccc4f0f07f8fc6f)) * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v35 ([#205](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/205)) ([35a6060](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/35a606014656d3bb7b34c4f52818084f90021d7a)) * **deps:** Update Terraform terraform-google-modules/vm/google to v12 ([#184](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/184)) ([0929277](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/09292776abe17a7f878b6d271e4b0b22b1138dca)) * **deps:** Update Terraform terraform-google-modules/vm/google to v13 ([#204](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/204)) ([de8d3f5](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/de8d3f531685bf4e340b69cccf059d99d282e621)) * reformat subnetwork secondary range block ([#187](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/187)) ([658acb0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/658acb014d06e54757e60302aa9da91c37669c13)) * set sensitive for gh-runner-gke ca_certificate output ([#196](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/196)) ([5367df3](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/5367df3f0fed5acd6dad9002a641409acd243317)) * **TF>=1.3:** Update Terraform ([#201](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/201)) ([2364424](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/236442442a61be9e7c975d80390c42be8f7f5da4)) ## [4.0.0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v3.1.2...v4.0.0) (2024-08-27) ### ⚠ BREAKING CHANGES * **deps:** Update Terraform terraform-google-modules/vm/google to v11 ([#152](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/152)) * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v32 ([#178](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/178)) * migrate to ARC ([#173](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/173)) ### Features * Add custom tags option to mig-vm-module ([#177](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/177)) ([5e1a3c6](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/5e1a3c6f44acd68d9ad160621dbd6cd8a5fe8f79)) * **deps:** Update Terraform Google Provider to v6 (major) ([#181](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/181)) ([3c94fa5](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/3c94fa50403bcf567113547ddea3d00818a350f0)) * migrate to ARC ([#173](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/173)) ([0b1299b](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/0b1299b802cafa1e331bb54b7c7dc6e7a23a1a0c)) ### Bug Fixes * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v32 ([#178](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/178)) ([999330d](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/999330dd53362a1e9f92821d858a0f13cf067594)) * **deps:** Update Terraform terraform-google-modules/vm/google to v11 ([#152](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/152)) ([42e5161](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/42e516109356cf66803d42bfea2a6df46fe8e7b4)) ## [3.1.2](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v3.1.1...v3.1.2) (2023-10-10) ### Bug Fixes * upgraded versions.tf to include minor bumps from tpg v5 ([#124](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/124)) ([ede4426](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/ede4426a9268ad50524d3b0d23cb1dbf52ab99d3)) ## [3.1.1](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v3.1.0...v3.1.1) (2022-12-29) ### Bug Fixes * **deps:** update terraform terraform-google-modules/kubernetes-engine/google to v24 ([#85](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/85)) ([980e5d5](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/980e5d50cd89ed0e84f120e0e263bd9700ffa3ca)) * fixes lint issues and generates metadata ([#89](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/89)) ([935368c](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/935368cf54df02eba97596bc21226c63bca2bf4c)) ## [3.1.0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v3.0.0...v3.1.0) (2022-07-20) ### Features * Issuer URI has been passed through variable ([#62](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/62)) ([c9da327](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/c9da3279e9af3e195f3ad089efdfb425b8e9032f)) ## [3.0.0](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v2.0.1...v3.0.0) (2022-02-02) ### ⚠ BREAKING CHANGES * update examples, bump gke module version ([#52](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/52)). `gh-runner-gke` now uses [v19](https://github.com/terraform-google-modules/terraform-google-kubernetes-engine/releases/tag/v19.0.0) of the GKE module. Please refer to the [GKE module upgrade guide](https://github.com/terraform-google-modules/terraform-google-kubernetes-engine/blob/master/docs/upgrading_to_v19.0.md) for more details. ### Features * Update TPG version constraints to allow 4.0 ([#50](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/50)) ([1aebd31](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/1aebd31f0548374ac061a58cdca7bc98e51eb760)) ### Bug Fixes * update examples, bump gke module version ([#52](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/52)) ([882578e](https://github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/882578e59bf2f5a808abd63ed5dcc74524aa30fa)) ### [2.0.1](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v2.0.0...v2.0.1) (2021-11-26) ### Bug Fixes * bump minimum provider version for gh oidc module ([#45](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/45)) ([204a546](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/204a5463a48237fbd2bf118459db7dbb7742bb8a)) ## [2.0.0](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v1.1.0...v2.0.0) (2021-11-09) ### ⚠ BREAKING CHANGES * Remove the default allowed audience in `gh-oidc` (#42) * update issuer_uri for gh provider (#36) * Support org runners, update images and autoscaling config (#34) ### Features * Add example for org runner & update shutdown script ([#37](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/37)) ([76115f9](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/76115f9587a048de26086116d6e3a3eb0ae6aa2c)) * Remove the default allowed audience in `gh-oidc` ([#42](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/42)) ([1ec0ec2](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/1ec0ec201a6a063d27fea8fd62e6a028fb9fc5e6)) * Support org runners, update images and autoscaling config ([#34](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/34)) ([280ca8a](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/280ca8a79266d00d6ec8fe84413de0d23cbdc791)) * update issuer_uri for gh provider ([#36](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/36)) ([2ca3e6c](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/2ca3e6c4ea2a9987f8c5ac6191bbe925df4dd12b)) ## [1.1.0](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v1.0.1...v1.1.0) (2021-09-20) ### Features * add gh oidc module ([#32](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/32)) ([1f10847](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/1f10847dc69246166bd68a3149d2fefb5a43bf3b)) ### [1.0.1](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v1.0.0...v1.0.1) (2021-08-17) ### Bug Fixes * Switched to use google_project_iam_member, which is non-authoritative ([#27](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/27)) ([281a737](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/281a737a59046735577178052f584c3c9749239b)) * use machine_type in mig-runner ([#30](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/30)) ([4f940f6](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/4f940f69a4bad949213250ba3b42ae905da5d2ca)) ## [1.0.0](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/compare/v0.1.0...v1.0.0) (2021-04-24) ### ⚠ BREAKING CHANGES * add Terraform 0.13 constraint and module attribution (#22) ### Features * add Terraform 0.13 constraint and module attribution ([#22](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/22)) ([11d7179](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/11d7179773abf41e1f4a101dd729edaf1773929a)) ## 0.1.0 (2020-11-24) ### Features * add network project for svpc, expose cooldown period, default scripts ([#15](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/15)) ([048156a](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/048156ae1708ccef39d36be55270048153fc8081)) * remove api enablement and update docs ([#13](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/issues/13)) ([5c01d64](https://www.github.com/terraform-google-modules/terraform-google-github-actions-runners/commit/5c01d64fdb47e84aa8bbe082f2af80669a0fcc32)) ## [0.1.0](https://github.com/terraform-google-modules/terraform-google-terraform-google-github-actions-runners/releases/tag/v0.1.0) - 20XX-YY-ZZ ### Features - Initial release [0.1.0]: https://github.com/terraform-google-modules/terraform-google-terraform-google-github-actions-runners/releases/tag/v0.1.0 ================================================ FILE: CODEOWNERS ================================================ # NOTE: This file is automatically generated from values at: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf * @terraform-google-modules/cft-admins # NOTE: GitHub CODEOWNERS locations: # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection CODEOWNERS @terraform-google-modules/cft-admins .github/CODEOWNERS @terraform-google-modules/cft-admins docs/CODEOWNERS @terraform-google-modules/cft-admins ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing This document provides guidelines for contributing to the module. ## Dependencies The following dependencies must be installed on the development system: - [Docker Engine][docker-engine] - [Google Cloud SDK][google-cloud-sdk] - [make] ## Generating Documentation for Inputs and Outputs The Inputs and Outputs tables in the READMEs of the root module, submodules, and example modules are automatically generated based on the `variables` and `outputs` of the respective modules. These tables must be refreshed if the module interfaces are changed. ### Execution Run `make generate_docs` to generate new Inputs and Outputs tables. ## Integration Testing Integration tests are used to verify the behaviour of the root module, submodules, and example modules. Additions, changes, and fixes should be accompanied with tests. The integration tests are run using [Kitchen][kitchen], [Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These tools are packaged within a Docker image for convenience. The general strategy for these tests is to verify the behaviour of the [example modules](./examples/), thus ensuring that the root module, submodules, and example modules are all functionally correct. ### Test Environment The easiest way to test the module is in an isolated test project. The setup for such a project is defined in [test/setup](./test/setup/) directory. To use this setup, you need a service account with these permissions (on a Folder or Organization): - Project Creator - Project Billing Manager The project that the service account belongs to must have the following APIs enabled (the setup won't create any resources on the service account's project): - Cloud Resource Manager - Cloud Billing - Service Usage - Identity and Access Management (IAM) Export the Service Account credentials to your environment like so: ``` export SERVICE_ACCOUNT_JSON=$(< credentials.json) ``` You will also need to set a few environment variables: ``` export TF_VAR_org_id="your_org_id" export TF_VAR_folder_id="your_folder_id" export TF_VAR_billing_account="your_billing_account_id" ``` With these settings in place, you can prepare a test project using Docker: ``` make docker_test_prepare ``` ### Noninteractive Execution Run `make docker_test_integration` to test all of the example modules noninteractively, using the prepared test project. ### Interactive Execution 1. Run `make docker_run` to start the testing Docker container in interactive mode. 1. Run `kitchen_do create ` to initialize the working directory for an example module. 1. Run `kitchen_do converge ` to apply the example module. 1. Run `kitchen_do verify ` to test the example module. 1. Run `kitchen_do destroy ` to destroy the example module state. ## Linting and Formatting Many of the files in the repository can be linted or formatted to maintain a standard of quality. ### Execution Run `make docker_test_lint`. [docker-engine]: https://www.docker.com/products/docker-engine [flake8]: http://flake8.pycqa.org/en/latest/ [gofmt]: https://golang.org/cmd/gofmt/ [google-cloud-sdk]: https://cloud.google.com/sdk/install [hadolint]: https://github.com/hadolint/hadolint [inspec]: https://inspec.io/ [kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform [kitchen]: https://kitchen.ci/ [make]: https://en.wikipedia.org/wiki/Make_(software) [shellcheck]: https://www.shellcheck.net/ [terraform-docs]: https://github.com/segmentio/terraform-docs [terraform]: https://terraform.io/ ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Please note that this file was generated from [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template). # Please make sure to contribute relevant changes upstream! # Make will use bash instead of sh SHELL := /usr/bin/env bash DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.25 DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools REGISTRY_URL := gcr.io/cloud-foundation-cicd # Enter docker container for local development .PHONY: docker_run docker_run: docker run --rm -it \ -e SERVICE_ACCOUNT_JSON \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /bin/bash # Execute prepare tests within the docker container .PHONY: docker_test_prepare docker_test_prepare: docker run --rm -it \ -e SERVICE_ACCOUNT_JSON \ -e TF_VAR_org_id \ -e TF_VAR_folder_id \ -e TF_VAR_billing_account \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /usr/local/bin/execute_with_credentials.sh prepare_environment # Clean up test environment within the docker container .PHONY: docker_test_cleanup docker_test_cleanup: docker run --rm -it \ -e SERVICE_ACCOUNT_JSON \ -e TF_VAR_org_id \ -e TF_VAR_folder_id \ -e TF_VAR_billing_account \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /usr/local/bin/execute_with_credentials.sh cleanup_environment # Execute integration tests within the docker container .PHONY: docker_test_integration docker_test_integration: docker run --rm -it \ -e SERVICE_ACCOUNT_JSON \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /usr/local/bin/test_integration.sh # Execute lint tests within the docker container .PHONY: docker_test_lint docker_test_lint: docker run --rm -it \ -e EXCLUDE_LINT_DIRS \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /usr/local/bin/test_lint.sh # Generate documentation .PHONY: docker_generate_docs docker_generate_docs: docker run --rm -it \ -v "$(CURDIR)":/workspace \ $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs' # Alias for backwards compatibility .PHONY: generate_docs generate_docs: docker_generate_docs ================================================ FILE: README.md ================================================ # terraform-google-github-actions-runners [![awesome-runners](https://img.shields.io/badge/listed%20on-awesome--runners-blue.svg)](https://github.com/jonico/awesome-runners) ## Description Using these Terraform modules you can quickly deploy self-hosted GitHub Runners for jobs in your GitHub Actions workflows ## Modules ### [Self Hosted Runners on GKE](modules/gh-runner-gke/) The `gh-runner-gke` module provisions the resources required to deploy Self Hosted Runners on GCP infrastructure using GKE. This module follows the guidance for using [Actions Runner Controller](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/quickstart-for-actions-runner-controller#installing-actions-runner-controller) provided by GitHub Examples: - [Simple Self Hosted Runners on GKE](examples/gh-runner-gke-simple/) - [Self Hosted runners on GKE that support Docker Workflows](examples/gh-runner-gke-dind/) - [Self Hosted runners on GKE that support Docker Workflows in rootless configuration](examples/gh-runner-gke-dind-rootless/) More examples of [Self Hosted Runners on GKE/Anthos](https://github.com/github-developer/self-hosted-runners-anthos). ### [Self Hosted Runners on Managed Instance Groups using VMs](modules/gh-runner-mig-vm/) The `gh-runner-mig-vm` module provisions the resources required to deploy Self Hosted Runners on GCP infrastructure using Managed Instance Groups. Examples: - [Simple Self Hosted Runner on MIG VMs](examples/gh-runner-mig-native-simple/) - [Self Hosted Runner on MIG VMs from Packer Image](examples/gh-runner-mig-native-packer/) ### [Self Hosted Runners on Managed Instance Groups using Container VMs](modules/gh-runner-mig-container-vm/) The `gh-runner-mig-container-vm` module provisions the resources required to deploy Self Hosted Runners on GCP infrastructure using Managed Instance Groups. Examples: - [Simple Self Hosted Runner on MIG Container VMs](examples/gh-runner-mig-container-vm-simple/) - [Self Hosted runners on MIG Container VMs that support Docker Workflows](examples/gh-runner-mig-container-vm-dind/) ### [GitHub OIDC](modules/gh-oidc/) This module handles the opinionated creation of infrastructure necessary to configure [Workload Identity pools](https://cloud.google.com/iam/docs/workload-identity-federation#pools) and [providers](https://cloud.google.com/iam/docs/workload-identity-federation#providers) for authenticating to GCP using GitHub Actions OIDC tokens. Examples: - [Simple Workload Identity configuration for GitHub OIDC](examples/oidc-simple/) ## Requirements These sections describe requirements for using this module. ### Software The following dependencies must be available: - [Terraform][terraform] v0.13 - [Terraform Provider for GCP][terraform-provider-gcp] ## Contributing Refer to the [contribution guidelines](./CONTRIBUTING.md) for information on contributing to this module. [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html [terraform]: https://www.terraform.io/downloads.html ## Security Disclosures Please see our [security disclosure process](./SECURITY.md). ================================================ FILE: build/int.cloudbuild.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. timeout: 3600s steps: - id: swap-module-refs name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['module-swapper'] - id: prepare name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && prepare_environment && chmod 600 /builder/home/.netrc'] env: - 'TF_VAR_org_id=$_ORG_ID' - 'TF_VAR_folder_id=$_FOLDER_ID' - 'TF_VAR_billing_account=$_BILLING_ACCOUNT' - id: init-all name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose'] waitFor: - prepare # test/fixtures/gh-runner-mig-container-vm - id: apply-gh-runner-mig-container-vm name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGHRunnerMIGContainerVM --stage apply --verbose'] waitFor: - init-all - id: verify-gh-runner-mig-container-vm name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGHRunnerMIGContainerVM --stage verify --verbose'] waitFor: - apply-gh-runner-mig-container-vm - id: destroy-gh-runner-mig-container-vm name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGHRunnerMIGContainerVM --stage destroy --verbose'] waitFor: - verify-gh-runner-mig-container-vm # TestAll/examples/gh-runner-gke-simple - id: apply-gh-runner-gke-simple name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeSimple --stage apply --verbose'] waitFor: - init-all - id: verify-gh-runner-gke-simple name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeSimple --stage verify --verbose'] waitFor: - apply-gh-runner-gke-simple - id: destroy-gh-runner-gke-simple name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeSimple --stage destroy --verbose'] waitFor: - verify-gh-runner-gke-simple # TestAll/examples/gh-runner-gke-dind - id: apply-gh-runner-gke-dind name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDind --stage apply --verbose'] waitFor: - init-all - id: verify-gh-runner-gke-dind name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDind --stage verify --verbose'] waitFor: - apply-gh-runner-gke-dind - id: destroy-gh-runner-gke-dind name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDind --stage destroy --verbose'] waitFor: - verify-gh-runner-gke-dind # TestAll/examples/gh-runner-gke-dind-rootless - id: apply-gh-runner-gke-dind-rootless name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDindRootless --stage apply --verbose'] waitFor: - init-all - id: verify-gh-runner-gke-dind-rootless name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDindRootless --stage verify --verbose'] waitFor: - apply-gh-runner-gke-dind-rootless - id: destroy-gh-runner-gke-dind-rootless name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestGhRunnerGkeDindRootless --stage destroy --verbose'] waitFor: - verify-gh-runner-gke-dind-rootless # examples/oidc-simple - id: apply-oidc name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestOIDCSimple --stage apply --verbose'] waitFor: - init-all - id: verify-oidc name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestOIDCSimple --stage verify --verbose'] waitFor: - apply-oidc - id: destroy-oidc name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestOIDCSimple --stage destroy --verbose'] waitFor: - verify-oidc tags: - 'ci' - 'integration' substitutions: _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.25' ================================================ FILE: build/lint.cloudbuild.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. steps: - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' id: 'lint' args: ['/usr/local/bin/test_lint.sh'] tags: - 'ci' - 'lint' substitutions: _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.25' ================================================ FILE: docs/upgrading_to_v4.0.md ================================================ # Upgrading to v4.0 The v4.0 release of the `gh-runner-gke` module contains breaking changes. ## Migration Instructions ### `gh-runner-gke` module ```diff module "runner-gke" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-gke" - version = "~> 3.0" + version = "~> 4.0" project_id = var.project_id create_network = true + cluster_suffix = "repo" - repo_name = "repo" - repo_owner = "repo_owner" - repo_url = "repo_url" - gh_token = "gh_token" + gh_app_id = "123456" + gh_app_installation_id = "12345678" + gh_app_private_key = "sample" + gh_config_url = "https://github.com/ORGANIZATION" } ``` - Previously, the name of the created GKE cluster appended `repo_name` as a suffix. Now, the value of the suffix is set via `cluster_suffix`, as runner clusters can be created for workflows more than one GitHub repo. To prevent cluster deletion when upgrading, set the value of `cluster_suffix` to the previous value of `repo_name`. - The module now prefers authentication via GitHub App installation. Follow the instructions for [authenticating to ARC via GitHub App](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#authenticating-arc-with-a-github-app), and provide the necessary values to the module instead of the previous repo authentication values. Upgrading will destroy the previously created `runner_k8s_config` kubernetes secret, so previous GitHub Runner images may fail. - Previously, the GKE cluster service account was provided with the `roles/storage.objectViewer` role to enable pulling images from Container Registry. The module no longer requires access to Container Registry, and so IAM membership has been removed. If your cluster relies on this role, you will need to add it again manually. ================================================ FILE: examples/gh-org-runner-mig-native-simple/README.md ================================================ # Example Org Runners that support Docker Workflows ## Overview This example showcases how to use startup scripts to deploy organisation runners using the `gh-runner-mig` module. We use startup/shutdown scripts to install the runner binary, register the runner when it comes online and de-register when shut down. ## Steps to deploy this example - Step 1: Create terraform.tfvars file with the necessary values. GitHub Apps must have the `organization_self_hosted_runners` permission for organizations. Authenticated users must have admin access to the organization to use this API. You must authenticate using an access token with the admin:org scope to use this endpoint. More info can be found [here](https://developer.github.com/v3/actions/self_hosted_runners/) and [here](https://docs.github.com/en/rest/reference/actions#create-a-registration-token-for-an-organization). ```sh project_id = "your-project-id" gh_token = "your-github-token" repo_owner = "owner" ``` - Step 2: Create the infrastructure ```sh $ terraform init $ terraform plan $ terraform apply ``` - Step 3: Your runners should become active at https://github.com/owner/your-repo-name/settings/actions. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | | repo\_owner | Owner of the organisation for the Github Action | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | service\_account | Service account email for GCE | ================================================ FILE: examples/gh-org-runner-mig-native-simple/main.tf ================================================ /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner_mig" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-mig-vm" version = "~> 5.0" create_network = true project_id = var.project_id repo_owner = var.repo_owner gh_token = var.gh_token } ================================================ FILE: examples/gh-org-runner-mig-native-simple/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.runner_mig.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.runner_mig.mig_name } output "service_account" { description = "Service account email for GCE" value = module.runner_mig.service_account } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.runner_mig.mig_instance_template } ================================================ FILE: examples/gh-org-runner-mig-native-simple/providers.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" version = ">= 4.0" } google-beta = { source = "hashicorp/google-beta" version = ">= 4.0" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-org-runner-mig-native-simple/variables.tf ================================================ /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } variable "repo_owner" { type = string description = "Owner of the organisation for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } ================================================ FILE: examples/gh-runner-gke-dind/.dockerignore ================================================ .terraform *.tf* *.tfvars ================================================ FILE: examples/gh-runner-gke-dind/.gcloudignore ================================================ .terraform *.tfstate *.tf *.out sample-manifests ================================================ FILE: examples/gh-runner-gke-dind/README.md ================================================ # Self Hosted runners on GKE that support Docker Workflows ## Overview This example shows how to deploy runners that support Docker Workflows on GKE. More examples of [Self Hosted Runners on GKE/Anthos](https://github.com/github-developer/self-hosted-runners-anthos). ## Deployment 1. Follow the instructions in the [GitHub documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#authenticating-arc-with-a-github-app) to create a GitHub App for authenticating ARC 1. Gather the values for your GitHub App ID, GitHub App Installation ID, and GitHub App Private Key from the instructions linked above. 1. Substitute your values into the example [`main.tf`](main.tf). Modify any other values as needed. For a full list of available variables, refer to the [module documentation](../../modules/gh-runner-gke/). 1. Execute Terraform commands to create the required resources. ```sh terraform init terraform apply ``` 1. Your runners should become active at `https://github.com/organizations/ORGANIZATION/settings/actions/runners`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | cluster\_name | Cluster name | | location | Cluster location | | project\_id | The project in which resources are created | | service\_account | The default service account used for running nodes. | ================================================ FILE: examples/gh-runner-gke-dind/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-gke" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-gke" version = "~> 5.0" project_id = var.project_id create_network = true network_name = "runner-network-dind" subnet_name = "runner-subnet-dind" cluster_suffix = "dind" gh_app_id = "123456" gh_app_installation_id = "12345678" gh_app_private_key = "sample" gh_config_url = "https://github.com/ORGANIZATION" arc_container_mode = "dind" enable_private_nodes = true } ================================================ FILE: examples/gh-runner-gke-dind/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "service_account" { description = "The default service account used for running nodes." value = module.runner-gke.service_account } output "cluster_name" { description = "Cluster name" value = module.runner-gke.cluster_name } output "location" { description = "Cluster location" value = module.runner-gke.location } output "project_id" { value = var.project_id description = "The project in which resources are created" } ================================================ FILE: examples/gh-runner-gke-dind/providers.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************** Kubernetes provider configuration *****************************************/ data "google_client_config" "default" { } provider "kubernetes" { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) } provider "helm" { kubernetes = { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) exec = { api_version = "client.authentication.k8s.io/v1beta1" command = "gke-gcloud-auth-plugin" } } } ================================================ FILE: examples/gh-runner-gke-dind/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } ================================================ FILE: examples/gh-runner-gke-dind/versions.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.0" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-gke-dind-rootless/README.md ================================================ # Self Hosted runners on GKE that support dind-rootless ## Overview This example shows how to deploy runners that support Docker Workflows on GKE in a rootless configuration. This example is based on the instructions published in [Deploying GitHub Action Runners on GKE with dind-rootless](https://medium.com/google-cloud/github-action-runners-on-gke-with-dind-rootless-bd54e23516c9). More examples of [Self Hosted Runners on GKE/Anthos](https://github.com/github-developer/self-hosted-runners-anthos). ## Deployment 1. Follow the instructions in the [GitHub documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#authenticating-arc-with-a-github-app) to create a GitHub App for authenticating ARC 1. Gather the values for your GitHub App ID, GitHub App Installation ID, and GitHub App Private Key from the instructions linked above. 1. Substitute your values into the example [`main.tf`](main.tf). Modify any other values as needed. For a full list of available variables, refer to the [module documentation](../../modules/gh-runner-gke/). 1. Execute Terraform commands to create the required resources. ```sh terraform init terraform apply ``` 1. Your runners should become active at `https://github.com/organizations/ORGANIZATION/settings/actions/runners`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | cluster\_name | Cluster name | | location | Cluster location | | project\_id | The project in which resources are created | | service\_account | The default service account used for running nodes. | ================================================ FILE: examples/gh-runner-gke-dind-rootless/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-gke" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-gke" version = "~> 5.0" project_id = var.project_id create_network = true network_name = "runner-network-dind-r" subnet_name = "runner-subnet-dind-r" cluster_suffix = "dind-rootless" gh_app_id = "123456" gh_app_installation_id = "12345678" gh_app_private_key = "sample" gh_config_url = "https://github.com/ORGANIZATION" enable_private_nodes = true # pass values.yaml for dind-rootless runners configuratin arc_runners_values = [ file("${path.module}/values.yaml") ] } ================================================ FILE: examples/gh-runner-gke-dind-rootless/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "service_account" { description = "The default service account used for running nodes." value = module.runner-gke.service_account } output "cluster_name" { description = "Cluster name" value = module.runner-gke.cluster_name } output "location" { description = "Cluster location" value = module.runner-gke.location } output "project_id" { value = var.project_id description = "The project in which resources are created" } ================================================ FILE: examples/gh-runner-gke-dind-rootless/providers.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************** Kubernetes provider configuration *****************************************/ data "google_client_config" "default" { } provider "kubernetes" { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) } provider "helm" { kubernetes = { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) exec = { api_version = "client.authentication.k8s.io/v1beta1" command = "gke-gcloud-auth-plugin" } } } ================================================ FILE: examples/gh-runner-gke-dind-rootless/values.yaml ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ## githubConfigUrl is the GitHub url for where you want to configure runners ## ex: https://github.com/myorg/myrepo or https://github.com/myorg ## githubConfigUrl: "https://github.com/[user]/[repo]" ## Note: specified on command line outside of values.yml ## githubConfigSecret is the k8s secrets to use when auth with GitHub API. ## You can choose to use GitHub App or a PAT token ## githubConfigSecret: "my-token" ## Note: specified on command line outside of values.yml ## maxRunners is the max number of runners the autoscaling runner set will scale up to. maxRunners: 5 ## minRunners is the min number of idle runners. The target number of runners created will be ## calculated as a sum of minRunners and the number of jobs assigned to the scale set. minRunners: 0 #runnerGroup: "my-custom-runner-group" ## name of the runner scale set to create. Defaults to the helm release name runnerScaleSetName: "arc-runner-set" ## template is the PodSpec for each runner Pod ## For reference: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec template: spec: initContainers: - name: init-dind-externals image: ghcr.io/actions/actions-runner:latest command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"] volumeMounts: - name: dind-externals mountPath: /home/runner/tmpDir - name: init-dind-rootless image: docker:dind-rootless command: - sh - -c - | set -x cp -a /etc/. /dind-etc/ echo 'runner:x:1001:1001:runner:/home/runner:/bin/ash' >> /dind-etc/passwd echo 'runner:x:1001:' >> /dind-etc/group echo 'runner:100000:65536' >> /dind-etc/subgid echo 'runner:100000:65536' >> /dind-etc/subuid chmod 755 /dind-etc; chmod u=rwx,g=rx+s,o=rx /dind-home chown 1001:1001 /dind-home securityContext: runAsUser: 0 volumeMounts: - mountPath: /dind-etc name: dind-etc - mountPath: /dind-home name: dind-home containers: - name: runner image: ghcr.io/actions/actions-runner:latest command: ["/home/runner/run.sh"] env: - name: DOCKER_HOST value: unix:///home/runner/var/run/docker.sock securityContext: privileged: true runAsUser: 1001 runAsGroup: 1001 volumeMounts: - name: work mountPath: /home/runner/_work - name: dind-sock mountPath: /home/runner/var/run - name: dind image: docker:dind-rootless args: ["dockerd", "--host=unix:///home/runner/var/run/docker.sock"] securityContext: privileged: true runAsUser: 1001 runAsGroup: 1001 volumeMounts: - name: work mountPath: /home/runner/_work - name: dind-sock mountPath: /home/runner/var/run - name: dind-externals mountPath: /home/runner/externals - name: dind-etc mountPath: /etc - name: dind-home mountPath: /home/runner volumes: - name: work emptyDir: {} - name: dind-externals emptyDir: {} - name: dind-sock emptyDir: {} - name: dind-etc emptyDir: {} - name: dind-home emptyDir: {} ================================================ FILE: examples/gh-runner-gke-dind-rootless/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } ================================================ FILE: examples/gh-runner-gke-dind-rootless/versions.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.0" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-gke-simple/.dockerignore ================================================ .terraform *.tf* *.tfvars ================================================ FILE: examples/gh-runner-gke-simple/.gcloudignore ================================================ .terraform *.tfstate *.tf *.out sample-manifests ================================================ FILE: examples/gh-runner-gke-simple/README.md ================================================ # Simple Self Hosted runners on GKE ## Overview This example shows how to deploy ARC runners on GKE. More examples of [Self Hosted Runners on GKE/Anthos](https://github.com/github-developer/self-hosted-runners-anthos). ## Deployment 1. Follow the instructions in the [GitHub documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#authenticating-arc-with-a-github-app) to create a GitHub App for authenticating ARC 1. Gather the values for your GitHub App ID, GitHub App Installation ID, and GitHub App Private Key from the instructions linked above. 1. Substitute your values into the example [`main.tf`](main.tf). Modify any other values as needed. For a full list of available variables, refer to the [module documentation](../../modules/gh-runner-gke/). 1. Execute Terraform commands to create the required resources. ```sh terraform init terraform apply ``` 1. Your runners should become active at `https://github.com/organizations/ORGANIZATION/settings/actions/runners`. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | cluster\_name | Cluster name | | location | Cluster location | | network\_name | Name of VPC | | project\_id | The project in which resources are created | | service\_account | The default service account used for running nodes. | | subnet\_name | Name of VPC | ================================================ FILE: examples/gh-runner-gke-simple/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-gke" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-gke" version = "~> 5.0" project_id = var.project_id create_network = true cluster_suffix = "k8s" gh_app_id = "123456" gh_app_installation_id = "12345678" gh_app_private_key = "sample" gh_config_url = "https://github.com/ORGANIZATION" } ================================================ FILE: examples/gh-runner-gke-simple/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "service_account" { description = "The default service account used for running nodes." value = module.runner-gke.service_account } output "cluster_name" { description = "Cluster name" value = module.runner-gke.cluster_name } output "network_name" { description = "Name of VPC" value = module.runner-gke.network_name } output "subnet_name" { description = "Name of VPC" value = module.runner-gke.subnet_name } output "location" { description = "Cluster location" value = module.runner-gke.location } output "project_id" { value = var.project_id description = "The project in which resources are created" } ================================================ FILE: examples/gh-runner-gke-simple/providers.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************** Kubernetes provider configuration *****************************************/ data "google_client_config" "default" { } provider "kubernetes" { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) } provider "helm" { kubernetes = { host = "https://${module.runner-gke.kubernetes_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.runner-gke.ca_certificate) exec = { api_version = "client.authentication.k8s.io/v1beta1" command = "gke-gcloud-auth-plugin" } } } ================================================ FILE: examples/gh-runner-gke-simple/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } ================================================ FILE: examples/gh-runner-gke-simple/versions.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.0" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-mig-container-vm-dind/.dockerignore ================================================ .terraform *.tf* *.tfvars ================================================ FILE: examples/gh-runner-mig-container-vm-dind/.gcloudignore ================================================ .terraform *.tfstate *.tf *.out ================================================ FILE: examples/gh-runner-mig-container-vm-dind/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Download and verify the integrity of the download first FROM ubuntu:24.04 RUN apt-get update && \ apt-get -y install apt-transport-https \ ca-certificates \ curl \ tar \ jq \ build-essential \ gnupg2 \ iputils-ping \ software-properties-common RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" && \ apt-get update && \ apt-get -y install docker-ce ARG GH_RUNNER_VERSION="2.169.0" WORKDIR /runner RUN curl -o actions.tar.gz --location "https://github.com/actions/runner/releases/download/v${GH_RUNNER_VERSION}/actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz" && \ tar -zxf actions.tar.gz && \ rm -f actions.tar.gz && \ ./bin/installdependencies.sh COPY entrypoint.sh . ENV RUNNER_ALLOW_RUNASROOT=1 RUN chmod +x entrypoint.sh ENTRYPOINT ["/runner/entrypoint.sh"] ================================================ FILE: examples/gh-runner-mig-container-vm-dind/README.md ================================================ # Example Runners on MIG Container VM that support Docker Workflows ## Overview This example shows how to deploy a runner that supports Docker Workflows on GCE Container VM. ## Steps to deploy this example - Step 1: Build the example runner image using Google Cloud Build. Alternatively, you can also use a prebuilt image or build using a local docker daemon. ```sh $ gcloud config set project $PROJECT_ID $ gcloud services enable containerregistry.googleapis.com cloudbuild.googleapis.com $ gcloud builds submit --config=cloudbuild.yaml ``` - Step 2: Create terraform.tfvars file with the necessary values. Access tokens require repo scope for private repos and public_repo scope for public repos. GitHub Apps must have the administration permission to use this API. Authenticated users must have admin access to the repository to use this API. More info can be found [here](https://developer.github.com/v3/actions/self_hosted_runners/). ```tf project_id = "your-project-id" image = "your-image-registry/image:tag" gh_token = "your-github-token" repo_url = "https://github.com/owner/your-repo-name" repo_name = "your-repo-name" repo_owner = "owner" ``` - Step 3: Create the infrastructure. ```sh $ terraform init $ terraform plan $ terraform apply ``` - Step 4: Your runners should become active at https://github.com/owner/your-repo-name/settings/actions. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | image | The github runner image | `string` | n/a | yes | | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | | repo\_name | Name of the repo for the Github Action | `string` | n/a | yes | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | | repo\_url | Repo URL for the Github Action | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_name | The name of the MIG | ================================================ FILE: examples/gh-runner-mig-container-vm-dind/cloudbuild.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. steps: - name: "gcr.io/cloud-builders/docker" args: [ "build", "-t", "gcr.io/$PROJECT_ID/runner:latest", "-t", "gcr.io/$PROJECT_ID/runner:0.1", ".", ] images: - "gcr.io/$PROJECT_ID/runner" ================================================ FILE: examples/gh-runner-mig-container-vm-dind/entrypoint.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #remove runner on stop signal remove_runner() { /runner/config.sh remove --unattended --token "$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/remove-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header "content-type: application/json" | jq -r .token)" exit 0 } #Trap SIGTERM trap 'remove_runner' SIGTERM #Trap SIGINT trap 'remove_runner' SIGINT # shellcheck disable=SC2034 #ACTIONS_RUNNER_INPUT_NAME is read by config.sh #set name for this runner as the hostname ACTIONS_RUNNER_INPUT_NAME=$HOSTNAME #get regsistration token for this runnner ACTIONS_RUNNER_INPUT_TOKEN="$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/registration-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header 'content-type: application/json' | jq -r .token)" #configure runner /runner/config.sh --unattended --replace --work "/tmp" --url "$ACTIONS_RUNNER_INPUT_URL" --token "$ACTIONS_RUNNER_INPUT_TOKEN" #start runner #https://github.com/actions/runner/issues/246#issuecomment-615293718 /runner/bin/runsvc.sh & wait $! ================================================ FILE: examples/gh-runner-mig-container-vm-dind/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-mig-dind" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-mig-container-vm" version = "~> 5.0" create_network = true project_id = var.project_id image = var.image repo_name = var.repo_name repo_url = var.repo_url repo_owner = var.repo_owner gh_token = var.gh_token dind = true } ================================================ FILE: examples/gh-runner-mig-container-vm-dind/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.runner-mig-dind.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.runner-mig-dind.mig_name } ================================================ FILE: examples/gh-runner-mig-container-vm-dind/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } variable "image" { type = string description = "The github runner image" } variable "repo_url" { type = string description = "Repo URL for the Github Action" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } ================================================ FILE: examples/gh-runner-mig-container-vm-dind/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-mig-container-vm-simple/.dockerignore ================================================ .terraform *.tf* *.tfvars ================================================ FILE: examples/gh-runner-mig-container-vm-simple/.gcloudignore ================================================ .terraform *.tfstate *.tf *.out ================================================ FILE: examples/gh-runner-mig-container-vm-simple/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Download and verify the integrity of the download first FROM ubuntu:24.04 RUN apt-get update && \ apt-get -y install curl \ iputils-ping \ tar \ jq ARG GH_RUNNER_VERSION="2.169.0" WORKDIR /runner RUN curl -o actions.tar.gz --location "https://github.com/actions/runner/releases/download/v${GH_RUNNER_VERSION}/actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz" && \ tar -zxf actions.tar.gz && \ rm -f actions.tar.gz && \ ./bin/installdependencies.sh COPY entrypoint.sh . RUN chmod +x entrypoint.sh RUN useradd ghrunner && chown -R ghrunner: /runner USER ghrunner ENTRYPOINT ["/runner/entrypoint.sh"] ================================================ FILE: examples/gh-runner-mig-container-vm-simple/README.md ================================================ # Example Runners on MIG Container VM ## Overview This example shows how to deploy a runner on GCE Container VM. ## Steps to deploy this example - Step 1: Build the example runner image using Google Cloud Build. Alternatively, you can also use a prebuilt image or build using a local docker daemon. ```sh $ gcloud config set project $PROJECT_ID $ gcloud services enable containerregistry.googleapis.com cloudbuild.googleapis.com $ gcloud builds submit --config=cloudbuild.yaml ``` - Step 2: Create terraform.tfvars file with the necessary values. Access tokens require repo scope for private repos and public_repo scope for public repos. GitHub Apps must have the administration permission to use this API. Authenticated users must have admin access to the repository to use this API. More info can be found [here](https://developer.github.com/v3/actions/self_hosted_runners/). ```tf project_id = "your-project-id" image = "your-image-registry/image:tag" gh_token = "your-github-token" repo_url = "https://github.com/owner/your-repo-name" repo_name = "your-repo-name" repo_owner = "owner" ``` - Step 3: Create the infrastructure. ```sh $ terraform init $ terraform plan $ terraform apply ``` - Step 4: Your runners should become active at https://github.com/owner/your-repo-name/settings/actions. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | image | The github runner image | `string` | n/a | yes | | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | | repo\_name | Name of the repo for the Github Action | `string` | n/a | yes | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | | repo\_url | Repo URL for the Github Action | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | service\_account | Service account email for GCE | ================================================ FILE: examples/gh-runner-mig-container-vm-simple/cloudbuild.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. steps: - name: "gcr.io/cloud-builders/docker" args: [ "build", "-t", "gcr.io/$PROJECT_ID/runner:latest", "-t", "gcr.io/$PROJECT_ID/runner:0.1", ".", ] images: - "gcr.io/$PROJECT_ID/runner" ================================================ FILE: examples/gh-runner-mig-container-vm-simple/entrypoint.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #remove runner on stop signal remove_runner() { /runner/config.sh remove --unattended --token "$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/remove-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header "content-type: application/json" | jq -r .token)" exit 0 } #Trap SIGTERM trap 'remove_runner' SIGTERM #Trap SIGINT trap 'remove_runner' SIGINT #set name for this runner as the hostname # shellcheck disable=SC2034 # ACTIONS_RUNNER_INPUT_NAME is used by config.sh ACTIONS_RUNNER_INPUT_NAME=$HOSTNAME #get regsistration token for this runnner ACTIONS_RUNNER_INPUT_TOKEN="$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/registration-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header 'content-type: application/json' | jq -r .token)" #configure runner /runner/config.sh --unattended --work "/tmp" --url "$ACTIONS_RUNNER_INPUT_URL" --token "$ACTIONS_RUNNER_INPUT_TOKEN" #start runner #https://github.com/actions/runner/issues/246#issuecomment-615293718 /runner/bin/runsvc.sh & wait $! ================================================ FILE: examples/gh-runner-mig-container-vm-simple/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-mig" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-mig-container-vm" version = "~> 5.0" create_network = true project_id = var.project_id image = var.image repo_name = var.repo_name repo_owner = var.repo_owner repo_url = var.repo_url gh_token = var.gh_token } ================================================ FILE: examples/gh-runner-mig-container-vm-simple/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.runner-mig.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.runner-mig.mig_name } output "service_account" { description = "Service account email for GCE" value = module.runner-mig.service_account } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.runner-mig.mig_instance_template } ================================================ FILE: examples/gh-runner-mig-container-vm-simple/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } variable "image" { type = string description = "The github runner image" } variable "repo_url" { type = string description = "Repo URL for the Github Action" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } ================================================ FILE: examples/gh-runner-mig-container-vm-simple/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-mig-native-packer/.gcloudignore ================================================ .terraform *.tfstate *.tf *.out ================================================ FILE: examples/gh-runner-mig-native-packer/README.md ================================================ # Example Runners that support Docker Workflows ## Overview This example showcases how to use Packer to pre-bake a Google VM Image with the necessary toolchain including Github Actions Runner and deploy this image using the `gh-runner-mig` module. We use startup/shutdown scripts to register the runner when it comes online and de-register when it is shut down. In this example, Packer creates a VM image that has the following: - curl - jq - Docker - Github Actions Runner ## Steps to deploy this example - Step 1: Enable APIs necessary to build an GCE VM image using Packer and Google Cloud Build. ```sh $ gcloud config set project $PROJECT_ID $ gcloud services enable compute.googleapis.com cloudbuild.googleapis.com ``` - Step 2: Give Cloud Build Service Account necessary permissions to create a new GCE VM Image using Packer. ```sh $ CLOUD_BUILD_ACCOUNT=$(gcloud projects get-iam-policy $PROJECT_ID --filter="(bindings.role:roles/cloudbuild.builds.builder)" --flatten="bindings[].members" --format="value(bindings.members[])") $ gcloud projects add-iam-policy-binding $PROJECT_ID --member $CLOUD_BUILD_ACCOUNT --role roles/compute.instanceAdmin.v1 $ gcloud projects add-iam-policy-binding $PROJECT_ID --member $CLOUD_BUILD_ACCOUNT --role roles/iam.serviceAccountUser ``` - Step 3: Build GCE VM image. When the build finishes, the image id of the form `gh-actions-image-*` will be displayed. We will use this in the tfvars we create in step 4. ```sh $ gcloud builds submit --config=cloudbuild.yaml ``` - Step 4: Create terraform.tfvars file with the necessary values. Access tokens require repo scope for private repos and public_repo scope for public repos. GitHub Apps must have the administration permission to use this API. Authenticated users must have admin access to the repository to use this API. More info can be found [here](https://developer.github.com/v3/actions/self_hosted_runners/) ```tf project_id = "your-project-id" source_image = "image-id-from-step-3" gh_token = "your-github-token" repo_url = "https://github.com/owner/your-repo-name" repo_name = "your-repo-name" repo_owner = "owner" ``` - Step 5: Create the infrastructure ```sh $ terraform init $ terraform plan $ terraform apply ``` - Step 4: Your runners should become active at https://github.com/owner/your-repo-name/settings/actions. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | | repo\_name | Name of the repo for the Github Action | `string` | n/a | yes | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | | source\_image | Source disk image | `string` | n/a | yes | | source\_image\_project | Project where the source image comes from | `string` | `null` | no | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | service\_account | Service account email for GCE | ================================================ FILE: examples/gh-runner-mig-native-packer/cloudbuild.yaml ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. steps: - name: "hashicorp/packer:1.14.1" args: - build - -var - project_id=$PROJECT_ID - packer.json ================================================ FILE: examples/gh-runner-mig-native-packer/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-mig" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-mig-vm" version = "~> 5.0" create_network = true project_id = var.project_id repo_name = var.repo_name repo_owner = var.repo_owner gh_token = var.gh_token startup_script = file("${path.cwd}/startup.sh") shutdown_script = file("${path.cwd}/shutdown.sh") source_image_project = var.source_image_project != null ? var.source_image_project : var.project_id source_image = var.source_image } ================================================ FILE: examples/gh-runner-mig-native-packer/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.runner-mig.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.runner-mig.mig_name } output "service_account" { description = "Service account email for GCE" value = module.runner-mig.service_account } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.runner-mig.mig_instance_template } ================================================ FILE: examples/gh-runner-mig-native-packer/packer.json ================================================ { "variables": { "source_image_family": "ubuntu-1804-lts", "source_image_project_id": "ubuntu-os-cloud", "machine_type": "n1-standard-4", "disk_size": "50", "disk_type": "pd-ssd", "image_name": "gh-actions-image-{{timestamp}}", "image_family": "gh-actions-image", "ssh_username": "ubuntu", "region": "us-central1", "zone": "us-central1-a", "project_id": "{{env `PACKER_PROJECT_ID`}}", "gh_runner_version": "2.168.0" }, "builders": [ { "type": "googlecompute", "project_id": "{{user `project_id`}}", "source_image_family": "{{user `source_image_family`}}", "source_image_project_id": "{{user `source_image_project_id`}}", "zone": "{{user `zone`}}", "machine_type": "{{user `machine_type`}}", "disk_size": "{{user `disk_size`}}", "ssh_username": "{{user `ssh_username`}}", "image_name": "{{user `image_name`}}", "image_family": "{{user `source_image_family`}}", "disable_default_service_account": false, "metadata": { "enable-oslogin": "true", "new_nodes_topic": "new-instances-0001" } } ], "provisioners": [ { "type": "shell", "environment_vars": ["DEBIAN_FRONTEND=noninteractive"], "inline": [ "apt-get update", "apt-get dist-upgrade -y", "apt-get install -y apt-transport-https ca-certificates curl tar jq build-essential gnupg2 software-properties-common", "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -", "add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"", "apt-get update", "apt-get install -y docker-ce", "usermod -aG docker ubuntu" ], "execute_command": "sudo -S sh -c '{{ .Vars }} {{ .Path }}'" }, { "type": "shell", "environment_vars": ["DEBIAN_FRONTEND=noninteractive"], "inline": [ "curl -o actions.tar.gz --location \"https://github.com/actions/runner/releases/download/v{{user `gh_runner_version`}}/actions-runner-linux-x64-{{user `gh_runner_version`}}.tar.gz\"", "mkdir /runner", "mkdir /runner-tmp", "tar -zxf actions.tar.gz --directory /runner", "rm -f actions.tar.gz", "/runner/bin/installdependencies.sh" ], "execute_command": "sudo -S sh -c '{{ .Vars }} {{ .Path }}'" } ] } ================================================ FILE: examples/gh-runner-mig-native-packer/shutdown.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. secretUri=$(curl -sS "http://metadata.google.internal/computeMetadata/v1/instance/attributes/secret-id" -H "Metadata-Flavor: Google") #secrets URI is of the form projects/$PROJECT_NUMBER/secrets/$SECRET_NAME/versions/$SECRET_VERSION #split into array based on `/` delimeter IFS="/" read -r -a secretsConfig <<< "$secretUri" #get SECRET_NAME and SECRET_VERSION SECRET_NAME=${secretsConfig[3]} SECRET_VERSION=${secretsConfig[5]} #access secret from secretsmanager secrets=$(gcloud secrets versions access "$SECRET_VERSION" --secret="$SECRET_NAME") #set secrets as env vars # shellcheck disable=SC2046 # we want to use wordsplitting export $(echo "$secrets" | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") #stop and uninstall the runner service cd /runner || exit ./svc.sh stop ./svc.sh uninstall #remove the runner configuration RUNNER_ALLOW_RUNASROOT=1 /runner/config.sh remove --unattended --token "$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/remove-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header "content-type: application/json" | jq -r .token)" ================================================ FILE: examples/gh-runner-mig-native-packer/startup.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. secretUri=$(curl -sS "http://metadata.google.internal/computeMetadata/v1/instance/attributes/secret-id" -H "Metadata-Flavor: Google") #secrets URI is of the form projects/$PROJECT_NUMBER/secrets/$SECRET_NAME/versions/$SECRET_VERSION #split into array based on `/` delimeter IFS="/" read -r -a secretsConfig <<< "$secretUri" #get SECRET_NAME and SECRET_VERSION SECRET_NAME=${secretsConfig[3]} SECRET_VERSION=${secretsConfig[5]} #access secret from secretsmanager secrets=$(gcloud secrets versions access "$SECRET_VERSION" --secret="$SECRET_NAME") #set secrets as env vars # shellcheck disable=SC2046 # we want to use wordsplitting export $(echo "$secrets" | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") #get actions token # shellcheck disable=SC2034 # ACTIONS_RUNNER_INPUT_NAME is used by config.sh ACTIONS_RUNNER_INPUT_NAME=$HOSTNAME ACTIONS_RUNNER_INPUT_TOKEN="$(curl -sS --request POST --url "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/registration-token" --header "authorization: Bearer ${GITHUB_TOKEN}" --header 'content-type: application/json' | jq -r .token)" #configure runner RUNNER_ALLOW_RUNASROOT=1 /runner/config.sh --unattended --replace --work "/runner-tmp" --url "$REPO_URL" --token "$ACTIONS_RUNNER_INPUT_TOKEN" #install and start runner service cd /runner || exit ./svc.sh install ./svc.sh start ================================================ FILE: examples/gh-runner-mig-native-packer/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } variable "source_image_project" { type = string description = "Project where the source image comes from" default = null } variable "source_image" { type = string description = "Source disk image" } ================================================ FILE: examples/gh-runner-mig-native-packer/versions.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } } required_version = ">= 0.13" } ================================================ FILE: examples/gh-runner-mig-native-simple/README.md ================================================ # Example Runners that support Docker Workflows ## Overview This example showcases how to use startup scripts to deploy runners using the `gh-runner-mig` module. We use startup/shutdown scripts to install the runner binary, register the runner when it comes online and de-register when shut down. ## Steps to deploy this example - Step 1: Create terraform.tfvars file with the necessary values. Access tokens require repo scope for private repos and public_repo scope for public repos. GitHub Apps must have the administration permission to use this API. Authenticated users must have admin access to the repository to use this API. More info can be found [here](https://developer.github.com/v3/actions/self_hosted_runners/). ```sh project_id = "your-project-id" gh_token = "your-github-token" repo_name = "your-repo-name" repo_owner = "owner" ``` - Step 2: Create the infrastructure ```sh $ terraform init $ terraform plan $ terraform apply ``` - Step 3: Your runners should become active at https://github.com/owner/your-repo-name/settings/actions. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | project\_id | The project id to deploy Github Runner MIG | `string` | n/a | yes | | repo\_name | Name of the repo for the Github Action | `string` | n/a | yes | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | service\_account | Service account email for GCE | ================================================ FILE: examples/gh-runner-mig-native-simple/main.tf ================================================ /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "runner-mig" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-mig-vm" version = "~> 5.0" create_network = true project_id = var.project_id repo_name = var.repo_name repo_owner = var.repo_owner gh_token = var.gh_token } ================================================ FILE: examples/gh-runner-mig-native-simple/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.runner-mig.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.runner-mig.mig_name } output "service_account" { description = "Service account email for GCE" value = module.runner-mig.service_account } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.runner-mig.mig_instance_template } ================================================ FILE: examples/gh-runner-mig-native-simple/variables.tf ================================================ /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner MIG" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } ================================================ FILE: examples/gh-runner-mig-native-simple/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } } required_version = ">= 0.13" } ================================================ FILE: examples/oidc-simple/README.md ================================================ # OIDC Simple Example ## Overview This example showcases how to configure [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) using the [gh-oidc module](../../modules/gh-oidc/README.md) for a sample Service Account. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | project\_id | The project id to create WIF pool and example SA | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | pool\_name | Pool name | | provider\_name | Provider name | | sa\_email | Example SA email | ================================================ FILE: examples/oidc-simple/main.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ resource "google_service_account" "sa" { project = var.project_id account_id = "test-storage-sa" } resource "google_project_iam_member" "project" { project = var.project_id role = "roles/storage.admin" member = "serviceAccount:${google_service_account.sa.email}" } module "oidc" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-oidc" version = "~> 5.0" project_id = var.project_id pool_id = "example-pool" provider_id = "example-gh-provider" attribute_condition = "assertion.repository_owner_id=='1342004'" sa_mapping = { (google_service_account.sa.account_id) = { sa_name = google_service_account.sa.name attribute = "attribute.repository/user/repo" } } } ================================================ FILE: examples/oidc-simple/outputs.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "pool_name" { description = "Pool name" value = module.oidc.pool_name } output "provider_name" { description = "Provider name" value = module.oidc.provider_name } output "sa_email" { description = "Example SA email" value = google_service_account.sa.email } ================================================ FILE: examples/oidc-simple/variables.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to create WIF pool and example SA" } ================================================ FILE: examples/oidc-simple/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_providers { google = { source = "hashicorp/google" } google-beta = { source = "hashicorp/google-beta" } } required_version = ">= 0.13" } ================================================ FILE: metadata.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: name: terraform-google-github-actions-runners annotations: config.kubernetes.io/local-config: "true" spec: title: terraform-google-github-actions-runners source: repo: https://github.com/terraform-google-modules/terraform-google-github-actions-runners sourceType: git subBlueprints: - name: gh-oidc location: modules/gh-oidc - name: gh-runner-gke location: modules/gh-runner-gke - name: gh-runner-mig-container-vm location: modules/gh-runner-mig-container-vm - name: gh-runner-mig-vm location: modules/gh-runner-mig-vm examples: - name: gh-org-runner-mig-native-simple location: examples/gh-org-runner-mig-native-simple - name: gh-runner-gke-dind location: examples/gh-runner-gke-dind - name: gh-runner-gke-simple location: examples/gh-runner-gke-simple - name: gh-runner-mig-container-vm-dind location: examples/gh-runner-mig-container-vm-dind - name: gh-runner-mig-container-vm-simple location: examples/gh-runner-mig-container-vm-simple - name: gh-runner-mig-native-packer location: examples/gh-runner-mig-native-packer - name: gh-runner-mig-native-simple location: examples/gh-runner-mig-native-simple - name: oidc-simple location: examples/oidc-simple roles: - level: Project roles: - roles/owner services: - cloudresourcemanager.googleapis.com - storage-api.googleapis.com - iam.googleapis.com - container.googleapis.com - serviceusage.googleapis.com ================================================ FILE: modules/gh-oidc/README.md ================================================ ## GitHub OIDC This module handles the opinionated creation of infrastructure necessary to configure [Workload Identity pools](https://cloud.google.com/iam/docs/workload-identity-federation#pools) and [providers](https://cloud.google.com/iam/docs/workload-identity-federation#providers) for authenticating to GCP using GitHub Actions OIDC tokens. This includes: - Creation of a Workload Identity pool - Configuring a Workload Identity provider - Granting external identities necessary IAM roles on Service Accounts ### Example Usage ```terraform module "gh_oidc" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-oidc" project_id = var.project_id pool_id = "example-pool" provider_id = "example-gh-provider" sa_mapping = { "foo-service-account" = { sa_name = "projects/my-project/serviceAccounts/foo-service-account@my-project.iam.gserviceaccount.com" attribute = "attribute.repository/${USER/ORG}/" } } } ``` Below are some examples: ### [OIDC Simple](../../examples/oidc-simple/README.md) This example shows how to use this module along with a Service Account to access storage buckets. ### GitHub Workflow Once provisioned, you can use the [google-github-actions/auth](https://github.com/google-github-actions/auth) Action in a workflow as shown below ```yaml # Example workflow # .github/workflows/example.yml name: 'example oidc' on: push: branches: - 'main' jobs: run: name: 'example to list bucket contents' permissions: id-token: write contents: read runs-on: 'ubuntu-latest' steps: - id: 'auth' uses: 'google-github-actions/auth@v1' with: token_format: 'access_token' workload_identity_provider: ${{ secrets.PROVIDER_NAME }} # this is the output provider_name from the TF module service_account: ${{ secrets.SA_EMAIL }} # this is a SA email configured using the TF module with access to YOUR-GCS-BUCKET - id: 'list-buckets-contents' run: |- curl -sSf https://storage.googleapis.com/storage/v1/b/YOUR-GCS-BUCKET/o \ --header "Authorization: Bearer ${{ steps.auth.outputs.access_token }}" ``` ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | allowed\_audiences | Workload Identity Pool Provider allowed audiences. | `list(string)` | `[]` | no | | attribute\_condition | Workload Identity Pool Provider attribute condition expression. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_condition) | `string` | `null` | no | | attribute\_mapping | Workload Identity Pool Provider attribute mapping. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_mapping) | `map(any)` |
{
"attribute.actor": "assertion.actor",
"attribute.aud": "assertion.aud",
"attribute.repository": "assertion.repository",
"google.subject": "assertion.sub"
}
| no | | issuer\_uri | Workload Identity Pool Issuer URL | `string` | `"https://token.actions.githubusercontent.com"` | no | | pool\_description | Workload Identity Pool description | `string` | `"Workload Identity Pool managed by Terraform"` | no | | pool\_display\_name | Workload Identity Pool display name | `string` | `null` | no | | pool\_id | Workload Identity Pool ID | `string` | n/a | yes | | project\_id | The project id to create Workload Identity Pool | `string` | n/a | yes | | provider\_description | Workload Identity Pool Provider description | `string` | `"Workload Identity Pool Provider managed by Terraform"` | no | | provider\_display\_name | Workload Identity Pool Provider display name | `string` | `null` | no | | provider\_id | Workload Identity Pool Provider id | `string` | n/a | yes | | sa\_mapping | Service Account resource names and corresponding WIF provider attributes. If attribute is set to `*` all identities in the pool are granted access to SAs. |
map(object({
sa_name = string
attribute = string
}))
| `{}` | no | ## Outputs | Name | Description | |------|-------------| | pool\_name | Pool name | | provider\_name | Provider name | ## Requirements Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 1. Required APIs are activated ``` "iam.googleapis.com", "cloudresourcemanager.googleapis.com", "iamcredentials.googleapis.com", "sts.googleapis.com", ``` 1. Service Account used to deploy this module has the following roles ``` roles/iam.workloadIdentityPoolAdmin roles/iam.serviceAccountAdmin ``` ================================================ FILE: modules/gh-oidc/main.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ resource "google_iam_workload_identity_pool" "main" { provider = google-beta project = var.project_id workload_identity_pool_id = var.pool_id display_name = var.pool_display_name description = var.pool_description disabled = false } resource "google_iam_workload_identity_pool_provider" "main" { provider = google-beta project = var.project_id workload_identity_pool_id = google_iam_workload_identity_pool.main.workload_identity_pool_id workload_identity_pool_provider_id = var.provider_id display_name = var.provider_display_name description = var.provider_description attribute_condition = var.attribute_condition attribute_mapping = var.attribute_mapping oidc { allowed_audiences = var.allowed_audiences issuer_uri = var.issuer_uri } } resource "google_service_account_iam_member" "wif-sa" { for_each = var.sa_mapping service_account_id = each.value.sa_name role = "roles/iam.workloadIdentityUser" member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.main.name}/${each.value.attribute}" } ================================================ FILE: modules/gh-oidc/metadata.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: name: terraform-google-github-actions-runners annotations: config.kubernetes.io/local-config: "true" spec: title: "" source: repo: https://github.com/terraform-google-modules/terraform-google-github-actions-runners sourceType: git version: 5.1.0 actuationTool: type: Terraform version: '>= 0.13' examples: - name: gh-org-runner-mig-native-simple location: examples/gh-org-runner-mig-native-simple - name: gh-runner-gke-dind location: examples/gh-runner-gke-dind - name: gh-runner-gke-simple location: examples/gh-runner-gke-simple - name: gh-runner-mig-container-vm-dind location: examples/gh-runner-mig-container-vm-dind - name: gh-runner-mig-container-vm-simple location: examples/gh-runner-mig-container-vm-simple - name: gh-runner-mig-native-packer location: examples/gh-runner-mig-native-packer - name: gh-runner-mig-native-simple location: examples/gh-runner-mig-native-simple - name: oidc-simple location: examples/oidc-simple variables: - name: allowed_audiences description: Workload Identity Pool Provider allowed audiences. type: list(string) default: [] required: false - name: attribute_condition description: Workload Identity Pool Provider attribute condition expression. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_condition) type: string required: false - name: attribute_mapping description: Workload Identity Pool Provider attribute mapping. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_mapping) type: map(any) default: attribute.actor: assertion.actor attribute.aud: assertion.aud attribute.repository: assertion.repository google.subject: assertion.sub required: false - name: issuer_uri description: Workload Identity Pool Issuer URL type: string default: https://token.actions.githubusercontent.com required: false - name: pool_description description: Workload Identity Pool description type: string default: Workload Identity Pool managed by Terraform required: false - name: pool_display_name description: Workload Identity Pool display name type: string required: false - name: pool_id description: Workload Identity Pool ID type: string required: true - name: project_id description: The project id to create Workload Identity Pool type: string required: true - name: provider_description description: Workload Identity Pool Provider description type: string default: Workload Identity Pool Provider managed by Terraform required: false - name: provider_display_name description: Workload Identity Pool Provider display name type: string required: false - name: provider_id description: Workload Identity Pool Provider id type: string required: true - name: sa_mapping description: Service Account resource names and corresponding WIF provider attributes. If attribute is set to `*` all identities in the pool are granted access to SAs. type: |- map(object({ sa_name = string attribute = string })) default: {} required: false outputs: - name: pool_name description: Pool name - name: provider_name description: Provider name roles: - level: Project roles: - roles/owner services: - cloudresourcemanager.googleapis.com - storage-api.googleapis.com - iam.googleapis.com - container.googleapis.com - serviceusage.googleapis.com ================================================ FILE: modules/gh-oidc/outputs.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "pool_name" { description = "Pool name" value = google_iam_workload_identity_pool.main.name } output "provider_name" { description = "Provider name" value = google_iam_workload_identity_pool_provider.main.name } ================================================ FILE: modules/gh-oidc/variables.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to create Workload Identity Pool" } variable "pool_id" { type = string description = "Workload Identity Pool ID" } variable "pool_display_name" { type = string description = "Workload Identity Pool display name" default = null } variable "pool_description" { type = string description = "Workload Identity Pool description" default = "Workload Identity Pool managed by Terraform" } variable "provider_id" { type = string description = "Workload Identity Pool Provider id" } variable "issuer_uri" { type = string description = "Workload Identity Pool Issuer URL" default = "https://token.actions.githubusercontent.com" } variable "provider_display_name" { type = string description = "Workload Identity Pool Provider display name" default = null } variable "provider_description" { type = string description = "Workload Identity Pool Provider description" default = "Workload Identity Pool Provider managed by Terraform" } variable "attribute_condition" { type = string description = "Workload Identity Pool Provider attribute condition expression. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_condition)" default = null } variable "attribute_mapping" { type = map(any) description = "Workload Identity Pool Provider attribute mapping. [More info](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider#attribute_mapping)" default = { "google.subject" = "assertion.sub" "attribute.actor" = "assertion.actor" "attribute.aud" = "assertion.aud" "attribute.repository" = "assertion.repository" } } variable "allowed_audiences" { type = list(string) description = "Workload Identity Pool Provider allowed audiences." default = [] } variable "sa_mapping" { type = map(object({ sa_name = string attribute = string })) description = "Service Account resource names and corresponding WIF provider attributes. If attribute is set to `*` all identities in the pool are granted access to SAs." default = {} } ================================================ FILE: modules/gh-oidc/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" version = ">= 3.64, < 8" } google-beta = { source = "hashicorp/google-beta" version = ">= 3.64, < 8" } } provider_meta "google" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-oidc/v5.1.0" } provider_meta "google-beta" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-oidc/v5.1.0" } } ================================================ FILE: modules/gh-runner-gke/README.md ================================================ # Self Hosted Runners on GKE This module handles the opinionated creation of infrastructure necessary to deploy GitHub Actions Runners on GKE. This module follows the guide provided by GitHub for [Quickstart for Actions Runner Controller](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/quickstart-for-actions-runner-controller). ![ARC on GKE architecture diagram](../../assets/gh-runners-gke.png) This includes: - Enabling necessary APIs - VPC - GKE Cluster - Kubernetes Secret - Installation via Helm Chart ## Usage See below for example usage of this module: ```tf module "runner-gke" { source = "terraform-google-modules/github-actions-runners/google//modules/gh-runner-gke" version = "~> 5.1" project_id = "PROJECT_ID" create_network = true cluster_suffix = "k8s" gh_app_id = "123456" gh_app_installation_id = "12345678" gh_app_private_key = "sample" gh_config_url = "https://github.com/ORGANIZATION" } ``` ### Authenticating to GitHub It's recommended to authenticate to GitHub via a GitHub App. Follow the instructions at [Authenticating ARC with a GitHub App](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/authenticating-to-the-github-api#authenticating-arc-with-a-github-app) to retrieve the necessary prerequisites: - GitHub App ID - GitHub App Installation ID - GitHub App Private Key Install the app in the organization or account for which the runners should be available. Substitute these values gathered from creating the GitHub App installation into the variables in the module. ## Requirements Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 1. Required APIs are activated ``` "cloudresourcemanager.googleapis.com", "storage-api.googleapis.com", "iam.googleapis.com", "container.googleapis.com", "serviceusage.googleapis.com" ``` ## Examples ### [Simple Self Hosted Runners on GKE](../../examples/gh-runner-gke-simple/README.md) This example shows how to deploy a simple GKE Self Hosted Runner. Below are some examples: ### [Self Hosted runners on GKE that support Docker workflows](../../examples/gh-runner-gke-dind/README.md) This example shows how to deploy Self Hosted Runners on GKE that supports Docker Workflows. ### [Self Hosted runners on GKE that support Docker Workflows in rootless configuration](examples/gh-runner-gke-dind-rootless/) This example shows how to deploy Self Hosted Runners on GKE that supports Docker Workflows in a rootless configuration. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | arc\_container\_mode | value of containerMode.type in ARC runner scale set helm chart. If set, value can be `dind` or `kubernetes` | `string` | `""` | no | | arc\_controller\_values | List of values in raw yaml format to pass to helm for ARC runners scale set controller chart | `list(string)` | `[]` | no | | arc\_controller\_version | Version tag for the ARC image. See [https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set-controller](https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set-controller) for releases. | `string` | `"0.9.3"` | no | | arc\_runners\_namespace | Namespace created for the ARC runner pods. | `string` | `"arc-runners"` | no | | arc\_runners\_values | List of values in raw yaml format to pass to helm for ARC runners scale set chart | `list(string)` | `[]` | no | | arc\_runners\_version | Version tag for the ARC image. See [https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set](https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set) for releases. | `string` | `"0.9.3"` | no | | arc\_systems\_namespace | Namespace created for the ARC operator pods. | `string` | `"arc-systems"` | no | | cluster\_suffix | Name of the GitHub organization associated with this runner cluster. | `string` | `"arc"` | no | | create\_network | When set to true, VPC will be auto created | `bool` | `true` | no | | enable\_private\_nodes | Whether nodes have internal IP addresses only. | `bool` | `false` | no | | gh\_app\_id | After creating the GitHub App, on the GitHub App's page, note the value for "App ID". | `string` | n/a | yes | | gh\_app\_installation\_id | You can find the app installation ID on the app installation page, which has the following URL format: `https://github.com/organizations/ORGANIZATION/settings/installations/INSTALLATION_ID` | `string` | n/a | yes | | gh\_app\_pre\_defined\_secret\_name | Name for the k8s secret required to configure gh runners on GKE via GitHub App authentication | `string` | `"gh-app-pre-defined-secret"` | no | | gh\_app\_private\_key | Under "Private keys", click Generate a private key, and save the .pem file. Use the contents of this file for this variable. | `string` | n/a | yes | | gh\_config\_url | URL of GitHub App config. If installed in an organization, this is in the format "https://github.com/ORGANIZATION" | `string` | n/a | yes | | ip\_range\_pods\_cidr | The secondary ip range cidr to use for pods | `string` | `"192.168.0.0/18"` | no | | ip\_range\_pods\_name | The secondary ip range to use for pods | `string` | `"ip-range-pods"` | no | | ip\_range\_services\_cider | The secondary ip range cidr to use for services | `string` | `"192.168.64.0/18"` | no | | ip\_range\_services\_name | The secondary ip range to use for services | `string` | `"ip-range-scv"` | no | | machine\_type | Machine type for runner node pool | `string` | `"n1-standard-4"` | no | | max\_node\_count | Maximum number of nodes in the runner node pool | `number` | `4` | no | | min\_node\_count | Minimum number of nodes in the runner node pool | `number` | `2` | no | | network\_name | Name for the VPC network | `string` | `"runner-network"` | no | | project\_id | The project id to deploy Github Runner cluster | `string` | n/a | yes | | region | The GCP region to deploy instances into | `string` | `"us-east4"` | no | | service\_account | Optional Service Account for the nodes | `string` | `""` | no | | spot | A boolean that represents whether the underlying node VMs are spot | `bool` | `false` | no | | subnet\_ip | IP range for the subnet | `string` | `"10.0.0.0/17"` | no | | subnet\_name | Name for the subnet | `string` | `"runner-subnet"` | no | | subnetwork\_project | The ID of the project in which the subnetwork belongs. If it is not provided, the project\_id is used. | `string` | `""` | no | | zones | The GCP zone to deploy gke into | `list(string)` |
[
"us-east4-a"
]
| no | ## Outputs | Name | Description | |------|-------------| | ca\_certificate | The cluster ca certificate (base64 encoded) | | client\_token | The bearer token for auth | | cluster\_name | Cluster name | | kubernetes\_endpoint | The cluster endpoint | | location | Cluster location | | network\_name | Name of VPC | | service\_account | The default service account used for running nodes. | | subnet\_name | Name of VPC | ================================================ FILE: modules/gh-runner-gke/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { network_name = var.create_network ? google_compute_network.gh-network[0].name : var.network_name subnet_name = var.create_network ? google_compute_subnetwork.gh-subnetwork[0].name : var.subnet_name service_account = var.service_account == "" ? "create" : var.service_account } /***************************************** Optional Network *****************************************/ resource "google_compute_network" "gh-network" { count = var.create_network ? 1 : 0 name = var.network_name project = var.project_id auto_create_subnetworks = false } resource "google_compute_subnetwork" "gh-subnetwork" { count = var.create_network ? 1 : 0 project = var.project_id name = var.subnet_name ip_cidr_range = var.subnet_ip region = var.region network = google_compute_network.gh-network[0].name secondary_ip_range { range_name = var.ip_range_pods_name ip_cidr_range = var.ip_range_pods_cidr } secondary_ip_range { range_name = var.ip_range_services_name ip_cidr_range = var.ip_range_services_cider } } /***************************************** Runner GKE *****************************************/ module "runner-cluster" { source = "terraform-google-modules/kubernetes-engine/google//modules/beta-public-cluster/" version = "~> 35.0" project_id = var.project_id name = "gh-runner-${var.cluster_suffix}" regional = false region = var.region zones = var.zones network = local.network_name network_project_id = var.subnetwork_project != "" ? var.subnetwork_project : var.project_id subnetwork = local.subnet_name ip_range_pods = var.ip_range_pods_name ip_range_services = var.ip_range_services_name logging_service = "logging.googleapis.com/kubernetes" monitoring_service = "monitoring.googleapis.com/kubernetes" remove_default_node_pool = true service_account = local.service_account gce_pd_csi_driver = true deletion_protection = false node_pools = [ { name = "runner-pool" min_count = var.min_node_count max_count = var.max_node_count auto_upgrade = true machine_type = var.machine_type enable_private_nodes = var.enable_private_nodes spot = var.spot } ] } data "google_client_config" "default" { } resource "kubernetes_namespace" "arc_systems" { metadata { name = var.arc_systems_namespace } } resource "kubernetes_namespace" "arc_runners" { metadata { name = var.arc_runners_namespace } depends_on = [helm_release.arc] } /***************************************** K8S secrets for configuring k8s runners *****************************************/ resource "kubernetes_secret" "gh_app_pre_defined_secret" { metadata { name = var.gh_app_pre_defined_secret_name namespace = kubernetes_namespace.arc_runners.metadata[0].name } data = { github_app_id = var.gh_app_id github_app_installation_id = var.gh_app_installation_id github_app_private_key = var.gh_app_private_key } } resource "helm_release" "arc" { name = "arc" namespace = kubernetes_namespace.arc_systems.metadata[0].name chart = "oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller" version = var.arc_controller_version wait = true values = var.arc_controller_values } resource "helm_release" "arc_runners_set" { name = "arc-runners" namespace = kubernetes_namespace.arc_runners.metadata[0].name chart = "oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set" version = var.arc_runners_version set = concat( [ { name = "githubConfigSecret" value = kubernetes_secret.gh_app_pre_defined_secret.metadata[0].name }, { name = "githubConfigUrl" value = var.gh_config_url } ], var.arc_container_mode == "" ? [] : [ { name = "containerMode.type" value = var.arc_container_mode } ] ) values = var.arc_runners_values } ================================================ FILE: modules/gh-runner-gke/metadata.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: name: terraform-google-github-actions-runners annotations: config.kubernetes.io/local-config: "true" spec: title: "" source: repo: https://github.com/terraform-google-modules/terraform-google-github-actions-runners sourceType: git version: 5.1.0 actuationTool: type: Terraform version: '>= 0.13' examples: - name: gh-org-runner-mig-native-simple location: examples/gh-org-runner-mig-native-simple - name: gh-runner-gke-dind location: examples/gh-runner-gke-dind - name: gh-runner-gke-simple location: examples/gh-runner-gke-simple - name: gh-runner-mig-container-vm-dind location: examples/gh-runner-mig-container-vm-dind - name: gh-runner-mig-container-vm-simple location: examples/gh-runner-mig-container-vm-simple - name: gh-runner-mig-native-packer location: examples/gh-runner-mig-native-packer - name: gh-runner-mig-native-simple location: examples/gh-runner-mig-native-simple - name: oidc-simple location: examples/oidc-simple variables: - name: create_network description: When set to true, VPC will be auto created type: bool default: true required: false - name: gh_token description: Github token that is used for generating Self Hosted Runner Token type: string required: true - name: ip_range_pods_cidr description: The secondary ip range cidr to use for pods type: string default: 192.168.0.0/18 required: false - name: ip_range_pods_name description: The secondary ip range to use for pods type: string default: ip-range-pods required: false - name: ip_range_services_cider description: The secondary ip range cidr to use for services type: string default: 192.168.64.0/18 required: false - name: ip_range_services_name description: The secondary ip range to use for services type: string default: ip-range-scv required: false - name: machine_type description: Machine type for runner node pool type: string default: n1-standard-4 required: false - name: max_node_count description: Maximum number of nodes in the runner node pool type: number default: 4 required: false - name: min_node_count description: Minimum number of nodes in the runner node pool type: number default: 2 required: false - name: network_name description: Name for the VPC network type: string default: runner-network required: false - name: project_id description: The project id to deploy Github Runner cluster type: string required: true - name: region description: The GCP region to deploy instances into type: string default: us-east4 required: false - name: repo_name description: Name of the repo for the Github Action type: string required: true - name: repo_owner description: Owner of the repo for the Github Action type: string required: true - name: repo_url description: Repo URL for the Github Action type: string required: true - name: runner_k8s_config description: Name for the k8s secret required to configure gh runners on GKE type: string default: runner-k8s-config required: false - name: service_account description: Optional Service Account for the nodes type: string default: "" required: false - name: subnet_ip description: IP range for the subnet type: string default: 10.0.0.0/17 required: false - name: subnet_name description: Name for the subnet type: string default: runner-subnet required: false - name: subnetwork_project description: The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used. type: string default: "" required: false - name: zones description: The GCP zone to deploy gke into type: list(string) default: - us-east4-a required: false outputs: - name: ca_certificate description: The cluster ca certificate (base64 encoded) - name: client_token description: The bearer token for auth - name: cluster_name description: Cluster name - name: kubernetes_endpoint description: The cluster endpoint - name: location description: Cluster location - name: network_name description: Name of VPC - name: service_account description: The default service account used for running nodes. - name: subnet_name description: Name of VPC roles: - level: Project roles: - roles/owner services: - cloudresourcemanager.googleapis.com - storage-api.googleapis.com - iam.googleapis.com - container.googleapis.com - serviceusage.googleapis.com ================================================ FILE: modules/gh-runner-gke/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "kubernetes_endpoint" { description = "The cluster endpoint" sensitive = true value = module.runner-cluster.endpoint } output "client_token" { description = "The bearer token for auth" sensitive = true value = base64encode(data.google_client_config.default.access_token) } output "ca_certificate" { description = "The cluster ca certificate (base64 encoded)" sensitive = true value = module.runner-cluster.ca_certificate } output "service_account" { description = "The default service account used for running nodes." value = module.runner-cluster.service_account } output "cluster_name" { description = "Cluster name" value = module.runner-cluster.name } output "network_name" { description = "Name of VPC" value = local.network_name } output "subnet_name" { description = "Name of VPC" value = local.subnet_name } output "location" { description = "Cluster location" value = module.runner-cluster.location } ================================================ FILE: modules/gh-runner-gke/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner cluster" } variable "region" { type = string description = "The GCP region to deploy instances into" default = "us-east4" } variable "zones" { type = list(string) description = "The GCP zone to deploy gke into" default = ["us-east4-a"] } variable "ip_range_pods_name" { type = string description = "The secondary ip range to use for pods" default = "ip-range-pods" } variable "ip_range_services_name" { type = string description = "The secondary ip range to use for services" default = "ip-range-scv" } variable "ip_range_pods_cidr" { type = string description = "The secondary ip range cidr to use for pods" default = "192.168.0.0/18" } variable "ip_range_services_cider" { type = string description = "The secondary ip range cidr to use for services" default = "192.168.64.0/18" } variable "network_name" { type = string description = "Name for the VPC network" default = "runner-network" } variable "subnet_ip" { type = string description = "IP range for the subnet" default = "10.0.0.0/17" } variable "subnet_name" { type = string description = "Name for the subnet" default = "runner-subnet" } variable "create_network" { type = bool description = "When set to true, VPC will be auto created" default = true } variable "subnetwork_project" { type = string description = "The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used." default = "" } variable "machine_type" { type = string description = "Machine type for runner node pool" default = "n1-standard-4" } variable "max_node_count" { type = number description = "Maximum number of nodes in the runner node pool" default = 4 } variable "min_node_count" { type = number description = "Minimum number of nodes in the runner node pool" default = 2 } variable "gh_app_pre_defined_secret_name" { type = string description = "Name for the k8s secret required to configure gh runners on GKE via GitHub App authentication" default = "gh-app-pre-defined-secret" } variable "gh_app_id" { type = string description = "After creating the GitHub App, on the GitHub App's page, note the value for \"App ID\"." } variable "gh_app_installation_id" { type = string description = "You can find the app installation ID on the app installation page, which has the following URL format: `https://github.com/organizations/ORGANIZATION/settings/installations/INSTALLATION_ID`" } variable "gh_app_private_key" { type = string description = "Under \"Private keys\", click Generate a private key, and save the .pem file. Use the contents of this file for this variable." sensitive = true } variable "service_account" { type = string description = "Optional Service Account for the nodes" default = "" } variable "arc_systems_namespace" { type = string description = "Namespace created for the ARC operator pods." default = "arc-systems" } variable "arc_runners_namespace" { type = string description = "Namespace created for the ARC runner pods." default = "arc-runners" } variable "cluster_suffix" { type = string description = "Name of the GitHub organization associated with this runner cluster." default = "arc" } variable "gh_config_url" { type = string description = "URL of GitHub App config. If installed in an organization, this is in the format \"https://github.com/ORGANIZATION\"" } variable "arc_runners_version" { type = string description = "Version tag for the ARC image. See [https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set](https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set) for releases." default = "0.9.3" } variable "arc_controller_version" { type = string description = "Version tag for the ARC image. See [https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set-controller](https://github.com/actions/actions-runner-controller/pkgs/container/actions-runner-controller-charts%2Fgha-runner-scale-set-controller) for releases." default = "0.9.3" } variable "arc_container_mode" { type = string description = "value of containerMode.type in ARC runner scale set helm chart. If set, value can be `dind` or `kubernetes`" default = "" } variable "arc_controller_values" { type = list(string) description = "List of values in raw yaml format to pass to helm for ARC runners scale set controller chart" default = [] } variable "arc_runners_values" { type = list(string) description = "List of values in raw yaml format to pass to helm for ARC runners scale set chart" default = [] } variable "enable_private_nodes" { type = bool description = "Whether nodes have internal IP addresses only." default = false } variable "spot" { type = bool description = "A boolean that represents whether the underlying node VMs are spot" default = false } ================================================ FILE: modules/gh-runner-gke/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" version = ">= 4.3.0, < 8" } google-beta = { source = "hashicorp/google-beta" version = ">= 4.3.0, < 8" } kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.0" } helm = { source = "hashicorp/helm" version = "~> 3.0" } } provider_meta "google" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-runner-gke/v5.1.0" } } ================================================ FILE: modules/gh-runner-mig-container-vm/README.md ================================================ ## Self Hosted Runners on Managed Instance Group This module handles the opinionated creation of infrastructure necessary to deploy Github Self Hosted Runners on MIG Container VMs. This includes: - Enabling necessary APIs - VPC - NAT & Cloud Router - MIG Container Instance Template - MIG Instance Manager - FW Rules Below are some examples: ### [Self Hosted runners that support Docker Workflows](../../examples/gh-runner-mig-container-vm-dind/README.md) This example shows how to deploy a Self Hosted Runner that supports Docker Workflows on MIG Container VMs. ### [Simple Self Hosted Runner](../../examples/gh-runner-mig-container-vm-simple/README.md) This example shows how to deploy a Self Hosted Runner on MIG Container VMs. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | additional\_metadata | Additional metadata to attach to the instance | `map(any)` | `{}` | no | | cooldown\_period | The number of seconds that the autoscaler should wait before it starts collecting information from a new instance. | `number` | `60` | no | | create\_network | When set to true, VPC,router and NAT will be auto created | `bool` | `true` | no | | dind | Flag to determine whether to expose dockersock | `bool` | `false` | no | | disk\_size\_gb | Instance disk size in GB | `number` | `100` | no | | disk\_type | Instance disk type, can be either pd-ssd, local-ssd, or pd-standard | `string` | `"pd-ssd"` | no | | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | image | The github runner image | `string` | n/a | yes | | instance\_name | The gce instance name | `string` | `"gh-runner"` | no | | network\_name | Name for the VPC network | `string` | `"gh-runner-network"` | no | | project\_id | The project id to deploy Github Runner | `string` | n/a | yes | | region | The GCP region to deploy instances into | `string` | `"us-east4"` | no | | repo\_name | Name of the repo for the Github Action | `string` | n/a | yes | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | | repo\_url | Repo URL for the Github Action | `string` | n/a | yes | | restart\_policy | The desired Docker restart policy for the runner image | `string` | `"Always"` | no | | service\_account | Service account email address | `string` | `""` | no | | spot | Provision a SPOT instance | `bool` | `false` | no | | spot\_instance\_termination\_action | Action to take when Compute Engine preempts a Spot VM. | `string` | `"STOP"` | no | | subnet\_ip | IP range for the subnet | `string` | `"10.10.10.0/24"` | no | | subnet\_name | Name for the subnet | `string` | `"gh-runner-subnet"` | no | | subnetwork\_project | The ID of the project in which the subnetwork belongs. If it is not provided, the project\_id is used. | `string` | `""` | no | | target\_size | The number of runner instances | `number` | `2` | no | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | network\_name | Name of VPC | | service\_account | Service account email for GCE | | subnet\_name | Name of VPC | ## Requirements Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 1. Required APIs are activated ``` "iam.googleapis.com", "cloudresourcemanager.googleapis.com", "containerregistry.googleapis.com", "storage-component.googleapis.com", "logging.googleapis.com", "monitoring.googleapis.com" ``` ================================================ FILE: modules/gh-runner-mig-container-vm/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { dindVolumeMounts = var.dind ? [{ mountPath = "/var/run/docker.sock" name = "dockersock" readOnly = false }] : [] dindVolumes = var.dind ? [ { name = "dockersock" hostPath = { path = "/var/run/docker.sock" } }] : [] network_name = var.create_network ? google_compute_network.gh-network[0].self_link : var.network_name subnet_name = var.create_network ? google_compute_subnetwork.gh-subnetwork[0].self_link : var.subnet_name service_account = var.service_account == "" ? google_service_account.runner_service_account[0].email : var.service_account # location = var.regional ? var.region : var.zones[0] } /***************************************** Optional Runner Networking *****************************************/ resource "google_compute_network" "gh-network" { count = var.create_network ? 1 : 0 name = var.network_name project = var.project_id auto_create_subnetworks = false } resource "google_compute_subnetwork" "gh-subnetwork" { count = var.create_network ? 1 : 0 project = var.project_id name = var.subnet_name ip_cidr_range = var.subnet_ip region = var.region network = google_compute_network.gh-network[0].name } resource "google_compute_router" "default" { count = var.create_network ? 1 : 0 name = "${var.network_name}-router" network = google_compute_network.gh-network[0].self_link region = var.region project = var.project_id } resource "google_compute_router_nat" "nat" { count = var.create_network ? 1 : 0 project = var.project_id name = "${var.network_name}-nat" router = google_compute_router.default[0].name region = google_compute_router.default[0].region nat_ip_allocate_option = "AUTO_ONLY" source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" } /***************************************** IAM Bindings GCE SVC *****************************************/ resource "google_service_account" "runner_service_account" { count = var.service_account == "" ? 1 : 0 project = var.project_id account_id = "runner-service-account" display_name = "Github Runner GCE Service Account" } # allow GCE to pull images from GCR resource "google_project_iam_binding" "gce" { count = var.service_account == "" ? 1 : 0 project = var.project_id role = "roles/storage.objectViewer" members = [ "serviceAccount:${local.service_account}", ] } /***************************************** Runner GCE Instance Template *****************************************/ locals { instance_name = format("%s-%s", var.instance_name, substr(md5(module.gce-container.container.image), 0, 8)) } module "gce-container" { source = "terraform-google-modules/container-vm/google" version = "~> 3.0" container = { image = var.image env = [ { name = "ACTIONS_RUNNER_INPUT_URL" value = var.repo_url }, { name = "GITHUB_TOKEN" value = var.gh_token }, { name = "REPO_OWNER" value = var.repo_owner }, { name = "REPO_NAME" value = var.repo_name } ] # Declare volumes to be mounted # This is similar to how Docker volumes are mounted volumeMounts = concat([ { mountPath = "/cache" name = "tempfs-0" readOnly = false } ], local.dindVolumeMounts) } # Declare the volumes volumes = concat([ { name = "tempfs-0" emptyDir = { medium = "Memory" } } ], local.dindVolumes) restart_policy = var.restart_policy } module "mig_template" { source = "terraform-google-modules/vm/google//modules/instance_template" version = "~> 13.0" project_id = var.project_id region = var.region network = local.network_name subnetwork = local.subnet_name subnetwork_project = var.subnetwork_project != "" ? var.subnetwork_project : var.project_id service_account = { email = local.service_account scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] } disk_size_gb = var.disk_size_gb disk_type = var.disk_type auto_delete = true name_prefix = "gh-runner" source_image_family = "cos-stable" source_image_project = "cos-cloud" startup_script = "export TEST_ENV='hello'" source_image = reverse(split("/", module.gce-container.source_image))[0] spot = var.spot spot_instance_termination_action = var.spot_instance_termination_action metadata = merge(var.additional_metadata, { "gce-container-declaration" = module.gce-container.metadata_value }) tags = [ "gh-runner-vm" ] labels = { container-vm = module.gce-container.vm_container_label } } /***************************************** Runner MIG *****************************************/ module "mig" { source = "terraform-google-modules/vm/google//modules/mig" version = "~> 13.0" project_id = var.project_id hostname = local.instance_name region = var.region instance_template = module.mig_template.self_link target_size = var.target_size /* autoscaler */ autoscaling_enabled = true cooldown_period = var.cooldown_period } ================================================ FILE: modules/gh-runner-mig-container-vm/metadata.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: name: terraform-google-github-actions-runners annotations: config.kubernetes.io/local-config: "true" spec: title: "" source: repo: https://github.com/terraform-google-modules/terraform-google-github-actions-runners sourceType: git version: 5.1.0 actuationTool: type: Terraform version: '>= 0.13' examples: - name: gh-org-runner-mig-native-simple location: examples/gh-org-runner-mig-native-simple - name: gh-runner-gke-dind location: examples/gh-runner-gke-dind - name: gh-runner-gke-simple location: examples/gh-runner-gke-simple - name: gh-runner-mig-container-vm-dind location: examples/gh-runner-mig-container-vm-dind - name: gh-runner-mig-container-vm-simple location: examples/gh-runner-mig-container-vm-simple - name: gh-runner-mig-native-packer location: examples/gh-runner-mig-native-packer - name: gh-runner-mig-native-simple location: examples/gh-runner-mig-native-simple - name: oidc-simple location: examples/oidc-simple variables: - name: additional_metadata description: Additional metadata to attach to the instance type: map(any) default: {} required: false - name: cooldown_period description: The number of seconds that the autoscaler should wait before it starts collecting information from a new instance. type: number default: 60 required: false - name: create_network description: When set to true, VPC,router and NAT will be auto created type: bool default: true required: false - name: dind description: 'Flag to determine whether to expose dockersock ' type: bool default: false required: false - name: gh_token description: Github token that is used for generating Self Hosted Runner Token type: string required: true - name: image description: The github runner image type: string required: true - name: instance_name description: The gce instance name type: string default: gh-runner required: false - name: network_name description: Name for the VPC network type: string default: gh-runner-network required: false - name: project_id description: The project id to deploy Github Runner type: string required: true - name: region description: The GCP region to deploy instances into type: string default: us-east4 required: false - name: repo_name description: Name of the repo for the Github Action type: string required: true - name: repo_owner description: Owner of the repo for the Github Action type: string required: true - name: repo_url description: Repo URL for the Github Action type: string required: true - name: restart_policy description: The desired Docker restart policy for the runner image type: string default: Always required: false - name: service_account description: Service account email address type: string default: "" required: false - name: subnet_ip description: IP range for the subnet type: string default: 10.10.10.0/24 required: false - name: subnet_name description: Name for the subnet type: string default: gh-runner-subnet required: false - name: subnetwork_project description: The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used. type: string default: "" required: false - name: target_size description: The number of runner instances type: number default: 2 required: false outputs: - name: mig_instance_group description: The instance group url of the created MIG - name: mig_instance_template description: The name of the MIG Instance Template - name: mig_name description: The name of the MIG - name: network_name description: Name of VPC - name: service_account description: Service account email for GCE - name: subnet_name description: Name of VPC roles: - level: Project roles: - roles/owner services: - cloudresourcemanager.googleapis.com - storage-api.googleapis.com - iam.googleapis.com - container.googleapis.com - serviceusage.googleapis.com ================================================ FILE: modules/gh-runner-mig-container-vm/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.mig.instance_group } output "mig_name" { description = "The name of the MIG" value = local.instance_name } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.mig_template.name } output "network_name" { description = "Name of VPC" value = local.network_name } output "subnet_name" { description = "Name of VPC" value = local.subnet_name } output "service_account" { description = "Service account email for GCE" value = local.service_account } ================================================ FILE: modules/gh-runner-mig-container-vm/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner" } variable "region" { type = string description = "The GCP region to deploy instances into" default = "us-east4" } variable "network_name" { type = string description = "Name for the VPC network" default = "gh-runner-network" } variable "create_network" { type = bool description = "When set to true, VPC,router and NAT will be auto created" default = true } variable "subnetwork_project" { type = string description = "The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used." default = "" } variable "subnet_ip" { type = string description = "IP range for the subnet" default = "10.10.10.0/24" } variable "subnet_name" { type = string description = "Name for the subnet" default = "gh-runner-subnet" } variable "restart_policy" { type = string description = "The desired Docker restart policy for the runner image" default = "Always" } variable "image" { type = string description = "The github runner image" } variable "repo_url" { type = string description = "Repo URL for the Github Action" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } variable "instance_name" { type = string description = "The gce instance name" default = "gh-runner" } variable "target_size" { type = number description = "The number of runner instances" default = 2 } variable "service_account" { description = "Service account email address" type = string default = "" } variable "additional_metadata" { type = map(any) description = "Additional metadata to attach to the instance" default = {} } variable "dind" { type = bool description = "Flag to determine whether to expose dockersock " default = false } variable "cooldown_period" { description = "The number of seconds that the autoscaler should wait before it starts collecting information from a new instance." type = number default = 60 } variable "spot" { type = bool description = "Provision a SPOT instance" default = false } variable "spot_instance_termination_action" { description = "Action to take when Compute Engine preempts a Spot VM." type = string default = "STOP" } variable "disk_size_gb" { type = number description = "Instance disk size in GB" default = 100 } variable "disk_type" { type = string description = "Instance disk type, can be either pd-ssd, local-ssd, or pd-standard" default = "pd-ssd" } ================================================ FILE: modules/gh-runner-mig-container-vm/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" version = ">= 3.53, < 8" } } provider_meta "google" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-runner-mig-container-vm/v5.1.0" } } ================================================ FILE: modules/gh-runner-mig-vm/README.md ================================================ ## Self Hosted Runners on Managed Instance Group This module handles the opinionated creation of infrastructure necessary to deploy Github Self Hosted Runners on MIG. This includes: - Enabling necessary APIs - VPC - NAT & Cloud Router - Service Account for MIG - MIG Instance Template - MIG Instance Manager - FW Rules - Secret Manager Secret Below are some examples: ### [Simple Self Hosted Runner](../../examples/gh-runner-mig-native-simple/README.md) This example shows how to deploy a MIG Self Hosted Runner bootstrapped using startup scripts. ### [Simple Self Hosted Runner](../../examples/gh-runner-mig-native-packer/README.md) This example shows how to deploy a MIG Self Hosted Runner with an image pre-baked using Packer. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | cooldown\_period | The number of seconds that the autoscaler should wait before it starts collecting information from a new instance. | `number` | `60` | no | | create\_network | When set to true, VPC,router and NAT will be auto created | `bool` | `true` | no | | create\_subnetwork | Whether to create subnetwork or use the one provided via subnet\_name | `bool` | `true` | no | | custom\_metadata | User provided custom metadata | `map(any)` | `{}` | no | | disk\_size\_gb | Instance disk size in GB | `number` | `100` | no | | disk\_type | Instance disk type, can be either pd-ssd, local-ssd, or pd-standard | `string` | `"pd-ssd"` | no | | gh\_runner\_labels | GitHub runner labels to attach to the runners. Docs: https://docs.github.com/en/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners | `set(string)` | `[]` | no | | gh\_token | Github token that is used for generating Self Hosted Runner Token | `string` | n/a | yes | | instance\_tags | Additional tags to add to the instances | `list(string)` | `[]` | no | | machine\_type | The GCP machine type to deploy | `string` | `"n1-standard-1"` | no | | max\_replicas | Maximum number of runner instances | `number` | `10` | no | | min\_replicas | Minimum number of runner instances | `number` | `2` | no | | network\_name | Name for the VPC network | `string` | `"gh-runner-network"` | no | | project\_id | The project id to deploy Github Runner | `string` | n/a | yes | | region | The GCP region to deploy instances into | `string` | `"us-east4"` | no | | repo\_name | Name of the repo for the Github Action | `string` | `""` | no | | repo\_owner | Owner of the repo for the Github Action | `string` | n/a | yes | | service\_account | Service account email address | `string` | `""` | no | | shutdown\_script | User shutdown script to run when instances shutdown | `string` | `""` | no | | source\_image | Source disk image. If neither source\_image nor source\_image\_family is specified, defaults to the latest public CentOS image. | `string` | `""` | no | | source\_image\_family | Source image family. If neither source\_image nor source\_image\_family is specified, defaults to the latest public Ubuntu image. | `string` | `"ubuntu-1804-lts"` | no | | source\_image\_project | Project where the source image comes from | `string` | `"ubuntu-os-cloud"` | no | | spot | Provision a SPOT instance | `bool` | `false` | no | | spot\_instance\_termination\_action | Action to take when Compute Engine preempts a Spot VM. | `string` | `"STOP"` | no | | startup\_script | User startup script to run when instances spin up | `string` | `""` | no | | subnet\_ip | IP range for the subnet | `string` | `"10.10.10.0/24"` | no | | subnet\_name | Name for the subnet | `string` | `"gh-runner-subnet"` | no | | subnetwork\_project | The ID of the project in which the subnetwork belongs. If it is not provided, the project\_id is used. | `string` | `""` | no | ## Outputs | Name | Description | |------|-------------| | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | network\_name | Name of VPC | | service\_account | Service account email for GCE | | subnet\_name | Name of VPC | ## Requirements Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 1. Required APIs are activated ``` "iam.googleapis.com", "compute.googleapis.com", "storage-component.googleapis.com", "logging.googleapis.com", "monitoring.googleapis.com", "secretmanager.googleapis.com", ``` ================================================ FILE: modules/gh-runner-mig-vm/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { network_name = var.create_network ? google_compute_network.gh-network[0].self_link : var.network_name subnet_name = var.create_subnetwork ? google_compute_subnetwork.gh-subnetwork[0].self_link : var.subnet_name service_account = var.service_account == "" ? google_service_account.runner_service_account[0].email : var.service_account startup_script = var.startup_script == "" ? file("${path.module}/scripts/startup.sh") : var.startup_script shutdown_script = var.shutdown_script == "" ? file("${path.module}/scripts/shutdown.sh") : var.shutdown_script } /***************************************** Optional Runner Networking *****************************************/ resource "google_compute_network" "gh-network" { count = var.create_network ? 1 : 0 name = var.network_name project = var.project_id auto_create_subnetworks = false } resource "google_compute_subnetwork" "gh-subnetwork" { count = var.create_subnetwork ? 1 : 0 project = var.project_id name = var.subnet_name ip_cidr_range = var.subnet_ip region = var.region network = local.network_name } resource "google_compute_router" "default" { count = var.create_network ? 1 : 0 name = "${var.network_name}-router" network = google_compute_network.gh-network[0].self_link region = var.region project = var.project_id } resource "google_compute_router_nat" "nat" { count = var.create_network ? 1 : 0 project = var.project_id name = "${var.network_name}-nat" router = google_compute_router.default[0].name region = google_compute_router.default[0].region nat_ip_allocate_option = "AUTO_ONLY" source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" } /***************************************** IAM Bindings GCE SVC *****************************************/ resource "google_service_account" "runner_service_account" { count = var.service_account == "" ? 1 : 0 project = var.project_id account_id = "runner-service-account" display_name = "Github Runner GCE Service Account" } /***************************************** Runner Secrets *****************************************/ resource "google_secret_manager_secret" "gh-secret" { provider = google-beta project = var.project_id secret_id = "gh-token" labels = { label = "gh-token" } replication { user_managed { replicas { location = var.region } } } } resource "google_secret_manager_secret_version" "gh-secret-version" { provider = google-beta secret = google_secret_manager_secret.gh-secret.id secret_data = jsonencode({ "REPO_NAME" = var.repo_name "REPO_OWNER" = var.repo_owner "GITHUB_TOKEN" = var.gh_token "LABELS" = join(",", var.gh_runner_labels) }) } resource "google_secret_manager_secret_iam_member" "gh-secret-member" { provider = google-beta project = var.project_id secret_id = google_secret_manager_secret.gh-secret.id role = "roles/secretmanager.secretAccessor" member = "serviceAccount:${local.service_account}" } /***************************************** Runner GCE Instance Template *****************************************/ locals { instance_name = "gh-runner-vm" } module "mig_template" { source = "terraform-google-modules/vm/google//modules/instance_template" version = "~> 13.0" project_id = var.project_id machine_type = var.machine_type network = local.network_name subnetwork = local.subnet_name region = var.region subnetwork_project = var.subnetwork_project != "" ? var.subnetwork_project : var.project_id service_account = { email = local.service_account scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] } disk_size_gb = var.disk_size_gb disk_type = var.disk_type auto_delete = true name_prefix = "gh-runner" source_image_family = var.source_image_family source_image_project = var.source_image_project startup_script = local.startup_script source_image = var.source_image spot = var.spot spot_instance_termination_action = var.spot_instance_termination_action metadata = merge({ "secret-id" = google_secret_manager_secret_version.gh-secret-version.name }, { "shutdown-script" = local.shutdown_script }, var.custom_metadata) tags = concat(["gh-runner-vm"], var.instance_tags) } /***************************************** Runner MIG *****************************************/ module "mig" { source = "terraform-google-modules/vm/google//modules/mig" version = "~> 13.0" project_id = var.project_id hostname = local.instance_name region = var.region instance_template = module.mig_template.self_link /* autoscaler */ autoscaling_enabled = true min_replicas = var.min_replicas max_replicas = var.max_replicas cooldown_period = var.cooldown_period } ================================================ FILE: modules/gh-runner-mig-vm/metadata.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: name: terraform-google-github-actions-runners annotations: config.kubernetes.io/local-config: "true" spec: title: "" source: repo: https://github.com/terraform-google-modules/terraform-google-github-actions-runners sourceType: git version: 5.1.0 actuationTool: type: Terraform version: '>= 0.13' examples: - name: gh-org-runner-mig-native-simple location: examples/gh-org-runner-mig-native-simple - name: gh-runner-gke-dind location: examples/gh-runner-gke-dind - name: gh-runner-gke-simple location: examples/gh-runner-gke-simple - name: gh-runner-mig-container-vm-dind location: examples/gh-runner-mig-container-vm-dind - name: gh-runner-mig-container-vm-simple location: examples/gh-runner-mig-container-vm-simple - name: gh-runner-mig-native-packer location: examples/gh-runner-mig-native-packer - name: gh-runner-mig-native-simple location: examples/gh-runner-mig-native-simple - name: oidc-simple location: examples/oidc-simple variables: - name: cooldown_period description: The number of seconds that the autoscaler should wait before it starts collecting information from a new instance. type: number default: 60 required: false - name: create_network description: When set to true, VPC,router and NAT will be auto created type: bool default: true required: false - name: create_subnetwork description: Whether to create subnetwork or use the one provided via subnet_name type: bool default: true required: false - name: custom_metadata description: User provided custom metadata type: map(any) default: {} required: false - name: gh_runner_labels description: 'GitHub runner labels to attach to the runners. Docs: https://docs.github.com/en/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners' type: set(string) default: [] required: false - name: gh_token description: Github token that is used for generating Self Hosted Runner Token type: string required: true - name: machine_type description: The GCP machine type to deploy type: string default: n1-standard-1 required: false - name: max_replicas description: Maximum number of runner instances type: number default: 10 required: false - name: min_replicas description: Minimum number of runner instances type: number default: 2 required: false - name: network_name description: Name for the VPC network type: string default: gh-runner-network required: false - name: project_id description: The project id to deploy Github Runner type: string required: true - name: region description: The GCP region to deploy instances into type: string default: us-east4 required: false - name: repo_name description: Name of the repo for the Github Action type: string default: "" required: false - name: repo_owner description: Owner of the repo for the Github Action type: string required: true - name: service_account description: Service account email address type: string default: "" required: false - name: shutdown_script description: User shutdown script to run when instances shutdown type: string default: "" required: false - name: source_image description: Source disk image. If neither source_image nor source_image_family is specified, defaults to the latest public CentOS image. type: string default: "" required: false - name: source_image_family description: Source image family. If neither source_image nor source_image_family is specified, defaults to the latest public Ubuntu image. type: string default: ubuntu-1804-lts required: false - name: source_image_project description: Project where the source image comes from type: string default: ubuntu-os-cloud required: false - name: startup_script description: User startup script to run when instances spin up type: string default: "" required: false - name: subnet_ip description: IP range for the subnet type: string default: 10.10.10.0/24 required: false - name: subnet_name description: Name for the subnet type: string default: gh-runner-subnet required: false - name: subnetwork_project description: The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used. type: string default: "" required: false outputs: - name: mig_instance_group description: The instance group url of the created MIG - name: mig_instance_template description: The name of the MIG Instance Template - name: mig_name description: The name of the MIG - name: network_name description: Name of VPC - name: service_account description: Service account email for GCE - name: subnet_name description: Name of VPC roles: - level: Project roles: - roles/owner services: - cloudresourcemanager.googleapis.com - storage-api.googleapis.com - iam.googleapis.com - container.googleapis.com - serviceusage.googleapis.com ================================================ FILE: modules/gh-runner-mig-vm/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.mig.instance_group } output "mig_name" { description = "The name of the MIG" value = local.instance_name } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.mig_template.name } output "network_name" { description = "Name of VPC" value = local.network_name } output "subnet_name" { description = "Name of VPC" value = local.subnet_name } output "service_account" { description = "Service account email for GCE" value = local.service_account } ================================================ FILE: modules/gh-runner-mig-vm/scripts/shutdown.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. secretUri=$(curl -sS "http://metadata.google.internal/computeMetadata/v1/instance/attributes/secret-id" -H "Metadata-Flavor: Google") #secrets URI is of the form projects/$PROJECT_NUMBER/secrets/$SECRET_NAME/versions/$SECRET_VERSION #split into array based on `/` delimeter IFS="/" read -r -a secretsConfig <<<"$secretUri" #get SECRET_NAME and SECRET_VERSION SECRET_NAME=${secretsConfig[3]} SECRET_VERSION=${secretsConfig[5]} #access secret from secretsmanager secrets=$(gcloud secrets versions access "$SECRET_VERSION" --secret="$SECRET_NAME") #set secrets as env vars # shellcheck disable=SC2046 # we want to use wordsplitting export $(echo "$secrets" | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") #stop and uninstall the runner service cd /runner || exit ./svc.sh stop ./svc.sh uninstall if [[ -z $REPO_NAME ]]; then # Remove action runner from the organisation POST_URL="https://api.github.com/orgs/${REPO_OWNER}/actions/runners/remove-token" else # Remove action runner from the repo POST_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/remove-token" fi #remove the runner configuration RUNNER_ALLOW_RUNASROOT=1 /runner/config.sh remove --unattended --token "$(curl -sS --request POST --url "$POST_URL" --header "authorization: Bearer ${GITHUB_TOKEN}" --header "content-type: application/json" | jq -r .token)" ================================================ FILE: modules/gh-runner-mig-vm/scripts/startup.sh ================================================ #!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #install jq apt-get update apt-get -y install jq secretUri=$(curl -sS "http://metadata.google.internal/computeMetadata/v1/instance/attributes/secret-id" -H "Metadata-Flavor: Google") #secrets URI is of the form projects/$PROJECT_NUMBER/secrets/$SECRET_NAME/versions/$SECRET_VERSION #split into array based on `/` delimeter IFS="/" read -r -a secretsConfig <<<"$secretUri" #get SECRET_NAME and SECRET_VERSION SECRET_NAME=${secretsConfig[3]} SECRET_VERSION=${secretsConfig[5]} #access secret from secretsmanager secrets=$(gcloud secrets versions access "$SECRET_VERSION" --secret="$SECRET_NAME") #set secrets as env vars # shellcheck disable=SC2046 # we want to use wordsplitting export $(echo "$secrets" | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") #github runner version GH_RUNNER_VERSION="2.283.2" #get actions binary curl -o actions.tar.gz --location "https://github.com/actions/runner/releases/download/v${GH_RUNNER_VERSION}/actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz" mkdir /runner mkdir /runner-tmp tar -zxf actions.tar.gz --directory /runner rm -f actions.tar.gz /runner/bin/installdependencies.sh #get actions token # shellcheck disable=SC2034 # ACTIONS_RUNNER_INPUT_NAME is used by config.sh ACTIONS_RUNNER_INPUT_NAME=$HOSTNAME if [[ -z $REPO_NAME ]]; then # Add action runner for an organisation POST_URL="https://api.github.com/orgs/${REPO_OWNER}/actions/runners/registration-token" GH_URL="https://github.com/${REPO_OWNER}" else # Add action runner for a repo POST_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runners/registration-token" GH_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}" fi # Register runner ACTIONS_RUNNER_INPUT_TOKEN="$(curl -sS --request POST --url "$POST_URL" --header "authorization: Bearer ${GITHUB_TOKEN}" --header 'content-type: application/json' | jq -r .token)" #configure runner RUNNER_ALLOW_RUNASROOT=1 /runner/config.sh --unattended --replace --work "/runner-tmp" --url "$GH_URL" --token "$ACTIONS_RUNNER_INPUT_TOKEN" --labels "$LABELS" #install and start runner service cd /runner || exit ./svc.sh install ./svc.sh start ================================================ FILE: modules/gh-runner-mig-vm/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id" { type = string description = "The project id to deploy Github Runner" } variable "region" { type = string description = "The GCP region to deploy instances into" default = "us-east4" } variable "network_name" { type = string description = "Name for the VPC network" default = "gh-runner-network" } variable "create_network" { type = bool description = "When set to true, VPC,router and NAT will be auto created" default = true } variable "subnetwork_project" { type = string description = "The ID of the project in which the subnetwork belongs. If it is not provided, the project_id is used." default = "" } variable "subnet_ip" { type = string description = "IP range for the subnet" default = "10.10.10.0/24" } variable "create_subnetwork" { type = bool description = "Whether to create subnetwork or use the one provided via subnet_name" default = true } variable "subnet_name" { type = string description = "Name for the subnet" default = "gh-runner-subnet" } variable "repo_name" { type = string description = "Name of the repo for the Github Action" default = "" } variable "repo_owner" { type = string description = "Owner of the repo for the Github Action" } variable "gh_runner_labels" { type = set(string) description = "GitHub runner labels to attach to the runners. Docs: https://docs.github.com/en/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners" default = [] } variable "min_replicas" { type = number description = "Minimum number of runner instances" default = 2 } variable "max_replicas" { type = number default = 10 description = "Maximum number of runner instances" } variable "gh_token" { type = string description = "Github token that is used for generating Self Hosted Runner Token" } variable "service_account" { description = "Service account email address" type = string default = "" } variable "machine_type" { type = string description = "The GCP machine type to deploy" default = "n1-standard-1" } variable "source_image_family" { type = string description = "Source image family. If neither source_image nor source_image_family is specified, defaults to the latest public Ubuntu image." default = "ubuntu-1804-lts" } variable "source_image_project" { type = string description = "Project where the source image comes from" default = "ubuntu-os-cloud" } variable "source_image" { type = string description = "Source disk image. If neither source_image nor source_image_family is specified, defaults to the latest public CentOS image." default = "" } variable "startup_script" { type = string description = "User startup script to run when instances spin up" default = "" } variable "shutdown_script" { type = string description = "User shutdown script to run when instances shutdown" default = "" } variable "custom_metadata" { type = map(any) description = "User provided custom metadata" default = {} } variable "cooldown_period" { description = "The number of seconds that the autoscaler should wait before it starts collecting information from a new instance." type = number default = 60 } variable "instance_tags" { type = list(string) description = "Additional tags to add to the instances" default = [] } variable "spot" { type = bool description = "Provision a SPOT instance" default = false } variable "spot_instance_termination_action" { description = "Action to take when Compute Engine preempts a Spot VM." type = string default = "STOP" } variable "disk_size_gb" { type = number description = "Instance disk size in GB" default = 100 } variable "disk_type" { type = string description = "Instance disk type, can be either pd-ssd, local-ssd, or pd-standard" default = "pd-ssd" } ================================================ FILE: modules/gh-runner-mig-vm/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" version = ">= 3.53, < 8" } google-beta = { source = "hashicorp/google-beta" version = ">= 3.53, < 8" } } provider_meta "google" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-runner-mig-vm/v5.1.0" } provider_meta "google-beta" { module_name = "blueprints/terraform/terraform-google-github-actions-runners:gh-runner-mig-vm/v5.1.0" } } ================================================ FILE: test/.gitignore ================================================ source.sh ================================================ FILE: test/fixtures/gh-runner-mig-container-vm/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "example_mig_runner" { source = "../../../examples/gh-runner-mig-container-vm-simple" project_id = var.project_id_mig_container image = "gcr.io/google-samples/hello-app:1.0" repo_url = "example" repo_name = "example" repo_owner = "example" gh_token = "example" } ================================================ FILE: test/fixtures/gh-runner-mig-container-vm/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "project_id" { value = var.project_id_mig_container } output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.example_mig_runner.mig_instance_group } output "mig_name" { description = "The name of the MIG" value = module.example_mig_runner.mig_name } output "service_account" { description = "Service account email for GCE" value = module.example_mig_runner.service_account } output "mig_instance_template" { description = "The name of the MIG Instance Template" value = module.example_mig_runner.mig_instance_template } ================================================ FILE: test/fixtures/gh-runner-mig-container-vm/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "project_id_mig_container" { type = string description = "The GCP project to use for integration tests" } ================================================ FILE: test/integration/discover_test.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package test import ( "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" ) func TestAll(t *testing.T) { tft.AutoDiscoverAndTest(t) } ================================================ FILE: test/integration/gh-runner-gke-dind/gh_runner_gke_dind_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gh_runner_gke_dind import ( "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" "github.com/gruntwork-io/terratest/modules/k8s" "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) func TestGhRunnerGkeDind(t *testing.T) { bpt := tft.NewTFBlueprintTest(t) bpt.DefineVerify(func(assert *assert.Assertions) { bpt.DefaultVerify(assert) // get outputs projectId := bpt.GetStringOutput("project_id") location := bpt.GetStringOutput("location") clusterName := bpt.GetStringOutput("cluster_name") // Check cluster is running cluster := gcloud.Runf(t, "container clusters describe %s --location %s --project %s", clusterName, location, projectId) assert.Contains([]string{"RUNNING"}, cluster.Get("status").String()) // Get cluster credentials gcloud.Runf(t, "container clusters get-credentials %s --location %s --project %s", clusterName, location, projectId) k8sOpts := k8s.KubectlOptions{} CheckPodsRunningInNamespace("arc-systems", t, k8sOpts, assert) CheckPodsRunningInNamespace("arc-runners", t, k8sOpts, assert) }) bpt.Test() } func CheckPodsRunningInNamespace(namespace string, t *testing.T, k8sOpts k8s.KubectlOptions, assert *assert.Assertions) { pods, err := k8s.RunKubectlAndGetOutputE(t, &k8sOpts, "get", "pods", "-n", namespace, "-o", "json") if err != nil { t.Fatalf("Error getting pods: %s", err) } statuses := gjson.Get(pods, "items.#.status.phase") for _, status := range statuses.Array() { assert.Equal("Running", status.String()) } } ================================================ FILE: test/integration/gh-runner-gke-dind-rootless/gh_runner_gke_dind_rootless_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gh_runner_gke_dind_rootless import ( "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" "github.com/gruntwork-io/terratest/modules/k8s" "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) func TestGhRunnerGkeDindRootless(t *testing.T) { bpt := tft.NewTFBlueprintTest(t) bpt.DefineVerify(func(assert *assert.Assertions) { bpt.DefaultVerify(assert) // get outputs projectId := bpt.GetStringOutput("project_id") location := bpt.GetStringOutput("location") clusterName := bpt.GetStringOutput("cluster_name") // Check cluster is running cluster := gcloud.Runf(t, "container clusters describe %s --location %s --project %s", clusterName, location, projectId) assert.Contains([]string{"RUNNING"}, cluster.Get("status").String()) // Get cluster credentials gcloud.Runf(t, "container clusters get-credentials %s --location %s --project %s", clusterName, location, projectId) k8sOpts := k8s.KubectlOptions{} CheckPodsRunningInNamespace("arc-systems", t, k8sOpts, assert) CheckPodsRunningInNamespace("arc-runners", t, k8sOpts, assert) }) bpt.Test() } func CheckPodsRunningInNamespace(namespace string, t *testing.T, k8sOpts k8s.KubectlOptions, assert *assert.Assertions) { pods, err := k8s.RunKubectlAndGetOutputE(t, &k8sOpts, "get", "pods", "-n", namespace, "-o", "json") if err != nil { t.Fatalf("Error getting pods: %s", err) } statuses := gjson.Get(pods, "items.#.status.phase") for _, status := range statuses.Array() { assert.Equal("Running", status.String()) } } ================================================ FILE: test/integration/gh-runner-gke-simple/gh_runner_gke_simple_test.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gh_runner_gke_simple import ( "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" "github.com/gruntwork-io/terratest/modules/k8s" "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) func TestGhRunnerGkeSimple(t *testing.T) { bpt := tft.NewTFBlueprintTest(t) bpt.DefineVerify(func(assert *assert.Assertions) { bpt.DefaultVerify(assert) // get outputs projectId := bpt.GetStringOutput("project_id") location := bpt.GetStringOutput("location") clusterName := bpt.GetStringOutput("cluster_name") // Check cluster is running cluster := gcloud.Runf(t, "container clusters describe %s --location %s --project %s", clusterName, location, projectId) assert.Contains([]string{"RUNNING"}, cluster.Get("status").String()) // Get cluster credentials gcloud.Runf(t, "container clusters get-credentials %s --location %s --project %s", clusterName, location, projectId) k8sOpts := k8s.KubectlOptions{} CheckPodsRunningInNamespace("arc-systems", t, k8sOpts, assert) CheckPodsRunningInNamespace("arc-runners", t, k8sOpts, assert) }) bpt.Test() } func CheckPodsRunningInNamespace(namespace string, t *testing.T, k8sOpts k8s.KubectlOptions, assert *assert.Assertions) { pods, err := k8s.RunKubectlAndGetOutputE(t, &k8sOpts, "get", "pods", "-n", namespace, "-o", "json") if err != nil { t.Fatalf("Error getting pods: %s", err) } statuses := gjson.Get(pods, "items.#.status.phase") for _, status := range statuses.Array() { assert.Equal("Running", status.String()) } } ================================================ FILE: test/integration/gh-runner-mig-container-vm/gh_runner_mig_container_vm_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package gh_runner_mig_container_vm import ( "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" "github.com/stretchr/testify/assert" ) func TestGHRunnerMIGContainerVM(t *testing.T) { bpt := tft.NewTFBlueprintTest(t) bpt.DefineVerify(func(assert *assert.Assertions) { bpt.DefaultVerify(assert) // get outputs projectId := bpt.GetStringOutput("project_id") migName := bpt.GetStringOutput("mig_name") migInstanceTemplateName := bpt.GetStringOutput("mig_instance_template") // Check mig exists mig := gcloud.Runf(t, "compute instances list --project %s --filter='%s'", projectId, migName) assert.NotNil(t, mig) // Check IT exists it := gcloud.Runf(t, "compute instance-templates list --project %s --filter='%s'", projectId, migInstanceTemplateName) assert.NotNil(t, it) }) bpt.Test() } ================================================ FILE: test/integration/go.mod ================================================ module github.com/terraform-google-modules/terraform-google-github-actions-runners/test/integration go 1.24.0 toolchain go1.24.10 require ( github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9 github.com/gruntwork-io/terratest v0.52.0 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 ) require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/alexflint/go-filemutex v1.3.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 // indirect github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 // indirect github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 // indirect github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 // indirect github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 // indirect github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 // indirect github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 // indirect github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 // indirect github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 // indirect github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 // indirect github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0 // indirect github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 // indirect github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 // indirect github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-errors/errors v1.5.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gruntwork-io/go-commons v0.17.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter/v2 v2.2.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f // indirect github.com/hashicorp/hcl/v2 v2.22.0 // indirect github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7 // indirect github.com/hashicorp/terraform-json v0.26.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pquerna/otp v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect github.com/tmccombs/hcl2json v0.6.4 // indirect github.com/ulikunitz/xz v0.5.14 // indirect github.com/urfave/cli/v2 v2.25.7 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zclconf/go-cty v1.16.3 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.41.0 // indirect golang.org/x/mod v0.27.0 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/term v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.36.0 // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.34.0 // indirect k8s.io/apimachinery v0.34.0 // indirect k8s.io/client-go v0.34.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) ================================================ FILE: test/integration/go.sum ================================================ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9 h1:R7TF5kSOr+6fu9CFCdza5DIFLCQYGrQP923G7SaHd2Y= github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.9/go.mod h1:KfuvXj6g70rv3AI3D0+4aq9Icf/Axu156s6h1JeDJt4= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alexflint/go-filemutex v1.3.0 h1:LgE+nTUWnQCyRKbpoceKZsPQbs84LivvgwUymZXdOcM= github.com/alexflint/go-filemutex v1.3.0/go.mod h1:U0+VA/i30mGBlLCrFPGtTe9y6wGQfNAWPBTekHQ+c8A= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 h1:hqcxMc2g/MwwnRMod9n6Bd+t+9Nf7d5qRg7RaXKPd6o= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41/go.mod h1:d1eH0VrttvPmrCraU68LOyNdu26zFxQFjrVSb5vdhog= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 h1:JX70yGKLj25+lMC5Yyh8wBtvB01GDilyRuJvXJ4piD0= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24/go.mod h1:+Ln60j9SUTD0LEwnhEB0Xhg61DHqplBrbZpLgyjoEHg= github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 h1:fDg0RlN30Xf/yYzEUL/WXqhmgFsjVb/I3230oCfyI5w= github.com/aws/aws-sdk-go-v2/service/acm v1.30.6/go.mod h1:zRR6jE3v/TcbfO8C2P+H0Z+kShiKKVaVyoIl8NQRjyg= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 h1:1KzQVZi7OTixxaVJ8fWaJAUBjme+iQ3zBOCZhE4RgxQ= github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0/go.mod h1:I1+/2m+IhnK5qEbhS3CrzjeiVloo9sItE/2K+so0fkU= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 h1:OREVd94+oXW5a+3SSUAo4K0L5ci8cucCLu+PSiek8OU= github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0/go.mod h1:Qbr4yfpNqVNl69l/GEDK+8wxLf/vHi0ChoiSDzD7thU= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 h1:vucMirlM6D+RDU8ncKaSZ/5dGrXNajozVwpmWNPn2gQ= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1/go.mod h1:fceORfs010mNxZbQhfqUjUeHlTwANmIT4mvHamuUaUg= github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 h1:RhSoBFT5/8tTmIseJUXM6INTXTQDF8+0oyxWBnozIms= github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0/go.mod h1:mzj8EEjIHSN2oZRXiw1Dd+uB4HZTl7hC8nBzX9IZMWw= github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 h1:zg+3FGHA0PBs0KM25qE/rOf2o5zsjNa1g/Qq83+SDI0= github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6/go.mod h1:ZSq54Z9SIsOTf1Efwgw1msilSs4XVEfVQiP9nYVnKpM= github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 h1:7/vgFWplkusJN/m+3QOa+W9FNRqa8ujMPNmdufRaJpg= github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0/go.mod h1:dPTOvmjJQ1T7Q+2+Xs2KSPrMvx+p0rpyV+HsQVnUK4o= github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 h1:hfkzDZHBp9jAT4zcd5mtqckpU4E3Ax0LQaEWWk1VgN8= github.com/aws/aws-sdk-go-v2/service/iam v1.38.1/go.mod h1:u36ahDtZcQHGmVm/r+0L1sfKX4fzLEMdCqiKRKkUMVM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 h1:gvZOjQKPxFXy1ft3QnEyXmT+IqneM9QAUWlM3r0mfqw= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5/go.mod h1:DLWnfvIcm9IET/mmjdxeXbBKmTCm0ZB8p1za9BVteM8= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5 h1:3Y457U2eGukmjYjeHG6kanZpDzJADa2m0ADqnuePYVQ= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5/go.mod h1:CfwEHGkTjYZpkQ/5PvcbEtT7AJlG68KkEvmtwU8z3/U= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 h1:P1doBzv5VEg1ONxnJss1Kh5ZG/ewoIE4MQtKKc6Crgg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5/go.mod h1:NOP+euMW7W3Ukt28tAxPuoWao4rhhqJD3QEBk7oCg7w= github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 h1:CZImQdb1QbU9sGgJ9IswhVkxAcjkkD1eQTMA1KHWk+E= github.com/aws/aws-sdk-go-v2/service/kms v1.37.6/go.mod h1:YJDdlK0zsyxVBxGU48AR/Mi8DMrGdc1E3Yij4fNrONA= github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 h1:BXt75frE/FYtAmEDBJRBa2HexOw+oAZWZl6QknZEFgg= github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0/go.mod h1:guz2K3x4FKSdDaoeB+TPVgJNU9oj2gftbp5cR8ela1A= github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 h1:eqHz3Uih+gb0vLE5Cc4Xf733vOxsxDp6GFUUVQU4d7w= github.com/aws/aws-sdk-go-v2/service/rds v1.91.0/go.mod h1:h2jc7IleH3xHY7y+h8FH7WAZcz3IVLOB6/jXotIQ/qU= github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 h1:wmt05tPp/CaRZpPV5B4SaJ5TwkHKom07/BzHoLdkY1o= github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2/go.mod h1:d+K9HESMpGb1EU9/UmmpInbGIUcAkwmcY6ZO/A3zZsw= github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0 h1:Q2ax8S21clKOnHhhr933xm3JxdJebql+R7aNo7p7GBQ= github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0/go.mod h1:ralv4XawHjEMaHOWnTFushl0WRqim/gQWesAMF6hTow= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 h1:1KDMKvOKNrpD667ORbZ/+4OgvUoaok1gg/MLzrHF9fw= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6/go.mod h1:DmtyfCfONhOyVAJ6ZMTrDSFIeyCBlEO93Qkfhxwbxu0= github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 h1:lEUtRHICiXsd7VRwRjXaY7MApT2X4Ue0Mrwe6XbyBro= github.com/aws/aws-sdk-go-v2/service/sns v1.33.6/go.mod h1:SODr0Lu3lFdT0SGsGX1TzFTapwveBrT5wztVoYtppm8= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 h1:39WvSrVq9DD6UHkD+fx5x19P5KpRQfNdtgReDVNbelc= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1/go.mod h1:3gwPzC9LER/BTQdQZ3r6dUktb1rSjABF1D3Sr6nS7VU= github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 h1:mADKqoZaodipGgiZfuAjtlcr4IVBtXPZKVjkzUZCCYM= github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0/go.mod h1:l9qF25TzH95FhcIak6e4vt79KE4I7M2Nf59eMUVjj6c= github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-errors/errors v1.5.0 h1:/EuijeGOu7ckFxzhkj4CXJ8JaenxK7bKUxpPYqeLHqQ= github.com/go-errors/errors v1.5.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gruntwork-io/go-commons v0.17.1 h1:2KS9wAqrgeOTWj33DSHzDNJ1FCprptWdLFqej+wB8x0= github.com/gruntwork-io/go-commons v0.17.1/go.mod h1:S98JcR7irPD1bcruSvnqupg+WSJEJ6xaM89fpUZVISk= github.com/gruntwork-io/terratest v0.52.0 h1:7+I3FqEImowIajZ9Qyo5ngr7n2AUINJko6x+KzlWNjU= github.com/gruntwork-io/terratest v0.52.0/go.mod h1:y2Evi+Ac04QpzF3mbRPqrBjipDN7gjqlw6+OZoy2vX4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk= github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws= github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7 h1:NIwoxkIKF4OAbTze/gukXLJqS9MISRXCqn4SnurhZ1I= github.com/hashicorp/terraform-config-inspect v0.0.0-20250731202709-e8a84eebd3e7/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI= github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 h1:drhDO54gdT/a15GBcMRmunZiNcLgPiFIJa23KzmcvcU= github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770/go.mod h1:SO/iHr6q2EzbqRApt+8/E9wqebTwQn5y+UlB04bxzo0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE= k8s.io/api v0.34.0/go.mod h1:YzgkIzOOlhl9uwWCZNqpw6RJy9L2FK4dlJeayUoydug= k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0= k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo= k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= ================================================ FILE: test/integration/oidc-simple/oidc_simple_test.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package oidc_simple import ( "fmt" "testing" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" "github.com/stretchr/testify/assert" ) func TestOIDCSimple(t *testing.T) { oidc := tft.NewTFBlueprintTest(t) oidc.DefineVerify(func(assert *assert.Assertions) { oidc.DefaultVerify(assert) pool := gcloud.Run(t, fmt.Sprintf("beta iam workload-identity-pools describe %s", oidc.GetStringOutput("pool_name"))) assert.Equal("ACTIVE", pool.Get("state").String(), "WI pool is active") provider := gcloud.Run(t, fmt.Sprintf("beta iam workload-identity-pools providers describe %s", oidc.GetStringOutput("provider_name"))) assert.Equal("ACTIVE", provider.Get("state").String(), "WI provider is active") assert.Equal("https://token.actions.githubusercontent.com", provider.Get("oidc.issuerUri").String(), "provider has correct issuer ID") assert.Equal(0, len(provider.Get("oidc.allowedAudiences").Array()), "WI provider has correct number of audiences") expectedAttribMapping := map[string]string{ "attribute.actor": "assertion.actor", "attribute.aud": "assertion.aud", "attribute.repository": "assertion.repository", "google.subject": "assertion.sub", } providerMapping := provider.Get("attributeMapping").Map() assert.Equal(len(expectedAttribMapping), len(providerMapping), "WI provider has correct number of attribute mapping") for k, v := range expectedAttribMapping { assert.Equal(v, providerMapping[k].String(), "has correct mapping") } saBindings := gcloud.Run(t, fmt.Sprintf("iam service-accounts get-iam-policy %s", oidc.GetStringOutput("sa_email"))).Get("bindings").Array() assert.Equal(1, len(saBindings), "SA has one binding") assert.Equal(1, len(saBindings[0].Get("members").Array()), "SA binding has one member") assert.Equal(fmt.Sprintf("principalSet://iam.googleapis.com/%s/attribute.repository/user/repo", oidc.GetStringOutput("pool_name")), saBindings[0].Get("members").Array()[0].String(), "SA binding has correct member") assert.Equal("roles/iam.workloadIdentityUser", saBindings[0].Get("role").String(), "SA binding has correct member") }) oidc.Test() } ================================================ FILE: test/setup/.gitignore ================================================ terraform.tfvars source.sh ================================================ FILE: test/setup/iam.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { int_required_roles = [ "roles/owner" ] } resource "google_service_account" "int_test" { project = module.project.project_id account_id = "ci-account" display_name = "ci-account" } resource "google_project_iam_member" "int_test" { count = length(local.int_required_roles) project = module.project.project_id role = local.int_required_roles[count.index] member = "serviceAccount:${google_service_account.int_test.email}" } resource "google_project_iam_member" "int_test_gke" { count = length(local.int_required_roles) project = module.project-gke.project_id role = local.int_required_roles[count.index] member = "serviceAccount:${google_service_account.int_test.email}" } resource "google_project_iam_member" "int_test_mig_container" { count = length(local.int_required_roles) project = module.project-mig-container-vm.project_id role = local.int_required_roles[count.index] member = "serviceAccount:${google_service_account.int_test.email}" } resource "google_service_account_key" "int_test" { service_account_id = google_service_account.int_test.id } ================================================ FILE: test/setup/main.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ module "project" { source = "terraform-google-modules/project-factory/google" version = "~> 18.0" name = "ci-terraform-gh-runners" random_project_id = "true" org_id = var.org_id folder_id = var.folder_id billing_account = var.billing_account activate_apis = [ "cloudresourcemanager.googleapis.com", "storage-api.googleapis.com", "iam.googleapis.com", "container.googleapis.com", "serviceusage.googleapis.com" ] } module "project-gke" { source = "terraform-google-modules/project-factory/google" version = "~> 18.0" name = "ci-runners-gke" random_project_id = "true" org_id = var.org_id folder_id = var.folder_id billing_account = var.billing_account activate_apis = [ "iam.googleapis.com", "cloudresourcemanager.googleapis.com", "containerregistry.googleapis.com", "container.googleapis.com", "storage-component.googleapis.com", "logging.googleapis.com", "monitoring.googleapis.com", ] } module "project-mig-container-vm" { source = "terraform-google-modules/project-factory/google" version = "~> 18.0" name = "ci-runners-c-mig" random_project_id = "true" org_id = var.org_id folder_id = var.folder_id billing_account = var.billing_account activate_apis = [ "iam.googleapis.com", "cloudresourcemanager.googleapis.com", "containerregistry.googleapis.com", "container.googleapis.com", "storage-component.googleapis.com", "logging.googleapis.com", "monitoring.googleapis.com", ] } ================================================ FILE: test/setup/outputs.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ output "project_id" { value = module.project.project_id } output "project_id_gke" { value = module.project-gke.project_id } output "project_id_mig_container" { value = module.project-mig-container-vm.project_id } output "sa_key" { value = google_service_account_key.int_test.private_key sensitive = true } ================================================ FILE: test/setup/variables.tf ================================================ /** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ variable "org_id" { description = "The numeric organization id" } variable "folder_id" { description = "The folder to deploy in" } variable "billing_account" { description = "The billing account id associated with the project, e.g. XXXXXX-YYYYYY-ZZZZZZ" } ================================================ FILE: test/setup/versions.tf ================================================ /** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { required_version = ">= 0.13" required_providers { google = { source = "hashicorp/google" version = ">= 3.53.0, < 8" } google-beta = { source = "hashicorp/google-beta" version = ">= 3.53.0, < 8" } } }