├── test ├── .gitignore ├── setup │ ├── .gitignore │ ├── versions.tf │ ├── outputs.tf │ ├── variables.tf │ ├── iam.tf │ └── main.tf └── integration │ ├── discover_test.go │ ├── tfc-agent-mig-vm-packer │ └── tfc_agent_mig_vm_packer_test.go │ ├── tfc-agent-mig-vm-simple │ └── tfc_agent_mig_vm_simple_test.go │ ├── tfc-agent-mig-container-vm-simple │ └── tfc_agent_mig_container_vm_simple_test.go │ ├── tfc-agent-gke-custom │ └── tfc_agent_gke_custom_test.go │ ├── tfc-agent-gke-simple │ └── tfc_agent_gke_simple_test.go │ ├── oidc-simple │ └── oidc_simple_test.go │ └── go.mod ├── examples ├── tfc-agent-gke-custom │ ├── .dockerignore │ ├── .gcloudignore │ ├── providers.tf │ ├── cloudbuild.yaml │ ├── Dockerfile │ ├── variables.tf │ ├── outputs.tf │ ├── main.tf │ └── README.md ├── tfc-agent-mig-vm-packer │ ├── .gcloudignore │ ├── cloudbuild.yaml │ ├── outputs.tf │ ├── startup.sh │ ├── variables.tf │ ├── main.tf │ ├── README.md │ └── packer │ │ └── packer.pkr.hcl ├── tfc-agent-gke-simple │ ├── providers.tf │ ├── variables.tf │ ├── outputs.tf │ ├── README.md │ └── main.tf ├── oidc-simple │ ├── outputs.tf │ ├── README.md │ ├── variables.tf │ └── main.tf ├── tfc-agent-mig-vm-simple │ ├── outputs.tf │ ├── variables.tf │ ├── README.md │ └── main.tf └── tfc-agent-mig-container-vm-simple │ ├── outputs.tf │ ├── variables.tf │ ├── main.tf │ └── README.md ├── assets └── icon.png ├── .github ├── renovate.json ├── release-please.yml ├── trusted-contribution.yml └── workflows │ ├── stale.yml │ └── lint.yaml ├── .dockerignore ├── SECURITY.md ├── CODEOWNERS ├── modules ├── tfc-oidc │ ├── outputs.tf │ ├── versions.tf │ ├── main.tf │ ├── variables.tf │ └── README.md ├── tfc-agent-mig-vm │ ├── versions.tf │ ├── outputs.tf │ ├── scripts │ │ └── startup.sh │ ├── README.md │ ├── variables.tf │ └── main.tf ├── tfc-agent-mig-container-vm │ ├── versions.tf │ ├── outputs.tf │ ├── README.md │ ├── variables.tf │ └── main.tf └── tfc-agent-gke │ ├── versions.tf │ ├── outputs.tf │ ├── README.md │ ├── variables.tf │ └── main.tf ├── .gitignore ├── Makefile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── README.md └── LICENSE /test/.gitignore: -------------------------------------------------------------------------------- 1 | source.sh 2 | -------------------------------------------------------------------------------- /test/setup/.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfvars 2 | source.sh 3 | outputs.env 4 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/.dockerignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | *.tf* 3 | *.tfvars 4 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/.gcloudignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | *.tfstate 3 | *.tf 4 | *.out 5 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/.gcloudignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | *.tfstate 3 | *.tf 4 | *.out 5 | sample-manifests 6 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/HEAD/assets/icon.png -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>GoogleCloudPlatform/cloud-foundation-toolkit//infra/terraform/test-org/github/resources/renovate"] 4 | } 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .terraform 3 | .terraform.d 4 | .kitchen 5 | terraform.tfstate.d 6 | test/fixtures/*/.terraform 7 | test/fixtures/*/terraform.tfstate.d 8 | examples/.kitchen 9 | examples/*/.terraform 10 | examples/*/terraform.tfstate.d 11 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | To report a security issue, please use http://g.co/vulnz. We use 2 | http://g.co/vulnz for our intake, and do coordination and disclosure here on 3 | GitHub (including using GitHub Security Advisory). The Google Security Team will 4 | respond within 5 working days of your report on g.co/vulnz. 5 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # NOTE: This file is automatically generated from values at: 2 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 3 | 4 | * @GoogleCloudPlatform/blueprint-solutions 5 | 6 | # NOTE: GitHub CODEOWNERS locations: 7 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-and-branch-protection 8 | 9 | CODEOWNERS @GoogleCloudPlatform/blueprint-solutions 10 | .github/CODEOWNERS @GoogleCloudPlatform/blueprint-solutions 11 | docs/CODEOWNERS @GoogleCloudPlatform/blueprint-solutions 12 | 13 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | releaseType: terraform-module 16 | handleGHRelease: true 17 | primaryBranch: main 18 | bumpMinorPreMajor: true 19 | -------------------------------------------------------------------------------- /test/integration/discover_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package test 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 21 | ) 22 | 23 | func TestAll(t *testing.T) { 24 | tft.AutoDiscoverAndTest(t) 25 | } 26 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/providers.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | provider "kubernetes" { 18 | host = "https://${module.tfc_agent_gke.kubernetes_endpoint}" 19 | token = data.google_client_config.default.access_token 20 | cluster_ca_certificate = base64decode(module.tfc_agent_gke.ca_certificate) 21 | } 22 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-simple/providers.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | provider "kubernetes" { 18 | host = "https://${module.tfc_agent_gke.kubernetes_endpoint}" 19 | token = data.google_client_config.default.access_token 20 | cluster_ca_certificate = base64decode(module.tfc_agent_gke.ca_certificate) 21 | } 22 | -------------------------------------------------------------------------------- /modules/tfc-oidc/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "pool_name" { 18 | description = "Pool name" 19 | value = google_iam_workload_identity_pool.tfc_pool.name 20 | } 21 | 22 | output "provider_name" { 23 | description = "Provider name" 24 | value = google_iam_workload_identity_pool_provider.tfc_provider.name 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX leaves these everywhere on SMB shares 2 | ._* 3 | 4 | # OSX trash 5 | .DS_Store 6 | 7 | # Python 8 | *.pyc 9 | 10 | # Emacs save files 11 | *~ 12 | \#*\# 13 | .\#* 14 | 15 | # Vim-related files 16 | [._]*.s[a-w][a-z] 17 | [._]s[a-w][a-z] 18 | *.un~ 19 | Session.vim 20 | .netrwhist 21 | 22 | ### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore 23 | 24 | # Local .terraform directories 25 | **/.terraform/* 26 | 27 | # .tfstate files 28 | *.tfstate 29 | *.tfstate.* 30 | 31 | # Crash log files 32 | crash.log 33 | 34 | # Kitchen files 35 | **/inspec.lock 36 | **/.kitchen 37 | **/kitchen.local.yml 38 | **/Gemfile.lock 39 | 40 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 41 | # .tfvars files are managed as part of configuration and so should be included in 42 | # version control. 43 | **/*.tfvars 44 | 45 | credentials.json 46 | 47 | # tf lock file 48 | .terraform.lock.hcl 49 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | - name: "gcr.io/cloud-builders/docker" 17 | args: 18 | [ 19 | "build", 20 | "-t", 21 | "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}:${_VERSION}", 22 | ".", 23 | ] 24 | images: 25 | - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}" 26 | -------------------------------------------------------------------------------- /modules/tfc-oidc/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | version = ">= 3.53, < 7.0.0" 23 | } 24 | } 25 | 26 | provider_meta "google" { 27 | module_name = "blueprints/terraform/terraform-google-tf-cloud-agents:tfc-oidc/v0.2.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/trusted-contribution.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | annotations: 19 | - type: comment 20 | text: "/gcbrun" 21 | trustedContributors: 22 | - release-please[bot] 23 | - renovate[bot] 24 | - renovate-bot 25 | - forking-renovate[bot] 26 | - dependabot[bot] 27 | -------------------------------------------------------------------------------- /test/setup/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | google = { 21 | source = "hashicorp/google" 22 | version = ">= 3.25.0" 23 | } 24 | google-beta = { 25 | source = "hashicorp/google-beta" 26 | version = ">= 3.25.0" 27 | } 28 | tfe = { 29 | source = "hashicorp/tfe" 30 | version = ">= 0.48.0" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | steps: 16 | - name: 'hashicorp/packer:1.11.2' 17 | args: 18 | - init 19 | - -var 20 | - project_id=$PROJECT_ID 21 | - -var 22 | - tfc_agent_version=${_TFC_AGENT_VERSION} 23 | - packer/packer.pkr.hcl 24 | - name: 'hashicorp/packer:1.11.2' 25 | args: 26 | - build 27 | - --force 28 | - -var 29 | - project_id=$PROJECT_ID 30 | - -var 31 | - tfc_agent_version=${_TFC_AGENT_VERSION} 32 | - packer/packer.pkr.hcl 33 | -------------------------------------------------------------------------------- /test/setup/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | value = module.project.project_id 19 | } 20 | 21 | output "sa_key" { 22 | value = google_service_account_key.int_test.private_key 23 | sensitive = true 24 | } 25 | 26 | output "tfc_org_name" { 27 | value = data.tfe_organization.tfc_org.name 28 | } 29 | 30 | output "tfc_agent_image" { 31 | value = "us-central1-docker.pkg.dev/${module.project.project_id}/hashicorp/tfc-agent:latest" 32 | } 33 | 34 | output "source_image" { 35 | value = "tfc-agent-image" 36 | } 37 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | #hadolint ignore=DL3007 16 | FROM hashicorp/tfc-agent:latest 17 | 18 | USER root 19 | 20 | # Downloading gcloud package 21 | RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz 22 | 23 | # Installing the package 24 | RUN mkdir -p /usr/local/gcloud \ 25 | && tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \ 26 | && /usr/local/gcloud/google-cloud-sdk/install.sh 27 | 28 | # Adding the package path to local 29 | ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin 30 | 31 | USER tfc-agent 32 | -------------------------------------------------------------------------------- /examples/oidc-simple/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The project id to create Workload Identity Federation pool and example Service Account" 19 | value = var.project_id 20 | } 21 | 22 | output "pool_name" { 23 | description = "Pool name" 24 | value = module.oidc.pool_name 25 | } 26 | 27 | output "provider_name" { 28 | description = "Provider name" 29 | value = module.oidc.provider_name 30 | } 31 | 32 | output "sa_email" { 33 | description = "Example SA email" 34 | value = google_service_account.sa.email 35 | } 36 | -------------------------------------------------------------------------------- /test/setup/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | variable "org_id" { 17 | description = "The numeric organization id" 18 | type = string 19 | } 20 | 21 | variable "folder_id" { 22 | description = "The folder to deploy in" 23 | type = string 24 | } 25 | 26 | variable "billing_account" { 27 | description = "The billing account id associated with the project, e.g. XXXXXX-YYYYYY-ZZZZZZ" 28 | type = string 29 | } 30 | 31 | variable "tfc_org_name" { 32 | type = string 33 | default = "tfc-integration-sandbox" 34 | description = "Terraform Cloud org name to use" 35 | } 36 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-vm/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | 21 | google = { 22 | source = "hashicorp/google" 23 | version = ">= 3.53, < 7.0.0" 24 | } 25 | google-beta = { 26 | source = "hashicorp/google-beta" 27 | version = ">= 3.53, < 7.0.0" 28 | } 29 | random = { 30 | source = "hashicorp/random" 31 | version = ">= 3.4.3, < 4.0" 32 | } 33 | } 34 | 35 | provider_meta "google" { 36 | module_name = "blueprints/terraform/terraform-google-tf-cloud-agents:tfc-agent-mig-vm/v0.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-container-vm/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | 21 | google = { 22 | source = "hashicorp/google" 23 | version = ">= 3.53, < 7.0.0" 24 | } 25 | google-beta = { 26 | source = "hashicorp/google-beta" 27 | version = ">= 3.53, < 7.0.0" 28 | } 29 | random = { 30 | source = "hashicorp/random" 31 | version = ">= 3.4.3, < 4.0" 32 | } 33 | } 34 | 35 | provider_meta "google" { 36 | module_name = "blueprints/terraform/terraform-google-tf-cloud-agents:tfc-agent-mig-container-vm/v0.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/setup/iam.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | int_required_roles = [ 19 | "roles/owner", 20 | "roles/artifactregistry.admin" 21 | ] 22 | } 23 | 24 | resource "google_service_account" "int_test" { 25 | project = module.project.project_id 26 | account_id = "ci-account" 27 | display_name = "ci-account" 28 | } 29 | 30 | resource "google_project_iam_member" "int_test" { 31 | for_each = toset(local.int_required_roles) 32 | 33 | project = module.project.project_id 34 | role = each.value 35 | member = "serviceAccount:${google_service_account.int_test.email}" 36 | } 37 | 38 | resource "google_service_account_key" "int_test" { 39 | service_account_id = google_service_account.int_test.id 40 | } 41 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-vm/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "mig_instance_group" { 18 | description = "The instance group url of the created MIG" 19 | value = module.mig.instance_group 20 | } 21 | 22 | output "mig_name" { 23 | description = "The name of the MIG" 24 | value = local.instance_name 25 | } 26 | 27 | output "mig_instance_template" { 28 | description = "The name of the MIG Instance Template" 29 | value = module.mig_template.name 30 | } 31 | 32 | output "network_name" { 33 | description = "Name of the VPC" 34 | value = local.network_name 35 | } 36 | 37 | output "service_account_email" { 38 | description = "Service account email used with the MIG template" 39 | value = local.service_account_email 40 | } 41 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-simple/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" 19 | value = var.project_id 20 | } 21 | 22 | output "mig_instance_group" { 23 | description = "The instance group url of the created MIG" 24 | value = module.tfc_agent_mig.mig_instance_group 25 | } 26 | 27 | output "mig_name" { 28 | description = "The name of the MIG" 29 | value = module.tfc_agent_mig.mig_name 30 | } 31 | 32 | output "service_account_email" { 33 | description = "Service account email used with the MIG template" 34 | value = module.tfc_agent_mig.service_account_email 35 | } 36 | 37 | output "mig_instance_template" { 38 | description = "The name of the MIG Instance Template" 39 | value = module.tfc_agent_mig.mig_instance_template 40 | } 41 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-container-vm-simple/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" 19 | value = var.project_id 20 | } 21 | 22 | output "mig_instance_group" { 23 | description = "The instance group url of the created MIG" 24 | value = module.tfc_agent_mig.mig_instance_group 25 | } 26 | 27 | output "mig_name" { 28 | description = "The name of the MIG" 29 | value = module.tfc_agent_mig.mig_name 30 | } 31 | 32 | output "service_account_email" { 33 | description = "Service account email used with the MIG template" 34 | value = module.tfc_agent_mig.service_account_email 35 | } 36 | 37 | output "mig_instance_template" { 38 | description = "The name of the MIG Instance Template" 39 | value = module.tfc_agent_mig.mig_instance_template 40 | } 41 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" 19 | value = var.project_id 20 | } 21 | 22 | output "mig_instance_group" { 23 | description = "The instance group url of the created MIG" 24 | value = module.tfc_agent_mig.mig_instance_group 25 | } 26 | 27 | output "mig_name" { 28 | description = "The name of the MIG" 29 | value = module.tfc_agent_mig.mig_name 30 | } 31 | 32 | output "service_account_email" { 33 | description = "Service account email for GCE used with the MIG template" 34 | value = module.tfc_agent_mig.service_account_email 35 | } 36 | 37 | output "mig_instance_template" { 38 | description = "The name of the MIG Instance Template" 39 | value = module.tfc_agent_mig.mig_instance_template 40 | } 41 | -------------------------------------------------------------------------------- /modules/tfc-agent-gke/versions.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | terraform { 18 | required_version = ">= 1.3" 19 | required_providers { 20 | 21 | google = { 22 | source = "hashicorp/google" 23 | version = ">= 4.3.0, < 7.0.0" 24 | } 25 | 26 | kubernetes = { 27 | source = "hashicorp/kubernetes" 28 | version = ">= 2.0, <3.0" 29 | } 30 | 31 | random = { 32 | source = "hashicorp/random" 33 | version = ">= 3.4.3, < 4.0" 34 | } 35 | } 36 | 37 | provider_meta "google" { 38 | module_name = "blueprints/terraform/terraform-google-tf-cloud-agents:tfc-agent-gke/v0.2.0" 39 | } 40 | } 41 | 42 | provider "kubernetes" { 43 | host = "https://${module.tfc_agent_cluster.endpoint}" 44 | token = data.google_client_config.default.access_token 45 | cluster_ca_certificate = base64decode( 46 | module.tfc_agent_cluster.ca_certificate 47 | ) 48 | } 49 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-container-vm/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "mig_instance_group" { 18 | description = "The instance group url of the created MIG" 19 | value = module.mig.instance_group 20 | } 21 | 22 | output "mig_name" { 23 | description = "The name of the MIG" 24 | value = local.instance_name 25 | } 26 | 27 | output "mig_instance_template" { 28 | description = "The name of the MIG Instance Template" 29 | value = module.mig_template.name 30 | } 31 | 32 | output "network_name" { 33 | description = "Name of the VPC" 34 | value = local.network_name 35 | } 36 | 37 | output "subnet_name" { 38 | description = "Name of the subnet in the VPC" 39 | value = local.subnet_name 40 | } 41 | 42 | output "service_account_email" { 43 | description = "Service account email attached to MIG templates for GCE" 44 | value = local.service_account_email 45 | } 46 | -------------------------------------------------------------------------------- /examples/oidc-simple/README.md: -------------------------------------------------------------------------------- 1 | # OIDC Simple Example 2 | 3 | ## Overview 4 | 5 | This example showcases how to configure [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) using the [tfc-oidc module](../../modules/tfc-oidc/README.md) for a sample Service Account. 6 | 7 | 8 | ## Inputs 9 | 10 | | Name | Description | Type | Default | Required | 11 | |------|-------------|------|---------|:--------:| 12 | | project\_id | The project id to create Workload Identity Federation pool and example Service Account | `string` | n/a | yes | 13 | | role\_list | Google Cloud roles required for the Service Account | `list(string)` |
[
"roles/storage.admin"
]
| no | 14 | | tfc\_org\_name | Terraform Cloud org name where the Workload Identity Federation pool will be attached | `string` | n/a | yes | 15 | | tfc\_project\_name | Terraform Cloud project name where the Workload Identity Federation pool will be attached | `string` | `"GCP OIDC"` | no | 16 | | tfc\_workspace\_name | Terraform Cloud workspace name where the Workload Identity Federation pool will be attached | `string` | `"gcp-oidc"` | no | 17 | 18 | ## Outputs 19 | 20 | | Name | Description | 21 | |------|-------------| 22 | | pool\_name | Pool name | 23 | | project\_id | The project id to create Workload Identity Federation pool and example Service Account | 24 | | provider\_name | Provider name | 25 | | sa\_email | Example SA email | 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2023 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # Install jq 17 | apt-get update 18 | apt-get -y install jq unzip 19 | 20 | secretUri=$(curl -sS "http://metadata.google.internal/computeMetadata/v1/instance/attributes/secret-id" -H "Metadata-Flavor: Google") 21 | # Secrets URI is of the form projects/$PROJECT_NUMBER/secrets/$SECRET_NAME/versions/$SECRET_VERSION 22 | # Split into array based on `/` delimeter 23 | IFS="/" read -r -a secretsConfig <<<"$secretUri" 24 | 25 | # Get SECRET_NAME and SECRET_VERSION 26 | SECRET_NAME=${secretsConfig[3]} 27 | SECRET_VERSION=${secretsConfig[5]} 28 | 29 | # Access secret from secrets manager 30 | secrets=$(gcloud secrets versions access "$SECRET_VERSION" --secret="$SECRET_NAME") 31 | 32 | # Set secrets as env vars 33 | # shellcheck disable=SC2046 34 | 35 | # Use wordsplitting 36 | export $(echo "$secrets" | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") 37 | 38 | # Start agent service 39 | cd /agent || exit 40 | ./tfc-agent 41 | -------------------------------------------------------------------------------- /examples/oidc-simple/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The project id to create Workload Identity Federation pool and example Service Account" 20 | } 21 | 22 | variable "tfc_org_name" { 23 | type = string 24 | description = "Terraform Cloud org name where the Workload Identity Federation pool will be attached" 25 | } 26 | 27 | variable "tfc_project_name" { 28 | type = string 29 | description = "Terraform Cloud project name where the Workload Identity Federation pool will be attached" 30 | default = "GCP OIDC" 31 | } 32 | 33 | variable "tfc_workspace_name" { 34 | type = string 35 | description = "Terraform Cloud workspace name where the Workload Identity Federation pool will be attached" 36 | default = "gcp-oidc" 37 | } 38 | 39 | variable "role_list" { 40 | description = "Google Cloud roles required for the Service Account" 41 | type = list(string) 42 | default = [ 43 | "roles/storage.admin" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-simple/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" 20 | } 21 | 22 | variable "tfc_org_name" { 23 | type = string 24 | description = "Terraform Cloud org name where the agent pool will be created" 25 | } 26 | 27 | variable "tfc_project_name" { 28 | type = string 29 | description = "Terraform Cloud project to use" 30 | default = "GCP agents" 31 | } 32 | 33 | variable "tfc_workspace_name" { 34 | type = string 35 | description = "Terraform Cloud workspace name to be created" 36 | default = "tfc-agent-gke-simple" 37 | } 38 | 39 | variable "tfc_agent_pool_name" { 40 | type = string 41 | description = "Terraform Cloud agent pool name to be created" 42 | default = "tfc-agent-gke-simple-pool" 43 | } 44 | 45 | variable "tfc_agent_pool_token_description" { 46 | type = string 47 | description = "Terraform Cloud agent pool token description" 48 | default = "tfc-agent-gke-simple-pool-token" 49 | } 50 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-simple/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" 20 | } 21 | 22 | variable "tfc_org_name" { 23 | type = string 24 | description = "Terraform Cloud org name where the agent pool will be created" 25 | } 26 | 27 | variable "tfc_project_name" { 28 | type = string 29 | description = "Terraform Cloud project name to be created" 30 | default = "GCP agents" 31 | } 32 | 33 | variable "tfc_workspace_name" { 34 | type = string 35 | description = "Terraform Cloud workspace name to be created" 36 | default = "tfc-agent-mig-vm-simple" 37 | } 38 | 39 | variable "tfc_agent_pool_name" { 40 | type = string 41 | description = "Terraform Cloud agent pool name to be created" 42 | default = "tfc-agent-mig-vm-simple-pool" 43 | } 44 | 45 | variable "tfc_agent_pool_token_description" { 46 | type = string 47 | description = "Terraform Cloud agent pool token description" 48 | default = "tfc-agent-mig-vm-simple-pool-token" 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/github 17 | 18 | name: "Close stale issues" 19 | on: 20 | schedule: 21 | - cron: "0 23 * * *" 22 | 23 | permissions: 24 | contents: read 25 | issues: write 26 | pull-requests: write 27 | actions: write 28 | 29 | jobs: 30 | stale: 31 | if: github.repository_owner == 'GoogleCloudPlatform' || github.repository_owner == 'terraform-google-modules' 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/stale@v10 35 | with: 36 | repo-token: ${{ secrets.GITHUB_TOKEN }} 37 | 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' 38 | 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' 39 | exempt-issue-labels: 'triaged' 40 | exempt-pr-labels: 'dependencies,autorelease: pending' 41 | operations-per-run: 100 42 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-container-vm-simple/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" 20 | } 21 | 22 | variable "tfc_org_name" { 23 | type = string 24 | description = "Terraform Cloud org name where the agent pool will be created" 25 | } 26 | 27 | variable "tfc_project_name" { 28 | type = string 29 | description = "Terraform Cloud project name to be created" 30 | default = "GCP agents" 31 | } 32 | 33 | variable "tfc_workspace_name" { 34 | type = string 35 | description = "Terraform Cloud workspace name to be created" 36 | default = "tfc-agent-mig-container-vm-simple" 37 | } 38 | 39 | variable "tfc_agent_pool_name" { 40 | type = string 41 | description = "Terraform Cloud agent pool name to be created" 42 | default = "tfc-agent-mig-container-vm-simple-pool" 43 | } 44 | 45 | variable "tfc_agent_pool_token_description" { 46 | type = string 47 | description = "Terraform Cloud agent pool token description" 48 | default = "tfc-agent-mig-container-vm-simple-pool-token" 49 | } 50 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" 20 | } 21 | 22 | variable "tfc_org_name" { 23 | type = string 24 | description = "Terraform Cloud org name where the agent pool will be created" 25 | } 26 | 27 | variable "tfc_project_name" { 28 | type = string 29 | description = "Terraform Cloud project to use" 30 | default = "GCP agents" 31 | } 32 | 33 | variable "tfc_workspace_name" { 34 | type = string 35 | description = "Terraform Cloud workspace name to be created" 36 | default = "tfc-agent-gke-custom" 37 | } 38 | 39 | variable "tfc_agent_pool_name" { 40 | type = string 41 | description = "Terraform Cloud agent pool name to be created" 42 | default = "tfc-agent-gke-custom-pool" 43 | } 44 | 45 | variable "tfc_agent_pool_token_description" { 46 | type = string 47 | description = "Terraform Cloud agent pool token description" 48 | default = "tfc-agent-gke-custom-pool-token" 49 | } 50 | 51 | variable "tfc_agent_image" { 52 | type = string 53 | description = "The custom Terraform Cloud agent image to use" 54 | } 55 | -------------------------------------------------------------------------------- /modules/tfc-agent-gke/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "kubernetes_endpoint" { 18 | description = "The GKE cluster endpoint" 19 | sensitive = true 20 | value = module.tfc_agent_cluster.endpoint 21 | } 22 | 23 | output "client_token" { 24 | description = "The bearer token for auth" 25 | sensitive = true 26 | value = base64encode(data.google_client_config.default.access_token) 27 | } 28 | 29 | output "ca_certificate" { 30 | description = "The cluster CA certificate (base64 encoded)" 31 | sensitive = true 32 | value = module.tfc_agent_cluster.ca_certificate 33 | } 34 | 35 | output "service_account" { 36 | description = "The default service account used for TFC agent nodes" 37 | value = module.tfc_agent_cluster.service_account 38 | } 39 | 40 | output "cluster_name" { 41 | description = "GKE cluster name" 42 | value = module.tfc_agent_cluster.name 43 | } 44 | 45 | output "network_name" { 46 | description = "Name of the VPC" 47 | value = local.network_name 48 | } 49 | 50 | output "subnet_name" { 51 | description = "Name of the subnet in the VPC" 52 | value = local.subnet_name 53 | } 54 | 55 | output "location" { 56 | description = "GKE cluster location" 57 | value = module.tfc_agent_cluster.location 58 | } 59 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" 19 | value = var.project_id 20 | } 21 | 22 | output "kubernetes_endpoint" { 23 | description = "The cluster endpoint" 24 | sensitive = true 25 | value = module.tfc_agent_gke.kubernetes_endpoint 26 | } 27 | 28 | output "ca_certificate" { 29 | description = "The cluster CA certificate (base64 encoded)" 30 | sensitive = true 31 | value = module.tfc_agent_gke.ca_certificate 32 | } 33 | 34 | output "service_account" { 35 | description = "The default service account used for TFC agent nodes" 36 | value = module.tfc_agent_gke.service_account 37 | } 38 | 39 | output "cluster_name" { 40 | description = "GKE cluster name" 41 | value = module.tfc_agent_gke.cluster_name 42 | } 43 | 44 | output "network_name" { 45 | description = "Name of the VPC" 46 | value = module.tfc_agent_gke.network_name 47 | } 48 | 49 | output "subnet_name" { 50 | description = "Name of the subnet in the VPC" 51 | value = module.tfc_agent_gke.subnet_name 52 | } 53 | 54 | output "location" { 55 | description = "GKE cluster location" 56 | value = module.tfc_agent_gke.location 57 | } 58 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-simple/outputs.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | output "project_id" { 18 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" 19 | value = var.project_id 20 | } 21 | 22 | output "kubernetes_endpoint" { 23 | description = "The GKE cluster endpoint" 24 | sensitive = true 25 | value = module.tfc_agent_gke.kubernetes_endpoint 26 | } 27 | 28 | output "ca_certificate" { 29 | description = "The cluster CA certificate (base64 encoded)" 30 | sensitive = true 31 | value = module.tfc_agent_gke.ca_certificate 32 | } 33 | 34 | output "service_account" { 35 | description = "The default service account used for TFC agent nodes" 36 | value = module.tfc_agent_gke.service_account 37 | } 38 | 39 | output "cluster_name" { 40 | description = "GKE cluster name" 41 | value = module.tfc_agent_gke.cluster_name 42 | } 43 | 44 | output "network_name" { 45 | description = "Name of the VPC" 46 | value = module.tfc_agent_gke.network_name 47 | } 48 | 49 | output "subnet_name" { 50 | description = "Name of the subnet in the VPC" 51 | value = module.tfc_agent_gke.subnet_name 52 | } 53 | 54 | output "location" { 55 | description = "GKE cluster location" 56 | value = module.tfc_agent_gke.location 57 | } 58 | -------------------------------------------------------------------------------- /test/setup/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | module "project" { 18 | source = "terraform-google-modules/project-factory/google" 19 | version = "~> 17.0" 20 | 21 | name = "ci-tf-cloud-agents" 22 | random_project_id = "true" 23 | org_id = var.org_id 24 | folder_id = var.folder_id 25 | billing_account = var.billing_account 26 | auto_create_network = true 27 | deletion_policy = "DELETE" 28 | 29 | activate_apis = [ 30 | "artifactregistry.googleapis.com", 31 | "cloudresourcemanager.googleapis.com", 32 | "compute.googleapis.com", 33 | "container.googleapis.com", 34 | "iam.googleapis.com", 35 | "serviceusage.googleapis.com", 36 | "secretmanager.googleapis.com", 37 | "storage-api.googleapis.com", 38 | ] 39 | } 40 | 41 | data "tfe_organization" "tfc_org" { 42 | name = var.tfc_org_name 43 | } 44 | 45 | resource "google_artifact_registry_repository" "hashicorp" { 46 | project = module.project.project_id 47 | location = "us-central1" 48 | repository_id = "hashicorp" 49 | description = "HashiCorp Docker repository" 50 | format = "DOCKER" 51 | } 52 | 53 | resource "local_file" "env_file" { 54 | filename = "${path.module}/outputs.env" 55 | content = < Security > Agents. 29 | 30 | 1. Create additonal workspaces or use the existing workspace to run Terraform through the Terraform Cloud agent.[Click here for more info on running the workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_run#example-usage). 31 | 32 | 33 | ## Inputs 34 | 35 | | Name | Description | Type | Default | Required | 36 | |------|-------------|------|---------|:--------:| 37 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | `string` | n/a | yes | 38 | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-mig-container-vm-simple-pool"` | no | 39 | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-mig-container-vm-simple-pool-token"` | no | 40 | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | 41 | | tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents"` | no | 42 | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-mig-container-vm-simple"` | no | 43 | 44 | ## Outputs 45 | 46 | | Name | Description | 47 | |------|-------------| 48 | | mig\_instance\_group | The instance group url of the created MIG | 49 | | mig\_instance\_template | The name of the MIG Instance Template | 50 | | mig\_name | The name of the MIG | 51 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | 52 | | service\_account\_email | Service account email used with the MIG template | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-simple/README.md: -------------------------------------------------------------------------------- 1 | # Example Terraform Cloud agent on Managed Instance Group 2 | 3 | ## Overview 4 | 5 | This example showcases how to use startup scripts to deploy a Terraform Cloud agent using the `tfc-agent-mig-vm` module. 6 | 7 | It creates the Terraform Cloud agent pool, registers the agent to that pool and creates a project and an empty workspace with the agent attached using startup/shutdown scripts to install the Terraform Cloud agent binary, register the agent when it comes online. 8 | 9 | ## Steps to deploy this example 10 | 11 | 1. Create terraform.tfvars file with the necessary values. The Terraform Cloud agent token you would like to use. NOTE: This is a secret and should be marked as sensitive in Terraform Cloud. 12 | 13 | ```tf 14 | project_id = "your-project-id" 15 | tfc_org_name = "your-tfc-org-name" 16 | ``` 17 | 18 | 1. Create the infrastructure. 19 | 20 | ```sh 21 | terraform init 22 | terraform plan 23 | terraform apply 24 | ``` 25 | 26 | 1. Your Terraform Cloud agents should become active at Organization Setting > Security > Agents. 27 | 28 | 1. Create additonal workspaces or use the existing workspace to run Terraform through the Terraform Cloud agent.[Click here for more info on running the workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_run#example-usage). 29 | 30 | 31 | ## Inputs 32 | 33 | | Name | Description | Type | Default | Required | 34 | |------|-------------|------|---------|:--------:| 35 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | `string` | n/a | yes | 36 | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-mig-vm-simple-pool"` | no | 37 | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-mig-vm-simple-pool-token"` | no | 38 | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | 39 | | tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents"` | no | 40 | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-mig-vm-simple"` | no | 41 | 42 | ## Outputs 43 | 44 | | Name | Description | 45 | |------|-------------| 46 | | mig\_instance\_group | The instance group url of the created MIG | 47 | | mig\_instance\_template | The name of the MIG Instance Template | 48 | | mig\_name | The name of the MIG | 49 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | 50 | | service\_account\_email | Service account email used with the MIG template | 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/integration/oidc-simple/oidc_simple_test.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package oidc_simple 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | "time" 23 | 24 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" 25 | "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" 26 | "github.com/stretchr/testify/assert" 27 | ) 28 | 29 | func TestOidcSimple(t *testing.T) { 30 | bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) 31 | 32 | bpt.DefineVerify(func(assert *assert.Assertions) { 33 | bpt.DefaultVerify(assert) 34 | 35 | projectId := bpt.GetStringOutput("project_id") 36 | poolName := bpt.GetStringOutput("pool_name") 37 | providerName := bpt.GetStringOutput("provider_name") 38 | saEmail := bpt.GetStringOutput("sa_email") 39 | 40 | gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--format=json"}) 41 | op := gcloud.Run(t, fmt.Sprintf("iam workload-identity-pools describe %s --location=global", poolName), gcloudArgs) 42 | 43 | assert.Equal(op.Get("name").String(), poolName, "Workload Identity Poo should have the right name") 44 | assert.Equal(op.Get("description").String(), "Workload Identity Pool managed by Terraform", "Description should match to show WIP managed by Terraform") 45 | assert.Equal(op.Get("state").String(), "ACTIVE", "Workload Identity Pool status should be ACTIVE") 46 | 47 | op = gcloud.Run(t, fmt.Sprintf("iam workload-identity-pools providers describe %s --workload-identity-pool=%s --location=global",providerName, poolName), gcloudArgs) 48 | assert.Equal(op.Get("name").String(), providerName, "Workload Identity Poo should have the right name") 49 | assert.Equal(op.Get("oidc.issuerUri").String(), "https://app.terraform.io", "OIDC issuer should match with Terraform Cloud's endpoint") 50 | assert.Equal(op.Get("state").String(), "ACTIVE", "Workload Identity Pool status should be ACTIVE") 51 | 52 | op = gcloud.Run(t, fmt.Sprintf("iam service-accounts get-iam-policy %s",saEmail), gcloudArgs) 53 | assert.Equal(op.Get("bindings.0.role").String(), "roles/iam.workloadIdentityUser", "Service Account should have workloadIdentityUser role") 54 | }) 55 | 56 | bpt.Test() 57 | } 58 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-simple/README.md: -------------------------------------------------------------------------------- 1 | # Simple Self Hosted Terraform Cloud agent on GKE 2 | 3 | ## Overview 4 | 5 | This example shows how to deploy Terraform Cloud agents on Google Kubernetes Engine (GKE) using the `tfc-agent-gke` module. 6 | 7 | It creates the Terraform Cloud agent pool, registers the agent to that pool and creates a project and an empty workspace with the agent attached. 8 | 9 | ## Prerequisites 10 | 11 | The tools needed to build this example are available by default in Google Cloud Shell. 12 | 13 | If running from your own system, you will need: 14 | 15 | - [Terraform](https://developer.hashicorp.com/terraform/downloads) 16 | 17 | ## Steps to deploy this example 18 | 19 | 1. Create terraform.tfvars file with the necessary values. 20 | 21 | The Terraform Cloud agent token you would like to use. NOTE: This is a secret and should be marked as sensitive in Terraform Cloud. 22 | 23 | ```tf 24 | project_id = "your-project-id" 25 | tfc_org_name = "your-tfc-org-name" 26 | ``` 27 | 28 | 1. Create the infrastructure. 29 | 30 | ```sh 31 | terraform init 32 | terraform plan 33 | terraform apply 34 | ``` 35 | 36 | 1. Your Terraform Cloud agents should become active at Organization Setting > Security > Agents. 37 | 38 | 1. Create additonal workspaces or use the existing workspace to run Terraform through the Terraform Cloud agent. [Click here for more info on running the workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_run#example-usage). 39 | 40 | 41 | ## Inputs 42 | 43 | | Name | Description | Type | Default | Required | 44 | |------|-------------|------|---------|:--------:| 45 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | `string` | n/a | yes | 46 | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-gke-simple-pool"` | no | 47 | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-gke-simple-pool-token"` | no | 48 | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | 49 | | tfc\_project\_name | Terraform Cloud project to use | `string` | `"GCP agents"` | no | 50 | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-gke-simple"` | no | 51 | 52 | ## Outputs 53 | 54 | | Name | Description | 55 | |------|-------------| 56 | | ca\_certificate | The cluster CA certificate (base64 encoded) | 57 | | cluster\_name | GKE cluster name | 58 | | kubernetes\_endpoint | The GKE cluster endpoint | 59 | | location | GKE cluster location | 60 | | network\_name | Name of the VPC | 61 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | 62 | | service\_account | The default service account used for TFC agent nodes | 63 | | subnet\_name | Name of the subnet in the VPC | 64 | 65 | 66 | -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2023-2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: This file is automatically generated from values at: 16 | # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/test-org/org/locals.tf 17 | 18 | name: 'lint' 19 | 20 | on: 21 | workflow_dispatch: 22 | pull_request: 23 | types: [opened, edited, reopened, synchronize] 24 | branches: [main] 25 | 26 | permissions: 27 | contents: read 28 | 29 | concurrency: 30 | group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}' 31 | cancel-in-progress: true 32 | 33 | jobs: 34 | lint: 35 | name: 'lint' 36 | runs-on: 'ubuntu-latest' 37 | steps: 38 | - uses: 'actions/checkout@v6' 39 | - id: variables 40 | run: | 41 | MAKEFILE=$(find . -name Makefile -print -quit) 42 | if [ -z "$MAKEFILE" ]; then 43 | echo dev-tools=gcr.io/cloud-foundation-cicd/cft/developer-tools:1 >> "$GITHUB_OUTPUT" 44 | else 45 | VERSION=$(grep "DOCKER_TAG_VERSION_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 46 | IMAGE=$(grep "DOCKER_IMAGE_DEVELOPER_TOOLS := " $MAKEFILE | cut -d\ -f3) 47 | REGISTRY=$(grep "REGISTRY_URL := " $MAKEFILE | cut -d\ -f3) 48 | echo dev-tools=${REGISTRY}/${IMAGE}:${VERSION} >> "$GITHUB_OUTPUT" 49 | fi 50 | - run: docker run --rm -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} module-swapper 51 | - run: docker run --rm -v ${{ github.workspace }}:/workspace ${{ steps.variables.outputs.dev-tools }} /usr/local/bin/test_lint.sh 52 | commitlint: 53 | runs-on: ubuntu-latest 54 | steps: 55 | - uses: actions/checkout@v6 56 | with: 57 | fetch-depth: 0 58 | - name: Setup node 59 | uses: actions/setup-node@v6 60 | with: 61 | node-version: lts/* 62 | - name: Install commitlint 63 | run: | 64 | npm install -D @commitlint/cli@20.2.0 @commitlint/config-conventional@20.2.0 65 | echo "module.exports = { extends: ['@commitlint/config-conventional'], rules: {'subject-case': [0], 'header-max-length': [0]} };" > commitlint.config.js 66 | npx commitlint --version 67 | - name: Validate PR commits with commitlint 68 | if: github.event_name == 'pull_request' 69 | env: 70 | TITLE: ${{ github.event.pull_request.title }} 71 | run: 'echo "$TITLE" | npx commitlint --verbose' 72 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-simple/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | # Get the Terraform Cloud organization 18 | data "tfe_organization" "tfc_org" { 19 | name = var.tfc_org_name 20 | } 21 | 22 | # Get the Terraform Cloud organization project, make sure it exists 23 | data "tfe_project" "tfc_project" { 24 | name = var.tfc_project_name 25 | organization = data.tfe_organization.tfc_org.name 26 | } 27 | 28 | locals { 29 | tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" 30 | tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" 31 | network_name = "tfc-vm-simple-${random_string.suffix.result}" 32 | } 33 | 34 | resource "random_string" "suffix" { 35 | length = 4 36 | special = false 37 | upper = false 38 | } 39 | 40 | # Create a new workspace which uses the agent to run Terraform 41 | resource "tfe_workspace" "tfc_workspace" { 42 | name = local.tfc_workspace 43 | organization = data.tfe_organization.tfc_org.name 44 | project_id = data.tfe_project.tfc_project.id 45 | } 46 | 47 | resource "tfe_workspace_settings" "tfc_workspace_settings" { 48 | workspace_id = tfe_workspace.tfc_workspace.id 49 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 50 | execution_mode = "agent" 51 | } 52 | 53 | # Create a new agent pool in organization 54 | resource "tfe_agent_pool" "tfc_agent_pool" { 55 | name = local.tfc_agent_pool 56 | organization = data.tfe_organization.tfc_org.name 57 | } 58 | 59 | # Create a new token for the agent pool 60 | resource "tfe_agent_token" "tfc_agent_token" { 61 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 62 | description = var.tfc_agent_pool_token_description 63 | } 64 | 65 | # Create a new service account 66 | resource "google_service_account" "tfc_agent_service_account" { 67 | project = var.project_id 68 | account_id = "tfc-agent-mig-vm-sa" 69 | display_name = "Terraform Cloud agent VM simple Service Account" 70 | } 71 | 72 | # Create the infrastructure for the agent to run 73 | module "tfc_agent_mig" { 74 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-agent-mig-vm" 75 | version = "~> 0.2" 76 | 77 | project_id = var.project_id 78 | create_network = true 79 | network_name = local.network_name 80 | subnet_name = local.network_name 81 | tfc_agent_token = tfe_agent_token.tfc_agent_token.token 82 | create_service_account = false 83 | service_account_email = google_service_account.tfc_agent_service_account.email 84 | } 85 | -------------------------------------------------------------------------------- /test/integration/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/terraform-google-modules/tf-cloud-agents/test/integration 2 | 3 | go 1.22.7 4 | 5 | toolchain go1.23.4 6 | 7 | require ( 8 | github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test v0.17.3 9 | github.com/stretchr/testify v1.10.0 10 | ) 11 | 12 | require ( 13 | github.com/agext/levenshtein v1.2.3 // indirect 14 | github.com/alexflint/go-filemutex v1.3.0 // indirect 15 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 16 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect 17 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 18 | github.com/go-errors/errors v1.5.0 // indirect 19 | github.com/go-openapi/jsonpointer v0.20.0 // indirect 20 | github.com/go-openapi/jsonreference v0.20.2 // indirect 21 | github.com/go-openapi/swag v0.22.4 // indirect 22 | github.com/golang/protobuf v1.5.4 // indirect 23 | github.com/google/gnostic-models v0.6.8 // indirect 24 | github.com/google/go-cmp v0.6.0 // indirect 25 | github.com/gruntwork-io/terratest v0.48.0 // indirect 26 | github.com/hashicorp/errwrap v1.1.0 // indirect 27 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 28 | github.com/hashicorp/go-getter/v2 v2.2.3 // indirect 29 | github.com/hashicorp/go-multierror v1.1.1 // indirect 30 | github.com/hashicorp/go-safetemp v1.0.0 // indirect 31 | github.com/hashicorp/go-version v1.7.0 // indirect 32 | github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f // indirect 33 | github.com/hashicorp/hcl/v2 v2.22.0 // indirect 34 | github.com/hashicorp/terraform-config-inspect v0.0.0-20241129133400-c404f8227ea6 // indirect 35 | github.com/hashicorp/terraform-json v0.23.0 // indirect 36 | github.com/jinzhu/copier v0.4.0 // indirect 37 | github.com/josharian/intern v1.0.0 // indirect 38 | github.com/klauspost/compress v1.16.7 // indirect 39 | github.com/mailru/easyjson v0.7.7 // indirect 40 | github.com/mattn/go-shellwords v1.0.12 // indirect 41 | github.com/mattn/go-zglob v0.0.4 // indirect 42 | github.com/mitchellh/go-homedir v1.1.0 // indirect 43 | github.com/mitchellh/go-testing-interface v1.14.2-0.20210821155943-2d9075ca8770 // indirect 44 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 45 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 46 | github.com/tidwall/gjson v1.18.0 // indirect 47 | github.com/tidwall/match v1.1.1 // indirect 48 | github.com/tidwall/pretty v1.2.1 // indirect 49 | github.com/tidwall/sjson v1.2.5 // indirect 50 | github.com/tmccombs/hcl2json v0.6.4 // indirect 51 | github.com/ulikunitz/xz v0.5.11 // indirect 52 | github.com/zclconf/go-cty v1.15.0 // indirect 53 | golang.org/x/crypto v0.31.0 // indirect 54 | golang.org/x/mod v0.22.0 // indirect 55 | golang.org/x/net v0.31.0 // indirect 56 | golang.org/x/sync v0.10.0 // indirect 57 | golang.org/x/sys v0.28.0 // indirect 58 | golang.org/x/text v0.21.0 // indirect 59 | golang.org/x/tools v0.22.0 // indirect 60 | google.golang.org/protobuf v1.35.1 // indirect 61 | gopkg.in/yaml.v3 v3.0.1 // indirect 62 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect 63 | sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect 64 | sigs.k8s.io/yaml v1.4.0 // indirect 65 | ) 66 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-simple/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | data "google_client_config" "default" { 18 | } 19 | 20 | # Get the Terraform Cloud organization 21 | data "tfe_organization" "tfc_org" { 22 | name = var.tfc_org_name 23 | } 24 | 25 | # Get the Terraform Cloud organization project, make sure it exists 26 | data "tfe_project" "tfc_project" { 27 | name = var.tfc_project_name 28 | organization = data.tfe_organization.tfc_org.name 29 | } 30 | 31 | locals { 32 | tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" 33 | tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" 34 | network_name = "tfc-gke-simple-${random_string.suffix.result}" 35 | } 36 | 37 | resource "random_string" "suffix" { 38 | length = 4 39 | special = false 40 | upper = false 41 | } 42 | 43 | # Create a new workspace which uses the agent to run Terraform 44 | resource "tfe_workspace" "tfc_workspace" { 45 | name = local.tfc_workspace 46 | organization = data.tfe_organization.tfc_org.name 47 | project_id = data.tfe_project.tfc_project.id 48 | } 49 | 50 | resource "tfe_workspace_settings" "tfc_workspace_settings" { 51 | workspace_id = tfe_workspace.tfc_workspace.id 52 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 53 | execution_mode = "agent" 54 | } 55 | 56 | # Create a new agent pool in organization 57 | resource "tfe_agent_pool" "tfc_agent_pool" { 58 | name = local.tfc_agent_pool 59 | organization = data.tfe_organization.tfc_org.name 60 | } 61 | 62 | # Create a new token for the agent pool 63 | resource "tfe_agent_token" "tfc_agent_token" { 64 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 65 | description = var.tfc_agent_pool_token_description 66 | } 67 | 68 | # Create a new service account for the GKE cluster 69 | resource "google_service_account" "tfc_agent_service_account" { 70 | project = var.project_id 71 | account_id = "tfc-agent-gke-simple" 72 | display_name = "Terraform Cloud agent GKE Service Account" 73 | } 74 | 75 | # Create the infrastructure for the agent to run 76 | module "tfc_agent_gke" { 77 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-agent-gke" 78 | version = "~> 0.2" 79 | 80 | create_network = true 81 | network_name = local.network_name 82 | subnet_name = local.network_name 83 | project_id = var.project_id 84 | tfc_agent_token = tfe_agent_token.tfc_agent_token.token 85 | create_service_account = false 86 | service_account_email = google_service_account.tfc_agent_service_account.email 87 | } 88 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | data "tfe_organization" "tfc_org" { 18 | name = var.tfc_org_name 19 | } 20 | 21 | # Get the Terraform Cloud organization project, make sure it exists 22 | data "tfe_project" "tfc_project" { 23 | name = var.tfc_project_name 24 | organization = data.tfe_organization.tfc_org.name 25 | } 26 | 27 | locals { 28 | tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" 29 | tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" 30 | network_name = "tfc-vm-packer-${random_string.suffix.result}" 31 | } 32 | 33 | resource "random_string" "suffix" { 34 | length = 4 35 | special = false 36 | upper = false 37 | } 38 | 39 | # Create a new workspace which uses the agent to run Terraform 40 | resource "tfe_workspace" "tfc_workspace" { 41 | name = local.tfc_workspace 42 | organization = data.tfe_organization.tfc_org.name 43 | project_id = data.tfe_project.tfc_project.id 44 | } 45 | 46 | resource "tfe_workspace_settings" "tfc_workspace_settings" { 47 | workspace_id = tfe_workspace.tfc_workspace.id 48 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 49 | execution_mode = "agent" 50 | } 51 | 52 | # Create a new agent pool in organization 53 | resource "tfe_agent_pool" "tfc_agent_pool" { 54 | name = local.tfc_agent_pool 55 | organization = data.tfe_organization.tfc_org.name 56 | } 57 | 58 | # Create a new token for the agent pool 59 | resource "tfe_agent_token" "tfc_agent_token" { 60 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 61 | description = var.tfc_agent_pool_token_description 62 | } 63 | 64 | # Create a new service account 65 | resource "google_service_account" "tfc_agent_service_account" { 66 | project = var.project_id 67 | account_id = "tfc-agent-mig-vm-psa" 68 | display_name = "Terraform Cloud agent VM packer Service Account" 69 | } 70 | 71 | # Create the infrastructure for the agent to run 72 | module "tfc_agent_mig" { 73 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-agent-mig-vm" 74 | version = "~> 0.2" 75 | 76 | create_network = true 77 | network_name = local.network_name 78 | subnet_name = local.network_name 79 | project_id = var.project_id 80 | source_image = var.source_image 81 | source_image_project = var.source_image_project != null ? var.source_image_project : var.project_id 82 | startup_script = file("${path.cwd}/startup.sh") 83 | tfc_agent_token = tfe_agent_token.tfc_agent_token.token 84 | create_service_account = false 85 | service_account_email = google_service_account.tfc_agent_service_account.email 86 | } 87 | -------------------------------------------------------------------------------- /modules/tfc-oidc/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | attribute_condition = var.attribute_condition == "" ? "assertion.sub.startsWith(\"organization:${var.tfc_organization_name}:project:${var.tfc_project_name}:workspace:${var.tfc_workspace_name}\")" : var.attribute_condition 19 | } 20 | 21 | # Enables the required services in the project. 22 | # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_service 23 | resource "google_project_service" "services" { 24 | project = var.project_id 25 | count = length(var.service_list) 26 | service = var.service_list[count.index] 27 | disable_on_destroy = false 28 | } 29 | 30 | # Creates a workload identity pool to house a workload identity pool provider. 31 | # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool 32 | resource "google_iam_workload_identity_pool" "tfc_pool" { 33 | project = var.project_id 34 | workload_identity_pool_id = var.pool_id 35 | display_name = var.pool_display_name 36 | description = var.pool_description 37 | disabled = false 38 | } 39 | 40 | # Creates an identity pool provider which uses an attribute condition 41 | # to ensure that only the specified Terraform Cloud workspace will be 42 | # able to authenticate to GCP using this provider. 43 | # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider 44 | resource "google_iam_workload_identity_pool_provider" "tfc_provider" { 45 | project = var.project_id 46 | workload_identity_pool_id = google_iam_workload_identity_pool.tfc_pool.workload_identity_pool_id 47 | workload_identity_pool_provider_id = var.provider_id 48 | display_name = var.provider_display_name 49 | description = var.provider_description 50 | attribute_mapping = var.attribute_mapping 51 | attribute_condition = local.attribute_condition 52 | oidc { 53 | issuer_uri = var.issuer_uri 54 | allowed_audiences = var.allowed_audiences 55 | } 56 | } 57 | 58 | # Allows the service account to act as a workload identity user. 59 | # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam 60 | resource "google_service_account_iam_member" "tfc_service_account_member" { 61 | for_each = var.sa_mapping 62 | service_account_id = each.value.sa_name 63 | role = "roles/iam.workloadIdentityUser" 64 | member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.tfc_pool.name}/${each.value.attribute}" 65 | } 66 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Please note that this file was generated from [terraform-google-module-template](https://github.com/terraform-google-modules/terraform-google-module-template). 16 | # Please make sure to contribute relevant changes upstream! 17 | 18 | # Make will use bash instead of sh 19 | SHELL := /usr/bin/env bash 20 | 21 | DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.23 22 | DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools 23 | REGISTRY_URL := gcr.io/cloud-foundation-cicd 24 | 25 | # Enter docker container for local development 26 | .PHONY: docker_run 27 | docker_run: 28 | docker run --rm -it \ 29 | -e SERVICE_ACCOUNT_JSON \ 30 | -v "$(CURDIR)":/workspace \ 31 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 32 | /bin/bash 33 | 34 | # Execute prepare tests within the docker container 35 | .PHONY: docker_test_prepare 36 | docker_test_prepare: 37 | docker run --rm -it \ 38 | -e SERVICE_ACCOUNT_JSON \ 39 | -e TF_VAR_org_id \ 40 | -e TF_VAR_folder_id \ 41 | -e TF_VAR_billing_account \ 42 | -v "$(CURDIR)":/workspace \ 43 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 44 | /usr/local/bin/execute_with_credentials.sh prepare_environment 45 | 46 | # Clean up test environment within the docker container 47 | .PHONY: docker_test_cleanup 48 | docker_test_cleanup: 49 | docker run --rm -it \ 50 | -e SERVICE_ACCOUNT_JSON \ 51 | -e TF_VAR_org_id \ 52 | -e TF_VAR_folder_id \ 53 | -e TF_VAR_billing_account \ 54 | -v "$(CURDIR)":/workspace \ 55 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 56 | /usr/local/bin/execute_with_credentials.sh cleanup_environment 57 | 58 | # Execute integration tests within the docker container 59 | .PHONY: docker_test_integration 60 | docker_test_integration: 61 | docker run --rm -it \ 62 | -e SERVICE_ACCOUNT_JSON \ 63 | -v "$(CURDIR)":/workspace \ 64 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 65 | /usr/local/bin/test_integration.sh 66 | 67 | # Execute lint tests within the docker container 68 | .PHONY: docker_test_lint 69 | docker_test_lint: 70 | docker run --rm -it \ 71 | -e EXCLUDE_LINT_DIRS \ 72 | -v "$(CURDIR)":/workspace \ 73 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 74 | /usr/local/bin/test_lint.sh 75 | 76 | # Generate documentation 77 | .PHONY: docker_generate_docs 78 | docker_generate_docs: 79 | docker run --rm -it \ 80 | -v "$(CURDIR)":/workspace \ 81 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 82 | /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_docs' 83 | 84 | # Generate metadata 85 | .PHONY: docker_generate_metadata_w_display 86 | docker_generate_metadata: 87 | docker run --rm -it \ 88 | -v "$(CURDIR)":/workspace \ 89 | $(REGISTRY_URL)/${DOCKER_IMAGE_DEVELOPER_TOOLS}:${DOCKER_TAG_VERSION_DEVELOPER_TOOLS} \ 90 | /bin/bash -c 'source /usr/local/bin/task_helper_functions.sh && generate_metadata display' 91 | 92 | # Alias for backwards compatibility 93 | .PHONY: generate_docs 94 | generate_docs: docker_generate_docs 95 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | data "google_client_config" "default" { 18 | } 19 | 20 | # Get the Terraform Cloud organization 21 | data "tfe_organization" "tfc_org" { 22 | name = var.tfc_org_name 23 | } 24 | 25 | # Get the Terraform Cloud organization project, make sure it exists 26 | data "tfe_project" "tfc_project" { 27 | name = var.tfc_project_name 28 | organization = data.tfe_organization.tfc_org.name 29 | } 30 | 31 | locals { 32 | tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" 33 | tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" 34 | network_name = "tfc-gke-custom-${random_string.suffix.result}" 35 | } 36 | 37 | resource "random_string" "suffix" { 38 | length = 4 39 | special = false 40 | upper = false 41 | } 42 | 43 | # Create a new workspace which uses the agent to run Terraform 44 | resource "tfe_workspace" "tfc_workspace" { 45 | name = local.tfc_workspace 46 | organization = data.tfe_organization.tfc_org.name 47 | project_id = data.tfe_project.tfc_project.id 48 | } 49 | 50 | resource "tfe_workspace_settings" "tfc_workspace_settings" { 51 | workspace_id = tfe_workspace.tfc_workspace.id 52 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 53 | execution_mode = "agent" 54 | } 55 | 56 | # Create a new agent pool in organization 57 | resource "tfe_agent_pool" "tfc_agent_pool" { 58 | name = local.tfc_agent_pool 59 | organization = data.tfe_organization.tfc_org.name 60 | } 61 | 62 | # Create a new token for the agent pool 63 | resource "tfe_agent_token" "tfc_agent_token" { 64 | agent_pool_id = tfe_agent_pool.tfc_agent_pool.id 65 | description = var.tfc_agent_pool_token_description 66 | } 67 | 68 | # Allow GKE to view storage objects 69 | resource "google_project_iam_member" "gar_viewer" { 70 | project = var.project_id 71 | role = "roles/storage.objectViewer" 72 | member = "serviceAccount:${google_service_account.tfc_agent_service_account.email}" 73 | } 74 | 75 | # Allow GKE to pull images from Google Artifact Registry 76 | resource "google_project_iam_member" "gar_reader" { 77 | project = var.project_id 78 | role = "roles/artifactregistry.reader" 79 | member = "serviceAccount:${google_service_account.tfc_agent_service_account.email}" 80 | } 81 | 82 | # Create a new service account for the GKE cluster 83 | resource "google_service_account" "tfc_agent_service_account" { 84 | project = var.project_id 85 | account_id = "tfc-agent-gke-custom" 86 | display_name = "Terraform Cloud agent GKE Service Account" 87 | } 88 | 89 | # Create the infrastructure for the agent to run 90 | module "tfc_agent_gke" { 91 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-agent-gke" 92 | version = "~> 0.2" 93 | 94 | create_network = true 95 | network_name = local.network_name 96 | subnet_name = local.network_name 97 | project_id = var.project_id 98 | tfc_agent_image = var.tfc_agent_image 99 | tfc_agent_token = tfe_agent_token.tfc_agent_token.token 100 | create_service_account = false 101 | service_account_email = google_service_account.tfc_agent_service_account.email 102 | } 103 | -------------------------------------------------------------------------------- /examples/oidc-simple/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | # Get the Terraform Cloud organization 18 | data "tfe_organization" "tfc_org" { 19 | name = var.tfc_org_name 20 | } 21 | 22 | # Get the Terraform Cloud organization project, make sure it exists 23 | data "tfe_project" "tfc_project" { 24 | name = var.tfc_project_name 25 | organization = data.tfe_organization.tfc_org.name 26 | } 27 | 28 | locals { 29 | tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" 30 | } 31 | 32 | # Random ID for the workload_identity_pool_id 33 | # will avoid errors due to GCP's 30-day hold on deleted pools 34 | resource "random_string" "suffix" { 35 | length = 4 36 | special = false 37 | upper = false 38 | } 39 | 40 | # Create a new workspace which uses the agent to run Terraform 41 | resource "tfe_workspace" "tfc_workspace" { 42 | name = local.tfc_workspace 43 | organization = data.tfe_organization.tfc_org.name 44 | project_id = data.tfe_project.tfc_project.id 45 | } 46 | 47 | # Create a new Service Account in Google Cloud 48 | resource "google_service_account" "sa" { 49 | project = var.project_id 50 | account_id = "terraform-storage-sa" 51 | } 52 | 53 | # Give the service account necessary permissions, 54 | # for ex. storage access - see role_list variable 55 | resource "google_project_iam_member" "project" { 56 | project = var.project_id 57 | for_each = toset(var.role_list) 58 | role = each.value 59 | member = "serviceAccount:${google_service_account.sa.email}" 60 | } 61 | 62 | # The following variables must be set to allow runs 63 | # to authenticate to GCP. 64 | resource "tfe_variable" "enable_gcp_provider_auth" { 65 | workspace_id = tfe_workspace.tfc_workspace.id 66 | key = "TFC_GCP_PROVIDER_AUTH" 67 | value = "true" 68 | category = "env" 69 | 70 | description = "Enable the Workload Identity integration for GCP." 71 | } 72 | 73 | # TFC_GCP_WORKLOAD_PROVIDER_NAME variable contains the project number, 74 | # pool ID, and provider ID 75 | resource "tfe_variable" "tfc_gcp_workload_provider_name" { 76 | workspace_id = tfe_workspace.tfc_workspace.id 77 | key = "TFC_GCP_WORKLOAD_PROVIDER_NAME" 78 | value = module.oidc.provider_name 79 | category = "env" 80 | description = "The workload provider name to authenticate against." 81 | } 82 | 83 | resource "tfe_variable" "tfc_gcp_service_account_email" { 84 | workspace_id = tfe_workspace.tfc_workspace.id 85 | key = "TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL" 86 | value = google_service_account.sa.email 87 | category = "env" 88 | description = "The GCP service account TFC agents will use to authenticate." 89 | } 90 | 91 | # Use the OIDC module to provision the Workload identitly pool 92 | module "oidc" { 93 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-oidc" 94 | version = "~> 0.2" 95 | 96 | project_id = var.project_id 97 | pool_id = "pool-${random_string.suffix.result}" 98 | provider_id = "terraform-provider-${random_string.suffix.result}" 99 | sa_mapping = { 100 | (google_service_account.sa.account_id) = { 101 | sa_name = google_service_account.sa.name 102 | sa_email = google_service_account.sa.email 103 | attribute = "*" 104 | } 105 | } 106 | tfc_organization_name = data.tfe_organization.tfc_org.name 107 | tfc_project_name = data.tfe_project.tfc_project.name 108 | tfc_workspace_name = tfe_workspace.tfc_workspace.name 109 | } 110 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/README.md: -------------------------------------------------------------------------------- 1 | # Example Terraform Cloud agent from Packer image 2 | 3 | ## Overview 4 | 5 | This example showcases how to use Packer to pre-bake a Google VM Image with the necessary toolchain including Terraform Cloud agent and deploy this image using the `tfc-agent-mig` module. 6 | 7 | We use startup script to register the runner when it comes online. 8 | 9 | In this example, Packer creates a VM image that has the following: 10 | 11 | - curl 12 | - jq 13 | - Terraform Cloud agent 14 | 15 | ## Steps to deploy this example 16 | 17 | 1. Give Cloud Build Service Account necessary permissions to create a new GCE VM Image using Packer. 18 | 19 | ```sh 20 | # Export required variables 21 | export PROJECT_ID="your_gcp_project_id" 22 | export TFC_AGENT_VERSION="1.12.0" 23 | 24 | # GCP commands to enable services 25 | gcloud config set project $PROJECT_ID 26 | gcloud services enable compute.googleapis.com 27 | gcloud services enable cloudbuild.googleapis.com 28 | gcloud components update 29 | 30 | # Configure the Service Account for the Google Cloud Build 31 | export CLOUD_BUILD_ACCOUNT=$(gcloud projects get-iam-policy $PROJECT_ID --filter="(bindings.role:roles/cloudbuild.builds.builder)" --flatten="bindings[].members" --format="value(bindings.members[])") 32 | 33 | gcloud projects add-iam-policy-binding $PROJECT_ID --member $CLOUD_BUILD_ACCOUNT --role roles/compute.instanceAdmin.v1 34 | 35 | gcloud projects add-iam-policy-binding $PROJECT_ID --member $CLOUD_BUILD_ACCOUNT --role roles/iam.serviceAccountUser 36 | ``` 37 | 38 | 1. Build GCE VM image. When the build finishes, the image id of the form `tfc-agent-image-*` will be displayed. We will use this in the tfvars we create in the next step. 39 | 40 | ```sh 41 | gcloud builds submit --config=cloudbuild.yaml --substitutions=_TFC_AGENT_VERSION="$TFC_AGENT_VERSION" 42 | ``` 43 | 44 | 1. Create terraform.tfvars file with the necessary values. 45 | 46 | ```tf 47 | project_id = "your-project-id" 48 | tfc_org_name = "your-tfc-org-name" 49 | source_image = "image-name-from-prev-step" 50 | ``` 51 | 52 | 1. Create the infrastructure 53 | 54 | ```sh 55 | terraform init 56 | terraform plan 57 | terraform apply 58 | ``` 59 | 60 | 1. Your Terraform Cloud agents should become active at Organization Setting > Security > Agents. 61 | 62 | 1. Create additonal workspaces or use the existing workspace to run Terraform through the Terraform Cloud agent.[Click here for more info on running the workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_run#example-usage). 63 | 64 | 65 | ## Inputs 66 | 67 | | Name | Description | Type | Default | Required | 68 | |------|-------------|------|---------|:--------:| 69 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | `string` | n/a | yes | 70 | | source\_image | Source disk image | `string` | n/a | yes | 71 | | source\_image\_project | Project where the source image comes from | `string` | `null` | no | 72 | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-mig-vm-packer-pool"` | no | 73 | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-mig-vm-packer-pool-token"` | no | 74 | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | 75 | | tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents"` | no | 76 | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-mig-vm-packer"` | no | 77 | 78 | ## Outputs 79 | 80 | | Name | Description | 81 | |------|-------------| 82 | | mig\_instance\_group | The instance group url of the created MIG | 83 | | mig\_instance\_template | The name of the MIG Instance Template | 84 | | mig\_name | The name of the MIG | 85 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | 86 | | service\_account\_email | Service account email for GCE used with the MIG template | 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # Terraform Cloud agent Packer build for a Google Cloud VM based on Ubuntu 22.04 15 | 16 | packer { 17 | required_version = ">= 1.7.0" 18 | required_plugins { 19 | googlecompute = { 20 | version = "~> 1.0" 21 | source = "github.com/hashicorp/googlecompute" 22 | } 23 | } 24 | } 25 | 26 | variable "disk_size" { 27 | type = number 28 | description = "Size of the disk to create, in GB" 29 | default = 10 30 | } 31 | 32 | variable "disk_type" { 33 | type = string 34 | description = "Type of disk for the build VM" 35 | default = "pd-balanced" 36 | } 37 | 38 | variable "image_family" { 39 | type = string 40 | description = "Image family for the new image" 41 | default = "tfc-agent-image" 42 | } 43 | 44 | variable "machine_type" { 45 | type = string 46 | description = "Machine type for the build VM" 47 | default = "e2-small" 48 | } 49 | 50 | variable "project_id" { 51 | type = string 52 | description = "The Google Cloud project where the image will be built and stored" 53 | default = "${env("PACKER_PROJECT_ID")}" 54 | } 55 | 56 | variable "region" { 57 | type = string 58 | description = "The Google Cloud region where the image will be built" 59 | default = "us-central1" 60 | } 61 | 62 | variable "source_image_family" { 63 | type = string 64 | description = "Source image family for the new custom image" 65 | default = "ubuntu-2204-lts" 66 | } 67 | 68 | variable "source_image_project_id" { 69 | type = string 70 | description = "Project containing the source image" 71 | default = "ubuntu-os-cloud" 72 | } 73 | 74 | variable "ssh_username" { 75 | type = string 76 | description = "User name for SSH provisioner connections" 77 | default = "ubuntu" 78 | } 79 | 80 | variable "tfc_agent_image" { 81 | type = string 82 | description = "The name of the Terraform Cloud image to use" 83 | default = "tfc-agent-image" 84 | } 85 | 86 | variable "tfc_agent_version" { 87 | type = string 88 | description = "Version of the Terraform Cloud agent to install in the image" 89 | default = "${env("TFC_AGENT_VERSION")}" 90 | } 91 | 92 | variable "zone" { 93 | type = string 94 | description = "The zone where the image will be built" 95 | default = "us-central1-a" 96 | } 97 | 98 | source "googlecompute" "agent" { 99 | project_id = var.project_id 100 | source_image_family = var.source_image_family 101 | source_image_project_id = [var.source_image_project_id] 102 | zone = var.zone 103 | machine_type = var.machine_type 104 | disk_size = var.disk_size 105 | disk_type = var.disk_type 106 | ssh_username = var.ssh_username 107 | image_name = var.tfc_agent_image 108 | image_family = var.image_family 109 | 110 | disable_default_service_account = false 111 | } 112 | 113 | build { 114 | sources = ["source.googlecompute.agent"] 115 | 116 | provisioner "shell" { 117 | environment_vars = ["DEBIAN_FRONTEND=noninteractive"] 118 | execute_command = "sudo -S sh -c '{{ .Vars }} {{ .Path }}'" 119 | inline = [ 120 | "apt-get update", 121 | "apt-get dist-upgrade -q -y", 122 | "apt-get update", 123 | "apt-get install -q -y apt-transport-https ca-certificates curl unzip", 124 | "curl -s -O https://releases.hashicorp.com/tfc-agent/${var.tfc_agent_version}/tfc-agent_${var.tfc_agent_version}_linux_amd64.zip", 125 | "mkdir /agent", 126 | "unzip tfc-agent_${var.tfc_agent_version}_linux_amd64.zip -d /agent", 127 | "rm -f tfc-agent_${var.tfc_agent_version}_linux_amd64.zip" 128 | ] 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-container-vm/README.md: -------------------------------------------------------------------------------- 1 | # Self Hosted Terraform Cloud agent on Managed Instance Group Container VMs 2 | 3 | This module handles the opinionated creation of infrastructure necessary to deploy Terraform Cloud agents on MIG Container VMs. 4 | 5 | This includes: 6 | 7 | - Enabling necessary APIs 8 | - VPC 9 | - NAT & Cloud Router 10 | - MIG Container Instance Template 11 | - MIG Instance Manager 12 | - FW Rules 13 | 14 | Below are some examples: 15 | 16 | ## [Simple Self Hosted Terraform Cloud agent](../../examples/tfc-agent-mig-container-vm-simple/README.md) 17 | 18 | This example shows how to deploy a self hosted Terraform Cloud agent on MIG Container VMs. 19 | 20 | 21 | ## Inputs 22 | 23 | | Name | Description | Type | Default | Required | 24 | |------|-------------|------|---------|:--------:| 25 | | additional\_metadata | Additional metadata to attach to the instance | `map(any)` | `{}` | no | 26 | | autoscaling\_enabled | Set to true to enable autoscaling in the MIG | `bool` | `true` | no | 27 | | cooldown\_period | The number of seconds that the autoscaler should wait before it
starts collecting information from a new instance. | `number` | `60` | no | 28 | | create\_network | When set to true, VPC, router and NAT will be auto created | `bool` | `true` | no | 29 | | create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | 30 | | dind | Flag to determine whether to expose dockersock | `bool` | `false` | no | 31 | | image | The Terraform Cloud agent image | `string` | `"hashicorp/tfc-agent:latest"` | no | 32 | | network\_name | Name for the VPC network. Only used if subnetwork\_project and subnet\_name are not specified | `string` | `"tfc-agent-network"` | no | 33 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent | `string` | n/a | yes | 34 | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | 35 | | restart\_policy | The desired Docker restart policy for the agent image | `string` | `"Always"` | no | 36 | | service\_account\_email | Service account email address to use with the MIG template, required if create\_service\_account is set to false | `string` | `""` | no | 37 | | startup\_script | User startup script to run when instances spin up | `string` | `""` | no | 38 | | subnet\_ip | IP range for the subnet | `string` | `"10.10.10.0/24"` | no | 39 | | subnet\_name | Name for the subnet | `string` | `"tfc-agent-subnet"` | no | 40 | | subnetwork\_project | The project ID of the shared VPCs host (for shared vpc support).
If not provided, the project\_id is used | `string` | `""` | no | 41 | | target\_size | The number of Terraform Cloud agent instances | `number` | `2` | no | 42 | | tfc\_agent\_address | The HTTP or HTTPS address of the Terraform Cloud/Enterprise API | `string` | `"https://app.terraform.io"` | no | 43 | | tfc\_agent\_auto\_update | Controls automatic core updates behavior. Acceptable values include disabled, patch, and minor | `string` | `"minor"` | no | 44 | | tfc\_agent\_name\_prefix | This name may be used in the Terraform Cloud user interface to help easily identify the agent | `string` | `"tfc-agent-container-vm"` | no | 45 | | tfc\_agent\_single | Enable single mode. This causes the agent to handle at most one job and
immediately exit thereafter. Useful for running agents as ephemeral
containers, VMs, or other isolated contexts with a higher-level scheduler
or process supervisor. | `bool` | `false` | no | 46 | | tfc\_agent\_token | Terraform Cloud agent token. (Organization Settings >> Agents) | `string` | n/a | yes | 47 | 48 | ## Outputs 49 | 50 | | Name | Description | 51 | |------|-------------| 52 | | mig\_instance\_group | The instance group url of the created MIG | 53 | | mig\_instance\_template | The name of the MIG Instance Template | 54 | | mig\_name | The name of the MIG | 55 | | network\_name | Name of the VPC | 56 | | service\_account\_email | Service account email attached to MIG templates for GCE | 57 | | subnet\_name | Name of the subnet in the VPC | 58 | 59 | 60 | 61 | ## Requirements 62 | 63 | Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 64 | 65 | 1. Required APIs are activated 66 | 67 | ```text 68 | "iam.googleapis.com", 69 | "cloudresourcemanager.googleapis.com", 70 | "containerregistry.googleapis.com", 71 | "storage-component.googleapis.com", 72 | "logging.googleapis.com", 73 | "monitoring.googleapis.com" 74 | ``` 75 | -------------------------------------------------------------------------------- /examples/tfc-agent-gke-custom/README.md: -------------------------------------------------------------------------------- 1 | # Custom Self Hosted Terraform Cloud agent on GKE 2 | 3 | ## Overview 4 | 5 | This example shows how to deploy a custom Terraform Cloud agent image on Google Kubernetes Engine (GKE) using the `tfc-agent-gke` module. 6 | 7 | It creates the Terraform Cloud agent pool, registers the agent to that pool and creates a project and an empty workspace with the agent attached. 8 | 9 | ## Prerequisites 10 | 11 | The tools needed to build this example are available by default in Google Cloud Shell. 12 | 13 | If running from your own system, you will need: 14 | 15 | - [Terraform](https://developer.hashicorp.com/terraform/downloads) 16 | - [Google Cloud CLI (`gcloud`)](https://cloud.google.com/sdk/docs/install-sdk) 17 | - [`gke-gcloud-auth-plugin`](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke) 18 | 19 | ## Steps to deploy this example 20 | 21 | 1. Create terraform.tfvars file with the necessary values. 22 | 23 | The Terraform Cloud agent token you would like to use. NOTE: This is a secret and should be marked as sensitive in Terraform Cloud. 24 | 25 | ```tf 26 | project_id = "your-project-id" 27 | tfc_org_name = "your-tfc-org-name" 28 | ``` 29 | 30 | 1. Build the example Terraform Cloud agent image using Google Cloud Build. Alternatively, you can also use the [tfc-agent-gke-simple](../tfc-agent-gke-simple/README.md) for working with the default Terraform agent image. 31 | 32 | ```sh 33 | # Export required variables 34 | export PROJECT_ID="your-project-id" 35 | export LOCATION="us-west1" 36 | export REPOSITORY="hashicorp" 37 | export IMAGE="tfc-agent" 38 | export VERSION="latest" 39 | 40 | # GCP commands to enable services 41 | gcloud config set project $PROJECT_ID 42 | gcloud services enable cloudbuild.googleapis.com 43 | gcloud services enable artifactregistry.googleapis.com 44 | gcloud components update 45 | 46 | # Create the Google Artifact Repository for storing the agent 47 | gcloud artifacts repositories create $REPOSITORY --location="$LOCATION" --repository-format="DOCKER" 48 | 49 | # Build the custom Terraform Cloud agent image using Cloud Build 50 | gcloud builds submit --config=cloudbuild.yaml \ 51 | --substitutions=_LOCATION="$LOCATION",_REPOSITORY="$REPOSITORY",_IMAGE="$IMAGE",_VERSION="$VERSION" . 52 | ``` 53 | 54 | 1. Initialize the Terraform Cloud agent image for running Terraform. 55 | 56 | ```sh 57 | export TF_VAR_tfc_agent_image=$LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE:$VERSION 58 | ``` 59 | 60 | 1. Create the infrastructure. 61 | 62 | ```sh 63 | terraform init 64 | terraform plan 65 | terraform apply 66 | ``` 67 | 68 | 1. Your Terraform Cloud agents should become active at Organization Setting > Security > Agents. 69 | 70 | 1. Create additonal workspaces or use the existing workspace to run Terraform through the Terraform Cloud agent.[Click here for more info on running the workspace](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs/resources/workspace_run#example-usage). 71 | 72 | 73 | ## Inputs 74 | 75 | | Name | Description | Type | Default | Required | 76 | |------|-------------|------|---------|:--------:| 77 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | `string` | n/a | yes | 78 | | tfc\_agent\_image | The custom Terraform Cloud agent image to use | `string` | n/a | yes | 79 | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-gke-custom-pool"` | no | 80 | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-gke-custom-pool-token"` | no | 81 | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | 82 | | tfc\_project\_name | Terraform Cloud project to use | `string` | `"GCP agents"` | no | 83 | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-gke-custom"` | no | 84 | 85 | ## Outputs 86 | 87 | | Name | Description | 88 | |------|-------------| 89 | | ca\_certificate | The cluster CA certificate (base64 encoded) | 90 | | cluster\_name | GKE cluster name | 91 | | kubernetes\_endpoint | The cluster endpoint | 92 | | location | GKE cluster location | 93 | | network\_name | Name of the VPC | 94 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | 95 | | service\_account | The default service account used for TFC agent nodes | 96 | | subnet\_name | Name of the subnet in the VPC | 97 | 98 | 99 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on 6 | [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 7 | and this project adheres to 8 | [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 9 | This changelog is generated automatically based on [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). 10 | 11 | ## [0.2.0](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/compare/v0.1.2...v0.2.0) (2024-12-07) 12 | 13 | 14 | ### ⚠ BREAKING CHANGES 15 | 16 | * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v34 ([#49](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/49)) 17 | * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v32 ([#39](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/39)) 18 | 19 | ### Features 20 | 21 | * **deps:** Update Terraform Google Provider to v6 (major) ([#41](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/41)) ([3cbfbab](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/3cbfbab25a948440d08e358b5db82f46b515de7c)) 22 | 23 | 24 | ### Bug Fixes 25 | 26 | * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v32 ([#39](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/39)) ([d0938ec](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/d0938ecca7d3e6b58e58bf5e104cf0adba7905d9)) 27 | * **deps:** Update Terraform terraform-google-modules/kubernetes-engine/google to v34 ([#49](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/49)) ([8ec11ba](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/8ec11ba68f6c9dd14461658b0f821fc71b275c90)) 28 | * Update deletion protection for k8s ([#31](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/31)) ([16df0aa](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/16df0aaa5030dea593f76a7b68039b164bab16e7)) 29 | * update project-factory module and tf required version ([#51](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/51)) ([778b8d2](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/778b8d22529a4635a725b32d2404c0c0bb3fbacd)) 30 | * upgrade vm modules ([#53](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/53)) ([eb965ec](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/eb965eca3a1376ea0921a3cefb483b7a1737f32d)) 31 | 32 | ## [0.1.2](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/compare/v0.1.1...v0.1.2) (2024-06-25) 33 | 34 | 35 | ### Bug Fixes 36 | 37 | * **deps:** Update Terraform Google Provider to v5 (major) ([#24](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/24)) ([23de049](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/23de0492c5bc31c793bba0e44f6e6814f0801192)) 38 | 39 | ## [0.1.1](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/compare/v0.1.0...v0.1.1) (2023-10-26) 40 | 41 | 42 | ### Bug Fixes 43 | 44 | * README.md for OIDC module ([#12](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/12)) ([77fbabe](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/77fbabe538827ecb354fd5a1be514ecea528ce0b)) 45 | * Shared VPC architecture deployment and make Autoscaling optional ([#10](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/10)) ([415b2fc](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/415b2fc74af8bd8c49076509501b36f4c9bfbbcd)) 46 | 47 | ## 0.1.0 (2023-08-25) 48 | 49 | 50 | ### Features 51 | 52 | * adding tests for the major submodules ([#3](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/3)) ([330969f](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/330969fe5223e1cfb515427defd73d1d2958d0de)) 53 | * Updating the repository & OIDC module ([#1](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/1)) ([cb1a6c9](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/cb1a6c9dc6ad7d7aa81491123672d0d9a8cff2eb)) 54 | 55 | 56 | ### Bug Fixes 57 | 58 | * update readme and 'Agent' spelling refactor to 'agent' ([#8](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/issues/8)) ([9024beb](https://github.com/GoogleCloudPlatform/terraform-google-tf-cloud-agents/commit/9024beb9b6464532be312dd6a732fe24ab2caf79)) 59 | 60 | ## [0.1.0](https://github.com/terraform-google-modules/terraform-google-tf-cloud-agents/releases/tag/v0.1.0) - 20XX-YY-ZZ 61 | 62 | ### Features 63 | 64 | - Initial release 65 | 66 | [0.1.0]: https://github.com/terraform-google-modules/terraform-google-tf-cloud-agents/releases/tag/v0.1.0 67 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-vm/README.md: -------------------------------------------------------------------------------- 1 | # Self Hosted Terraform Cloud agent on Managed Instance Group 2 | 3 | This module handles the opinionated creation of infrastructure necessary to deploy Terraform Cloud agents on a Managed Instance Group (MIG). 4 | 5 | This includes: 6 | 7 | - Enabling necessary APIs 8 | - VPC 9 | - NAT & Cloud Router 10 | - Service Account for MIG 11 | - MIG Instance Template 12 | - MIG Instance Manager 13 | - FW Rules 14 | - Secret Manager Secret 15 | 16 | Below are some examples: 17 | 18 | ## [Simple Self Hosted Terraform Cloud agent](../../examples/tfc-agent-mig-vm-simple/README.md) 19 | 20 | This example shows how to deploy a MIG self hosted Terraform Cloud agent bootstrapped using startup scripts. 21 | 22 | 23 | ## Inputs 24 | 25 | | Name | Description | Type | Default | Required | 26 | |------|-------------|------|---------|:--------:| 27 | | cooldown\_period | The number of seconds that the autoscaler should wait before it
starts collecting information from a new instance | `number` | `60` | no | 28 | | create\_network | When set to true, VPC, router and NAT will be auto created | `bool` | `true` | no | 29 | | create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | 30 | | custom\_metadata | User provided custom metadata | `map(any)` | `{}` | no | 31 | | machine\_type | The GCP machine type to deploy | `string` | `"n1-standard-1"` | no | 32 | | max\_replicas | Maximum number of Terraform agent instances | `number` | `10` | no | 33 | | min\_replicas | Minimum number of Terraform agent instances | `number` | `1` | no | 34 | | network\_name | Name for the VPC network | `string` | `"tfc-agent-network"` | no | 35 | | network\_project | The project ID of the shared VPCs host (for shared vpc support).
If not provided, the project\_id is used | `string` | `""` | no | 36 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent | `string` | n/a | yes | 37 | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | 38 | | service\_account\_email | Service account email address to use with the MIG template, required if create\_service\_account is set to false | `string` | `""` | no | 39 | | source\_image | Source disk image. If neither source\_image nor source\_image\_family is specified,
defaults to the latest public CentOS image | `string` | `""` | no | 40 | | 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-2204-lts"` | no | 41 | | source\_image\_project | Project where the source image originates | `string` | `"ubuntu-os-cloud"` | no | 42 | | startup\_script | User startup script to run when instances spin up | `string` | `""` | no | 43 | | subnet\_ip | IP range for the subnet | `string` | `"10.10.10.0/24"` | no | 44 | | subnet\_name | Name for the subnet | `string` | `"tfc-agent-subnet"` | no | 45 | | tfc\_agent\_address | The HTTP or HTTPS address of the Terraform Cloud/Enterprise API | `string` | `"https://app.terraform.io"` | no | 46 | | tfc\_agent\_auto\_update | Controls automatic core updates behavior.
Acceptable values include disabled, patch, and minor | `string` | `"minor"` | no | 47 | | tfc\_agent\_labels | Terraform Cloud agent labels to attach to the VMs | `set(string)` | `[]` | no | 48 | | tfc\_agent\_name\_prefix | This name may be used in the Terraform Cloud user interface to help
easily identify the agent | `string` | `"tfc-agent-mig-vm"` | no | 49 | | tfc\_agent\_secret | The secret id for storing the Terraform Cloud agent secret | `string` | `"tfc-agent"` | no | 50 | | tfc\_agent\_single | Enable single mode. This causes the agent to handle at most one job and
immediately exit thereafter. Useful for running agents as ephemeral
containers, VMs, or other isolated contexts with a higher-level scheduler
or process supervisor | `bool` | `false` | no | 51 | | tfc\_agent\_token | Terraform Cloud agent token. (Organization Settings >> Agents) | `string` | n/a | yes | 52 | | tfc\_agent\_version | Terraform Cloud agent version to install | `string` | `"1.12.0"` | no | 53 | 54 | ## Outputs 55 | 56 | | Name | Description | 57 | |------|-------------| 58 | | mig\_instance\_group | The instance group url of the created MIG | 59 | | mig\_instance\_template | The name of the MIG Instance Template | 60 | | mig\_name | The name of the MIG | 61 | | network\_name | Name of the VPC | 62 | | service\_account\_email | Service account email used with the MIG template | 63 | 64 | 65 | 66 | ## Requirements 67 | 68 | Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 69 | 70 | 1. Required APIs are activated 71 | 72 | ```text 73 | "iam.googleapis.com", 74 | "compute.googleapis.com", 75 | "storage-component.googleapis.com", 76 | "logging.googleapis.com", 77 | "monitoring.googleapis.com", 78 | "secretmanager.googleapis.com", 79 | ``` 80 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Development 27 | 28 | The following dependencies must be installed on the development system: 29 | 30 | - [Docker Engine][docker-engine] 31 | - [Google Cloud SDK][google-cloud-sdk] 32 | - [make] 33 | 34 | ### Generating Documentation for Inputs and Outputs 35 | 36 | The Inputs and Outputs tables in the READMEs of the root module, 37 | submodules, and example modules are automatically generated based on 38 | the `variables` and `outputs` of the respective modules. These tables 39 | must be refreshed if the module interfaces are changed. 40 | 41 | #### Execution 42 | 43 | Run `make generate_docs` to generate new Inputs and Outputs tables. 44 | 45 | ### Integration Testing 46 | 47 | Integration tests are used to verify the behaviour of the root module, 48 | submodules, and example modules. Additions, changes, and fixes should 49 | be accompanied with tests. 50 | 51 | The integration tests are run using [Kitchen][kitchen], 52 | [Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These 53 | tools are packaged within a Docker image for convenience. 54 | 55 | The general strategy for these tests is to verify the behaviour of the 56 | [example modules](./examples/), thus ensuring that the root module, 57 | submodules, and example modules are all functionally correct. 58 | 59 | #### Test Environment 60 | 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. 61 | 62 | To use this setup, you need a service account with these permissions (on a Folder or Organization): 63 | - Project Creator 64 | - Project Billing Manager 65 | 66 | The project that the service account belongs to must have the following APIs enabled (the setup won't 67 | create any resources on the service account's project): 68 | - Cloud Resource Manager 69 | - Cloud Billing 70 | - Service Usage 71 | - Identity and Access Management (IAM) 72 | 73 | Export the Service Account credentials to your environment like so: 74 | 75 | ``` 76 | export SERVICE_ACCOUNT_JSON=$(< credentials.json) 77 | ``` 78 | 79 | You will also need to set a few environment variables: 80 | ``` 81 | export TF_VAR_org_id="your_org_id" 82 | export TF_VAR_folder_id="your_folder_id" 83 | export TF_VAR_billing_account="your_billing_account_id" 84 | ``` 85 | 86 | With these settings in place, you can prepare a test project using Docker: 87 | ``` 88 | make docker_test_prepare 89 | ``` 90 | 91 | #### Noninteractive Execution 92 | 93 | Run `make docker_test_integration` to test all of the example modules 94 | noninteractively, using the prepared test project. 95 | 96 | #### Interactive Execution 97 | 98 | 1. Run `make docker_run` to start the testing Docker container in 99 | interactive mode. 100 | 101 | 1. Run `kitchen_do create ` to initialize the working 102 | directory for an example module. 103 | 104 | 1. Run `kitchen_do converge ` to apply the example module. 105 | 106 | 1. Run `kitchen_do verify ` to test the example module. 107 | 108 | 1. Run `kitchen_do destroy ` to destroy the example module 109 | state. 110 | 111 | ### Linting and Formatting 112 | 113 | Many of the files in the repository can be linted or formatted to 114 | maintain a standard of quality. 115 | 116 | #### Execution 117 | 118 | Run `make docker_test_lint`. 119 | 120 | [docker-engine]: https://www.docker.com/products/docker-engine 121 | [flake8]: http://flake8.pycqa.org/en/latest/ 122 | [gofmt]: https://golang.org/cmd/gofmt/ 123 | [google-cloud-sdk]: https://cloud.google.com/sdk/install 124 | [hadolint]: https://github.com/hadolint/hadolint 125 | [inspec]: https://inspec.io/ 126 | [kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform 127 | [kitchen]: https://kitchen.ci/ 128 | [make]: https://en.wikipedia.org/wiki/Make_(software) 129 | [shellcheck]: https://www.shellcheck.net/ 130 | [terraform-docs]: https://github.com/segmentio/terraform-docs 131 | [terraform]: https://terraform.io/ 132 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-container-vm/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent" 20 | } 21 | 22 | variable "region" { 23 | type = string 24 | description = "The GCP region to use when deploying resources" 25 | default = "us-central1" 26 | } 27 | 28 | variable "create_network" { 29 | type = bool 30 | description = "When set to true, VPC, router and NAT will be auto created" 31 | default = true 32 | } 33 | 34 | variable "network_name" { 35 | type = string 36 | description = "Name for the VPC network. Only used if subnetwork_project and subnet_name are not specified" 37 | default = "tfc-agent-network" 38 | } 39 | 40 | variable "subnetwork_project" { 41 | type = string 42 | description = <<-EOF 43 | The project ID of the shared VPCs host (for shared vpc support). 44 | If not provided, the project_id is used 45 | EOF 46 | default = "" 47 | } 48 | 49 | variable "subnet_ip" { 50 | type = string 51 | description = "IP range for the subnet" 52 | default = "10.10.10.0/24" 53 | } 54 | 55 | variable "subnet_name" { 56 | type = string 57 | description = "Name for the subnet" 58 | default = "tfc-agent-subnet" 59 | } 60 | 61 | variable "restart_policy" { 62 | type = string 63 | description = "The desired Docker restart policy for the agent image" 64 | default = "Always" 65 | } 66 | 67 | variable "image" { 68 | type = string 69 | description = "The Terraform Cloud agent image" 70 | default = "hashicorp/tfc-agent:latest" 71 | } 72 | 73 | variable "target_size" { 74 | type = number 75 | description = "The number of Terraform Cloud agent instances" 76 | default = 2 77 | } 78 | 79 | variable "autoscaling_enabled" { 80 | description = "Set to true to enable autoscaling in the MIG" 81 | type = bool 82 | default = true 83 | } 84 | 85 | variable "create_service_account" { 86 | description = "Set to true to create a new service account, false to use an existing one" 87 | type = bool 88 | default = true 89 | } 90 | 91 | variable "service_account_email" { 92 | type = string 93 | description = "Service account email address to use with the MIG template, required if create_service_account is set to false" 94 | default = "" 95 | } 96 | variable "additional_metadata" { 97 | type = map(any) 98 | description = "Additional metadata to attach to the instance" 99 | default = {} 100 | } 101 | 102 | variable "dind" { 103 | type = bool 104 | description = "Flag to determine whether to expose dockersock " 105 | default = false 106 | } 107 | 108 | variable "cooldown_period" { 109 | type = number 110 | description = <<-EOF 111 | The number of seconds that the autoscaler should wait before it 112 | starts collecting information from a new instance. 113 | EOF 114 | default = 60 115 | } 116 | 117 | variable "startup_script" { 118 | type = string 119 | description = "User startup script to run when instances spin up" 120 | default = "" 121 | } 122 | 123 | variable "tfc_agent_address" { 124 | type = string 125 | description = "The HTTP or HTTPS address of the Terraform Cloud/Enterprise API" 126 | default = "https://app.terraform.io" 127 | } 128 | 129 | variable "tfc_agent_single" { 130 | type = bool 131 | default = false 132 | description = <<-EOF 133 | Enable single mode. This causes the agent to handle at most one job and 134 | immediately exit thereafter. Useful for running agents as ephemeral 135 | containers, VMs, or other isolated contexts with a higher-level scheduler 136 | or process supervisor. 137 | EOF 138 | } 139 | 140 | variable "tfc_agent_auto_update" { 141 | type = string 142 | description = "Controls automatic core updates behavior. Acceptable values include disabled, patch, and minor" 143 | default = "minor" 144 | } 145 | 146 | variable "tfc_agent_name_prefix" { 147 | type = string 148 | description = "This name may be used in the Terraform Cloud user interface to help easily identify the agent" 149 | default = "tfc-agent-container-vm" 150 | } 151 | 152 | variable "tfc_agent_token" { 153 | type = string 154 | description = "Terraform Cloud agent token. (Organization Settings >> Agents)" 155 | sensitive = true 156 | } 157 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-google-terraform-cloud-agents 2 | 3 | Creates self hosted Terraform Cloud agents on Google Cloud. Using these Terraform modules you can quickly deploy agent pools for your Terraform Cloud workflows. 4 | 5 | ## [Terraform Cloud agents on GKE](modules/tfc-agent-gke/README.md) 6 | 7 | The `tfc-agent-gke` module provisions the resources required to deploy self hosted Terraform Cloud agents on Google Cloud infrastructure using Google Kubernetes Engine (GKE). 8 | 9 | This includes 10 | 11 | - Enabling necessary APIs 12 | - VPC 13 | - GKE Cluster 14 | - Kubernetes Secret 15 | 16 | *Below are some examples:* 17 | 18 | - [Terraform Cloud agents on GKE](examples/tfc-agent-gke-simple/README.md) - This example shows how to deploy the Terraform Cloud agent on GKE. 19 | - [Terraform Cloud agents on GKE with a custom image](examples/tfc-agent-gke-custom/README.md) - This example shows how to deploy a custom built Terraform Cloud agent image on GKE. 20 | 21 | ## [Terraform Cloud agents on Managed Instance Groups using VMs](modules/tfc-agent-mig-vm/README.md) 22 | 23 | The `tfc-agent-mig-vm` module provisions the resources required to deploy Terrform Cloud agent on Google Cloud infrastructure using Managed Instance Groups (MIG). 24 | 25 | This includes 26 | 27 | - Enabling necessary APIs 28 | - VPC 29 | - NAT & Cloud Router 30 | - Service Account for MIG 31 | - MIG Instance Template 32 | - MIG Instance Manager 33 | - FW Rules 34 | - Secret Manager Secret 35 | 36 | Deployment of Managed Instance Groups requires a [Google VM image](https://cloud.google.com/compute/docs/images) with a startup script that downloads and configures the agent or a pre-baked image with the agent installed. 37 | 38 | *Below are some examples:* 39 | 40 | - [Terraform Cloud agents on MIG VMs](examples/tfc-agent-mig-vm-simple/README.md) - This example shows how to deploy the Terraform Cloud agent on MIG with startup scripts. 41 | - [Terraform Cloud agents on MIG VMs from Packer image](examples/tfc-agent-mig-vm-packer/README.md) - This example shows how to deploy the Terraform Cloud agent with an image pre-baked using Packer. 42 | 43 | ## [Terraform Cloud agents Instance Groups using Container VMs](modules/tfc-agent-mig-container-vm/README.md) 44 | 45 | The `tfc-agent-mig-container-vm` module provisions the resources required to deploy Terraform Cloud agents on Google Cloud infrastructure using Managed Instance Groups and Container VMs. 46 | 47 | This includes 48 | 49 | - Enabling necessary APIs 50 | - VPC 51 | - NAT & Cloud Router 52 | - MIG Container Instance Template 53 | - MIG Instance Manager 54 | - FW Rules 55 | 56 | *Below are some examples:* 57 | 58 | - [Terraform Cloud agents on MIG Container VMs](examples/tfc-agent-mig-container-vm-simple/README.md) - This example shows how to deploy a Terraform Cloud agent on MIG Container VMs. 59 | 60 | ## [Terraform Cloud OIDC (Dynamic Credentials)](modules/tfc-oidc/README.md) 61 | 62 | The `tfc-oidc` 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 [Terraform Cloud Dynamic Credentials](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/gcp-configuration). 63 | 64 | This includes 65 | 66 | - Enabling necessary APIs 67 | - Creation of a Workload Identity pool 68 | - Configuring a Workload Identity provider 69 | - Granting external identities necessary IAM roles on Service Accounts 70 | 71 | *Below are some examples:* 72 | 73 | - [OIDC Simple](examples/oidc-simple/README.md) - This example shows how to use this module along with a Service Account to access storage buckets. 74 | 75 | ## Requirements 76 | 77 | These sections describe requirements for using this module. 78 | 79 | ### Software 80 | 81 | The following dependencies might be required based on the module being used: 82 | 83 | - [Terraform CLI][terraform-cli] 84 | - [Terraform Provider for GCP][terraform-provider-gcp] 85 | - [Terraform Provider for GCP beta][terraform-provider-gcp-beta] 86 | - [Google Cloud CLI][gcloud-cli] 87 | - [Kubernetes Provider][k8s-provider] 88 | - [Random Provider][random-provider] 89 | 90 | ## Contributing 91 | 92 | Refer to the [contribution guidelines](./CONTRIBUTING.md) for 93 | information on contributing to this module. 94 | 95 | [iam-module]: https://registry.terraform.io/modules/terraform-google-modules/iam/google 96 | [project-factory-module]: https://registry.terraform.io/modules/terraform-google-modules/project-factory/google 97 | [terraform-provider-gcp]: https://www.terraform.io/docs/providers/google/index.html 98 | [terraform-provider-gcp-beta]: https://registry.terraform.io/providers/hashicorp/google-beta/latest 99 | [terraform-cli]: https://www.terraform.io/downloads.html 100 | [gcloud-cli]: https://cloud.google.com/sdk/gcloud 101 | [k8s-provider]: https://registry.terraform.io/providers/hashicorp/kubernetes/latest 102 | [random-provider]: https://registry.terraform.io/providers/hashicorp/random/latest 103 | 104 | ## Security Disclosures 105 | 106 | Please see our [security disclosure process](./SECURITY.md). 107 | -------------------------------------------------------------------------------- /modules/tfc-oidc/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to use" 20 | } 21 | 22 | variable "service_list" { 23 | description = "Google Cloud APIs required for the project" 24 | type = list(string) 25 | default = [ 26 | "iam.googleapis.com", 27 | "cloudresourcemanager.googleapis.com", 28 | "sts.googleapis.com", 29 | "iamcredentials.googleapis.com" 30 | ] 31 | } 32 | 33 | variable "pool_id" { 34 | type = string 35 | description = "Workload Identity Pool ID" 36 | } 37 | 38 | variable "pool_display_name" { 39 | type = string 40 | description = "Workload Identity Pool display name" 41 | default = null 42 | } 43 | 44 | variable "pool_description" { 45 | type = string 46 | description = "Workload Identity Pool description" 47 | default = "Workload Identity Pool managed by Terraform" 48 | } 49 | 50 | variable "provider_id" { 51 | type = string 52 | description = "Workload Identity Pool Provider ID" 53 | } 54 | 55 | variable "provider_display_name" { 56 | type = string 57 | description = "Workload Identity Pool Provider display name" 58 | default = null 59 | } 60 | 61 | variable "provider_description" { 62 | type = string 63 | description = "Workload Identity Pool Provider description" 64 | default = "Workload Identity Pool Provider managed by Terraform" 65 | } 66 | 67 | variable "attribute_condition" { 68 | type = string 69 | description = <<-EOF 70 | Workload Identity Pool Provider attribute condition expression 71 | For more info please see 72 | https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider 73 | EOF 74 | default = "" 75 | } 76 | 77 | variable "attribute_mapping" { 78 | type = map(any) 79 | description = <<-EOF 80 | Workload Identity Pool Provider attribute mapping 81 | For more info please see 82 | https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider 83 | EOF 84 | default = { 85 | "google.subject" = "assertion.sub", 86 | "attribute.aud" = "assertion.aud", 87 | "attribute.terraform_run_phase" = "assertion.terraform_run_phase", 88 | "attribute.terraform_project_id" = "assertion.terraform_project_id", 89 | "attribute.terraform_project_name" = "assertion.terraform_project_name", 90 | "attribute.terraform_workspace_id" = "assertion.terraform_workspace_id", 91 | "attribute.terraform_workspace_name" = "assertion.terraform_workspace_name", 92 | "attribute.terraform_organization_id" = "assertion.terraform_organization_id", 93 | "attribute.terraform_organization_name" = "assertion.terraform_organization_name", 94 | "attribute.terraform_run_id" = "assertion.terraform_run_id", 95 | "attribute.terraform_full_workspace" = "assertion.terraform_full_workspace", 96 | } 97 | } 98 | 99 | variable "allowed_audiences" { 100 | type = list(string) 101 | description = "Workload Identity Pool Provider allowed audiences" 102 | default = [] 103 | } 104 | 105 | variable "issuer_uri" { 106 | type = string 107 | description = <<-EOF 108 | Workload Identity Pool Issuer URL for Terraform Cloud/Enterprise. 109 | The default audience format used by TFC is of the form 110 | //iam.googleapis.com/projects/{project_id}/locations/global/workloadIdentityPools/{pool_id}/providers/{provider_id} 111 | which matches with the default accepted audience format on GCP 112 | EOF 113 | default = "https://app.terraform.io" 114 | } 115 | 116 | variable "tfc_organization_name" { 117 | type = string 118 | description = "The Terraform Cloud organization to use" 119 | } 120 | 121 | variable "tfc_project_name" { 122 | type = string 123 | default = "Default Project" 124 | description = "The Terraform Cloud project to use" 125 | } 126 | 127 | variable "tfc_workspace_name" { 128 | type = string 129 | default = "gcp-oidc-workspace" 130 | description = "The Terraform Cloud workspace to authorize via OIDC" 131 | } 132 | 133 | variable "sa_mapping" { 134 | type = map(object({ 135 | sa_name = string 136 | sa_email = string 137 | attribute = string 138 | })) 139 | description = <<-EOF 140 | Service Account resource names and corresponding WIF provider attributes. 141 | If attribute is set to `*` all identities in the pool are granted access to SAs 142 | EOF 143 | default = {} 144 | } 145 | -------------------------------------------------------------------------------- /modules/tfc-agent-gke/README.md: -------------------------------------------------------------------------------- 1 | # Self Hosted Terraform Cloud agent on GKE 2 | 3 | This module handles the opinionated creation of infrastructure necessary to deploy Terraform Cloud agents on Google Kubernetes Engine (GKE). 4 | 5 | This includes: 6 | 7 | - Enabling necessary APIs 8 | - VPC 9 | - GKE Cluster 10 | - Kubernetes Secret 11 | 12 | Below are some examples: 13 | 14 | ## [Simple Terraform Cloud agents on GKE](../../examples/tfc-agent-gke-simple/README.md) 15 | 16 | This example shows how to deploy a simple GKE self hosted Terraform Cloud agent. 17 | 18 | ## [Custom Terraform Cloud agents on GKE](../../examples/tfc-agent-gke-custom/README.md) 19 | 20 | This example shows how to deploy a custom Terraform Cloud agent image with GKE. 21 | 22 | 23 | ## Inputs 24 | 25 | | Name | Description | Type | Default | Required | 26 | |------|-------------|------|---------|:--------:| 27 | | create\_network | When set to true, VPC will be auto created | `bool` | `true` | no | 28 | | create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | 29 | | ip\_range\_pods\_cidr | The secondary IP range CIDR to use for pods | `string` | `"192.168.0.0/18"` | no | 30 | | ip\_range\_pods\_name | The secondary IP range to use for pods | `string` | `"ip-range-pods"` | no | 31 | | ip\_range\_services\_cider | The secondary IP range CIDR to use for services | `string` | `"192.168.64.0/18"` | no | 32 | | ip\_range\_services\_name | The secondary IP range to use for services | `string` | `"ip-range-scv"` | no | 33 | | machine\_type | Machine type for TFC agent node pool | `string` | `"n1-standard-4"` | no | 34 | | max\_node\_count | Maximum number of nodes in the TFC agent node pool | `number` | `4` | no | 35 | | min\_node\_count | Minimum number of nodes in the TFC agent node pool | `number` | `2` | no | 36 | | network\_name | Name for the VPC network | `string` | `"tfc-agent-network"` | no | 37 | | network\_project\_id | The project ID of the shared VPCs host (for shared vpc support).
If not provided, the project\_id is used | `string` | `""` | no | 38 | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | `string` | n/a | yes | 39 | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | 40 | | service\_account\_email | Optional Service Account for the GKE nodes, required if create\_service\_account is set to false | `string` | `""` | no | 41 | | subnet\_ip | IP range for the subnet | `string` | `"10.0.0.0/17"` | no | 42 | | subnet\_name | Name for the subnet | `string` | `"tfc-agent-subnet"` | no | 43 | | tfc\_agent\_address | The HTTP or HTTPS address of the Terraform Cloud/Enterprise API | `string` | `"https://app.terraform.io"` | no | 44 | | tfc\_agent\_auto\_update | Controls automatic core updates behavior. Acceptable values include disabled, patch, and minor | `string` | `"minor"` | no | 45 | | tfc\_agent\_cpu\_request | CPU request for the Terraform Cloud agent container | `string` | `"2"` | no | 46 | | tfc\_agent\_image | The Terraform Cloud agent image to use | `string` | `"hashicorp/tfc-agent:latest"` | no | 47 | | tfc\_agent\_k8s\_secrets | Name for the k8s secret required to configure TFC agent on GKE | `string` | `"tfc-agent-k8s-secrets"` | no | 48 | | tfc\_agent\_max\_replicas | Maximum replicas for the Terraform Cloud agent pod autoscaler | `string` | `"10"` | no | 49 | | tfc\_agent\_memory\_request | Memory request for the Terraform Cloud agent container | `string` | `"2Gi"` | no | 50 | | tfc\_agent\_min\_replicas | Minimum replicas for the Terraform Cloud agent pod autoscaler | `string` | `"1"` | no | 51 | | tfc\_agent\_name\_prefix | This name may be used in the Terraform Cloud user interface to help easily identify the agent | `string` | `"tfc-agent-k8s"` | no | 52 | | tfc\_agent\_single | Enable single mode. This causes the agent to handle at most one job and
immediately exit thereafter. Useful for running agents as ephemeral
containers, VMs, or other isolated contexts with a higher-level scheduler
or process supervisor. | `bool` | `false` | no | 53 | | tfc\_agent\_token | Terraform Cloud agent token. (Organization Settings >> Agents) | `string` | n/a | yes | 54 | | zones | The GCP zone to use when deploying resources | `list(string)` |
[
"us-central1-a"
]
| no | 55 | 56 | ## Outputs 57 | 58 | | Name | Description | 59 | |------|-------------| 60 | | ca\_certificate | The cluster CA certificate (base64 encoded) | 61 | | client\_token | The bearer token for auth | 62 | | cluster\_name | GKE cluster name | 63 | | kubernetes\_endpoint | The GKE cluster endpoint | 64 | | location | GKE cluster location | 65 | | network\_name | Name of the VPC | 66 | | service\_account | The default service account used for TFC agent nodes | 67 | | subnet\_name | Name of the subnet in the VPC | 68 | 69 | 70 | 71 | ## Requirements 72 | 73 | Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 74 | 75 | 1. Required APIs are activated 76 | 77 | ```text 78 | "iam.googleapis.com", 79 | "cloudresourcemanager.googleapis.com", 80 | "containerregistry.googleapis.com", 81 | "container.googleapis.com", 82 | "storage-component.googleapis.com", 83 | "logging.googleapis.com", 84 | "monitoring.googleapis.com" 85 | ``` 86 | -------------------------------------------------------------------------------- /modules/tfc-oidc/README.md: -------------------------------------------------------------------------------- 1 | ## Terraform Cloud OIDC (Dynamic Credentials) 2 | 3 | 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 [Terraform Cloud Dynamic Credentials](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/gcp-configuration). 4 | 5 | This includes: 6 | 7 | - Creation of a Workload Identity pool 8 | - Configuring a Workload Identity provider 9 | - Granting external identities necessary IAM roles on Service Accounts 10 | 11 | ### Example Usage 12 | 13 | ```terraform 14 | module "tfc_oidc" { 15 | source = "GoogleCloudPlatform/tf-cloud-agents/google//modules/tfc-oidc" 16 | project_id = var.project_id 17 | pool_id = "example-pool" 18 | provider_id = "example-tfc-provider" 19 | sa_mapping = { 20 | "foo-service-account" = { 21 | sa_name = "projects/my-project/serviceAccounts/foo-service-account@my-project.iam.gserviceaccount.com" 22 | sa_email = "foo-service-account@my-project.iam.gserviceaccount.com" 23 | attribute = "*" 24 | } 25 | } 26 | tfc_organization_name = "example-tfc-organization" 27 | tfc_project_name = "example-tfc-project" 28 | tfc_workspace_name = "example-tfc-workspace-name" 29 | } 30 | ``` 31 | 32 | Below are some examples: 33 | 34 | ### [OIDC Simple](../../examples/oidc-simple/README.md) 35 | 36 | This example shows how to use this module along with a Service Account to access storage buckets. 37 | 38 | ### Terraform Cloud Workflow 39 | 40 | Once provisioned, you can use the `example-tfc-workspace-name` workspace from the example above to provision any infrastructure that the Service Account has access for. 41 | 42 | 43 | ## Inputs 44 | 45 | | Name | Description | Type | Default | Required | 46 | |------|-------------|------|---------|:--------:| 47 | | allowed\_audiences | Workload Identity Pool Provider allowed audiences | `list(string)` | `[]` | no | 48 | | attribute\_condition | Workload Identity Pool Provider attribute condition expression
For more info please see
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider | `string` | `""` | no | 49 | | attribute\_mapping | Workload Identity Pool Provider attribute mapping
For more info please see
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider | `map(any)` |
{
"attribute.aud": "assertion.aud",
"attribute.terraform_full_workspace": "assertion.terraform_full_workspace",
"attribute.terraform_organization_id": "assertion.terraform_organization_id",
"attribute.terraform_organization_name": "assertion.terraform_organization_name",
"attribute.terraform_project_id": "assertion.terraform_project_id",
"attribute.terraform_project_name": "assertion.terraform_project_name",
"attribute.terraform_run_id": "assertion.terraform_run_id",
"attribute.terraform_run_phase": "assertion.terraform_run_phase",
"attribute.terraform_workspace_id": "assertion.terraform_workspace_id",
"attribute.terraform_workspace_name": "assertion.terraform_workspace_name",
"google.subject": "assertion.sub"
}
| no | 50 | | issuer\_uri | Workload Identity Pool Issuer URL for Terraform Cloud/Enterprise.
The default audience format used by TFC is of the form
//iam.googleapis.com/projects/{project\_id}/locations/global/workloadIdentityPools/{pool\_id}/providers/{provider\_id}
which matches with the default accepted audience format on GCP | `string` | `"https://app.terraform.io"` | no | 51 | | pool\_description | Workload Identity Pool description | `string` | `"Workload Identity Pool managed by Terraform"` | no | 52 | | pool\_display\_name | Workload Identity Pool display name | `string` | `null` | no | 53 | | pool\_id | Workload Identity Pool ID | `string` | n/a | yes | 54 | | project\_id | The Google Cloud Platform project ID to use | `string` | n/a | yes | 55 | | provider\_description | Workload Identity Pool Provider description | `string` | `"Workload Identity Pool Provider managed by Terraform"` | no | 56 | | provider\_display\_name | Workload Identity Pool Provider display name | `string` | `null` | no | 57 | | provider\_id | Workload Identity Pool Provider ID | `string` | n/a | yes | 58 | | 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
sa_email = string
attribute = string
}))
| `{}` | no | 59 | | service\_list | Google Cloud APIs required for the project | `list(string)` |
[
"iam.googleapis.com",
"cloudresourcemanager.googleapis.com",
"sts.googleapis.com",
"iamcredentials.googleapis.com"
]
| no | 60 | | tfc\_organization\_name | The Terraform Cloud organization to use | `string` | n/a | yes | 61 | | tfc\_project\_name | The Terraform Cloud project to use | `string` | `"Default Project"` | no | 62 | | tfc\_workspace\_name | The Terraform Cloud workspace to authorize via OIDC | `string` | `"gcp-oidc-workspace"` | no | 63 | 64 | ## Outputs 65 | 66 | | Name | Description | 67 | |------|-------------| 68 | | pool\_name | Pool name | 69 | | provider\_name | Provider name | 70 | 71 | 72 | 73 | ## Requirements 74 | 75 | Before this module can be used on a project, you must ensure that the following pre-requisites are fulfilled: 76 | 77 | 1. Required APIs are activated 78 | 79 | ``` 80 | "iam.googleapis.com", 81 | "cloudresourcemanager.googleapis.com", 82 | "sts.googleapis.com", 83 | "iamcredentials.googleapis.com" 84 | ``` 85 | 86 | 1. Service Account used to deploy this module has the following roles 87 | 88 | ``` 89 | roles/iam.workloadIdentityPoolAdmin 90 | roles/iam.serviceAccountAdmin 91 | ``` 92 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-vm/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent" 20 | } 21 | 22 | variable "region" { 23 | type = string 24 | description = "The GCP region to use when deploying resources" 25 | default = "us-central1" 26 | } 27 | 28 | variable "create_network" { 29 | type = bool 30 | description = "When set to true, VPC, router and NAT will be auto created" 31 | default = true 32 | } 33 | 34 | variable "network_name" { 35 | type = string 36 | description = "Name for the VPC network" 37 | default = "tfc-agent-network" 38 | } 39 | 40 | variable "network_project" { 41 | type = string 42 | description = <<-EOF 43 | The project ID of the shared VPCs host (for shared vpc support). 44 | If not provided, the project_id is used 45 | EOF 46 | default = "" 47 | } 48 | 49 | variable "subnet_ip" { 50 | type = string 51 | description = "IP range for the subnet" 52 | default = "10.10.10.0/24" 53 | } 54 | 55 | variable "subnet_name" { 56 | type = string 57 | description = "Name for the subnet" 58 | default = "tfc-agent-subnet" 59 | } 60 | 61 | variable "min_replicas" { 62 | type = number 63 | description = "Minimum number of Terraform agent instances" 64 | default = 1 65 | } 66 | 67 | variable "max_replicas" { 68 | type = number 69 | description = "Maximum number of Terraform agent instances" 70 | default = 10 71 | } 72 | 73 | variable "create_service_account" { 74 | description = "Set to true to create a new service account, false to use an existing one" 75 | type = bool 76 | default = true 77 | } 78 | 79 | variable "service_account_email" { 80 | type = string 81 | description = "Service account email address to use with the MIG template, required if create_service_account is set to false" 82 | default = "" 83 | } 84 | 85 | variable "machine_type" { 86 | type = string 87 | description = "The GCP machine type to deploy" 88 | default = "n1-standard-1" 89 | } 90 | 91 | variable "source_image_family" { 92 | type = string 93 | description = <<-EOF 94 | Source image family. If neither source_image nor source_image_family 95 | is specified, defaults to the latest public Ubuntu image 96 | EOF 97 | default = "ubuntu-2204-lts" 98 | } 99 | 100 | variable "source_image_project" { 101 | type = string 102 | description = "Project where the source image originates" 103 | default = "ubuntu-os-cloud" 104 | } 105 | 106 | variable "source_image" { 107 | type = string 108 | description = <<-EOF 109 | Source disk image. If neither source_image nor source_image_family is specified, 110 | defaults to the latest public CentOS image 111 | EOF 112 | default = "" 113 | } 114 | 115 | variable "startup_script" { 116 | type = string 117 | description = "User startup script to run when instances spin up" 118 | default = "" 119 | } 120 | 121 | variable "custom_metadata" { 122 | type = map(any) 123 | description = "User provided custom metadata" 124 | default = {} 125 | } 126 | 127 | variable "cooldown_period" { 128 | type = number 129 | description = <<-EOF 130 | The number of seconds that the autoscaler should wait before it 131 | starts collecting information from a new instance 132 | EOF 133 | default = 60 134 | } 135 | 136 | variable "tfc_agent_secret" { 137 | type = string 138 | description = "The secret id for storing the Terraform Cloud agent secret" 139 | default = "tfc-agent" 140 | } 141 | 142 | variable "tfc_agent_address" { 143 | type = string 144 | description = "The HTTP or HTTPS address of the Terraform Cloud/Enterprise API" 145 | default = "https://app.terraform.io" 146 | } 147 | 148 | variable "tfc_agent_single" { 149 | type = bool 150 | description = <<-EOF 151 | Enable single mode. This causes the agent to handle at most one job and 152 | immediately exit thereafter. Useful for running agents as ephemeral 153 | containers, VMs, or other isolated contexts with a higher-level scheduler 154 | or process supervisor 155 | EOF 156 | default = false 157 | } 158 | 159 | variable "tfc_agent_auto_update" { 160 | type = string 161 | description = <<-EOF 162 | Controls automatic core updates behavior. 163 | Acceptable values include disabled, patch, and minor 164 | EOF 165 | default = "minor" 166 | } 167 | 168 | variable "tfc_agent_name_prefix" { 169 | type = string 170 | description = <<-EOF 171 | This name may be used in the Terraform Cloud user interface to help 172 | easily identify the agent 173 | EOF 174 | default = "tfc-agent-mig-vm" 175 | } 176 | 177 | variable "tfc_agent_labels" { 178 | type = set(string) 179 | description = "Terraform Cloud agent labels to attach to the VMs" 180 | default = [] 181 | } 182 | 183 | variable "tfc_agent_version" { 184 | type = string 185 | description = "Terraform Cloud agent version to install" 186 | default = "1.12.0" 187 | } 188 | 189 | variable "tfc_agent_token" { 190 | type = string 191 | description = "Terraform Cloud agent token. (Organization Settings >> Agents)" 192 | sensitive = true 193 | } 194 | -------------------------------------------------------------------------------- /modules/tfc-agent-gke/variables.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | variable "project_id" { 18 | type = string 19 | description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" 20 | } 21 | 22 | variable "region" { 23 | type = string 24 | description = "The GCP region to use when deploying resources" 25 | default = "us-central1" 26 | } 27 | 28 | variable "zones" { 29 | type = list(string) 30 | description = "The GCP zone to use when deploying resources" 31 | default = ["us-central1-a"] 32 | } 33 | 34 | variable "ip_range_pods_name" { 35 | type = string 36 | description = "The secondary IP range to use for pods" 37 | default = "ip-range-pods" 38 | } 39 | 40 | variable "ip_range_services_name" { 41 | type = string 42 | description = "The secondary IP range to use for services" 43 | default = "ip-range-scv" 44 | } 45 | 46 | variable "ip_range_pods_cidr" { 47 | type = string 48 | description = "The secondary IP range CIDR to use for pods" 49 | default = "192.168.0.0/18" 50 | } 51 | 52 | variable "ip_range_services_cider" { 53 | type = string 54 | description = "The secondary IP range CIDR to use for services" 55 | default = "192.168.64.0/18" 56 | } 57 | 58 | variable "network_name" { 59 | type = string 60 | description = "Name for the VPC network" 61 | default = "tfc-agent-network" 62 | } 63 | 64 | variable "subnet_ip" { 65 | type = string 66 | description = "IP range for the subnet" 67 | default = "10.0.0.0/17" 68 | } 69 | 70 | variable "subnet_name" { 71 | type = string 72 | description = "Name for the subnet" 73 | default = "tfc-agent-subnet" 74 | } 75 | 76 | variable "create_network" { 77 | type = bool 78 | description = "When set to true, VPC will be auto created" 79 | default = true 80 | } 81 | 82 | variable "network_project_id" { 83 | type = string 84 | description = <<-EOF 85 | The project ID of the shared VPCs host (for shared vpc support). 86 | If not provided, the project_id is used 87 | EOF 88 | default = "" 89 | } 90 | 91 | variable "machine_type" { 92 | type = string 93 | description = "Machine type for TFC agent node pool" 94 | default = "n1-standard-4" 95 | } 96 | 97 | variable "max_node_count" { 98 | type = number 99 | description = "Maximum number of nodes in the TFC agent node pool" 100 | default = 4 101 | } 102 | 103 | variable "min_node_count" { 104 | type = number 105 | description = "Minimum number of nodes in the TFC agent node pool" 106 | default = 2 107 | } 108 | 109 | variable "create_service_account" { 110 | description = "Set to true to create a new service account, false to use an existing one" 111 | type = bool 112 | default = true 113 | } 114 | 115 | variable "service_account_email" { 116 | type = string 117 | description = "Optional Service Account for the GKE nodes, required if create_service_account is set to false" 118 | default = "" 119 | } 120 | 121 | variable "tfc_agent_k8s_secrets" { 122 | type = string 123 | description = "Name for the k8s secret required to configure TFC agent on GKE" 124 | default = "tfc-agent-k8s-secrets" 125 | } 126 | 127 | variable "tfc_agent_address" { 128 | type = string 129 | description = "The HTTP or HTTPS address of the Terraform Cloud/Enterprise API" 130 | default = "https://app.terraform.io" 131 | } 132 | 133 | variable "tfc_agent_single" { 134 | type = bool 135 | description = <<-EOF 136 | Enable single mode. This causes the agent to handle at most one job and 137 | immediately exit thereafter. Useful for running agents as ephemeral 138 | containers, VMs, or other isolated contexts with a higher-level scheduler 139 | or process supervisor. 140 | EOF 141 | default = false 142 | } 143 | 144 | variable "tfc_agent_auto_update" { 145 | type = string 146 | description = "Controls automatic core updates behavior. Acceptable values include disabled, patch, and minor" 147 | default = "minor" 148 | } 149 | 150 | variable "tfc_agent_name_prefix" { 151 | type = string 152 | description = "This name may be used in the Terraform Cloud user interface to help easily identify the agent" 153 | default = "tfc-agent-k8s" 154 | } 155 | 156 | variable "tfc_agent_image" { 157 | type = string 158 | description = "The Terraform Cloud agent image to use" 159 | default = "hashicorp/tfc-agent:latest" 160 | } 161 | 162 | variable "tfc_agent_memory_request" { 163 | type = string 164 | description = "Memory request for the Terraform Cloud agent container" 165 | default = "2Gi" 166 | } 167 | 168 | variable "tfc_agent_cpu_request" { 169 | type = string 170 | description = "CPU request for the Terraform Cloud agent container" 171 | default = "2" 172 | } 173 | 174 | variable "tfc_agent_token" { 175 | type = string 176 | description = "Terraform Cloud agent token. (Organization Settings >> Agents)" 177 | sensitive = true 178 | } 179 | 180 | variable "tfc_agent_min_replicas" { 181 | type = string 182 | description = "Minimum replicas for the Terraform Cloud agent pod autoscaler" 183 | default = "1" 184 | } 185 | 186 | variable "tfc_agent_max_replicas" { 187 | type = string 188 | description = "Maximum replicas for the Terraform Cloud agent pod autoscaler" 189 | default = "10" 190 | } 191 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-vm/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : var.network_name 19 | service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email 20 | startup_script = var.startup_script == "" ? file("${path.module}/scripts/startup.sh") : var.startup_script 21 | instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" 22 | tfc_agent_secret = "${var.tfc_agent_secret}-${random_string.suffix.result}" 23 | } 24 | 25 | resource "random_string" "suffix" { 26 | length = 4 27 | special = false 28 | upper = false 29 | } 30 | 31 | /***************************************** 32 | Optional Terraform agent Networking 33 | *****************************************/ 34 | 35 | resource "google_compute_network" "tfc_agent_network" { 36 | count = var.create_network ? 1 : 0 37 | name = var.network_name 38 | project = var.project_id 39 | auto_create_subnetworks = false 40 | } 41 | 42 | resource "google_compute_subnetwork" "tfc_agent_subnetwork" { 43 | count = var.create_network ? 1 : 0 44 | project = var.project_id 45 | name = var.subnet_name 46 | ip_cidr_range = var.subnet_ip 47 | region = var.region 48 | network = local.network_name 49 | } 50 | 51 | resource "google_compute_router" "tfc_agent_router" { 52 | count = var.create_network ? 1 : 0 53 | name = "${var.network_name}-router" 54 | network = google_compute_network.tfc_agent_network[0].self_link 55 | region = var.region 56 | project = var.project_id 57 | } 58 | 59 | resource "google_compute_router_nat" "tfc_agent_nat" { 60 | count = var.create_network ? 1 : 0 61 | project = var.project_id 62 | name = "${var.network_name}-nat" 63 | router = google_compute_router.tfc_agent_router[0].name 64 | region = google_compute_router.tfc_agent_router[0].region 65 | nat_ip_allocate_option = "AUTO_ONLY" 66 | source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" 67 | } 68 | 69 | /***************************************** 70 | IAM Bindings GCE SVC 71 | *****************************************/ 72 | 73 | resource "google_service_account" "tfc_agent_service_account" { 74 | count = var.create_service_account ? 1 : 0 75 | project = var.project_id 76 | account_id = "tfc-agent-mig-vm-sa" 77 | display_name = "Terraform Cloud agent GCE Service Account" 78 | } 79 | 80 | /***************************************** 81 | Terraform agent Secrets 82 | *****************************************/ 83 | 84 | resource "google_secret_manager_secret" "tfc_agent_secret" { 85 | provider = google-beta 86 | project = var.project_id 87 | secret_id = local.tfc_agent_secret 88 | 89 | labels = { 90 | label = local.tfc_agent_secret 91 | } 92 | 93 | replication { 94 | user_managed { 95 | replicas { 96 | location = var.region 97 | } 98 | } 99 | } 100 | } 101 | 102 | resource "google_secret_manager_secret_version" "tfc_agent_secret_version" { 103 | provider = google-beta 104 | secret = google_secret_manager_secret.tfc_agent_secret.id 105 | secret_data = jsonencode({ 106 | "TFC_AGENT_NAME" = local.instance_name 107 | "TFC_ADDRESS" = var.tfc_agent_address 108 | "TFC_AGENT_TOKEN" = var.tfc_agent_token 109 | "TFC_AGENT_SINGLE" = var.tfc_agent_single 110 | "TFC_AGENT_AUTO_UPDATE" = var.tfc_agent_auto_update 111 | "AGENT_VERSION" = var.tfc_agent_version 112 | "LABELS" = join(",", var.tfc_agent_labels) 113 | }) 114 | } 115 | 116 | resource "google_secret_manager_secret_iam_member" "tfc_agent_secret_member" { 117 | provider = google-beta 118 | project = var.project_id 119 | secret_id = google_secret_manager_secret.tfc_agent_secret.id 120 | role = "roles/secretmanager.secretAccessor" 121 | member = "serviceAccount:${local.service_account_email}" 122 | } 123 | 124 | /***************************************** 125 | Terraform agent GCE Instance Template 126 | *****************************************/ 127 | 128 | module "mig_template" { 129 | source = "terraform-google-modules/vm/google//modules/instance_template" 130 | version = "~> 12.0" 131 | 132 | project_id = var.project_id 133 | machine_type = var.machine_type 134 | network = local.network_name 135 | subnetwork = var.subnet_name 136 | region = var.region 137 | subnetwork_project = var.network_project != "" ? var.network_project : var.project_id 138 | service_account = { 139 | email = local.service_account_email 140 | scopes = [ 141 | "https://www.googleapis.com/auth/cloud-platform", 142 | ] 143 | } 144 | disk_size_gb = 100 145 | disk_type = "pd-ssd" 146 | auto_delete = true 147 | source_image = var.source_image 148 | source_image_family = var.source_image_family 149 | source_image_project = var.source_image_project 150 | name_prefix = var.tfc_agent_name_prefix 151 | startup_script = local.startup_script 152 | metadata = merge({ 153 | "secret-id" = google_secret_manager_secret_version.tfc_agent_secret_version.name 154 | }, var.custom_metadata) 155 | tags = [ 156 | local.instance_name 157 | ] 158 | 159 | depends_on = [ 160 | google_compute_network.tfc_agent_network, 161 | google_compute_subnetwork.tfc_agent_subnetwork, 162 | ] 163 | } 164 | 165 | /***************************************** 166 | Terraform agent MIG 167 | *****************************************/ 168 | 169 | module "mig" { 170 | source = "terraform-google-modules/vm/google//modules/mig" 171 | version = "~> 12.0" 172 | 173 | project_id = var.project_id 174 | region = var.region 175 | hostname = local.instance_name 176 | instance_template = module.mig_template.self_link 177 | 178 | /* autoscaler */ 179 | autoscaling_enabled = true 180 | min_replicas = var.min_replicas 181 | max_replicas = var.max_replicas 182 | cooldown_period = var.cooldown_period 183 | } 184 | -------------------------------------------------------------------------------- /modules/tfc-agent-mig-container-vm/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | dind_volume_mounts = var.dind ? [{ 19 | mountPath = "/var/run/docker.sock" 20 | name = "dockersock" 21 | readOnly = false 22 | }] : [] 23 | dind_volumes = var.dind ? [ 24 | { 25 | name = "dockersock" 26 | 27 | hostPath = { 28 | path = "/var/run/docker.sock" 29 | } 30 | }] : [] 31 | network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : (var.subnet_name != "" ? null : var.network_name) 32 | subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].self_link : var.subnet_name 33 | service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email 34 | instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" 35 | } 36 | 37 | resource "random_string" "suffix" { 38 | length = 4 39 | special = false 40 | upper = false 41 | } 42 | 43 | /***************************************** 44 | Optional TFC agent Networking 45 | *****************************************/ 46 | 47 | resource "google_compute_network" "tfc_agent_network" { 48 | count = var.create_network ? 1 : 0 49 | name = var.network_name 50 | project = var.project_id 51 | auto_create_subnetworks = false 52 | } 53 | 54 | resource "google_compute_subnetwork" "tfc_agent_subnetwork" { 55 | count = var.create_network ? 1 : 0 56 | project = var.project_id 57 | name = var.subnet_name 58 | ip_cidr_range = var.subnet_ip 59 | region = var.region 60 | network = google_compute_network.tfc_agent_network[0].name 61 | } 62 | 63 | resource "google_compute_router" "default" { 64 | count = var.create_network ? 1 : 0 65 | name = "${var.network_name}-router" 66 | network = google_compute_network.tfc_agent_network[0].self_link 67 | region = var.region 68 | project = var.project_id 69 | } 70 | 71 | resource "google_compute_router_nat" "nat" { 72 | count = var.create_network ? 1 : 0 73 | project = var.project_id 74 | name = "${var.network_name}-nat" 75 | router = google_compute_router.default[0].name 76 | region = google_compute_router.default[0].region 77 | nat_ip_allocate_option = "AUTO_ONLY" 78 | source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" 79 | } 80 | 81 | /***************************************** 82 | IAM Bindings GCE SVC 83 | *****************************************/ 84 | 85 | resource "google_service_account" "tfc_agent_service_account" { 86 | count = var.create_service_account ? 1 : 0 87 | project = var.project_id 88 | account_id = "tfc-agent-mig-container-vm-sa" 89 | display_name = "Terrform agent GCE Service Account" 90 | } 91 | 92 | # allow GCE to pull images from GCR 93 | resource "google_project_iam_member" "gce" { 94 | count = var.create_service_account ? 1 : 0 95 | project = var.project_id 96 | role = "roles/storage.objectViewer" 97 | member = "serviceAccount:${local.service_account_email}" 98 | } 99 | 100 | /***************************************** 101 | TFC agent GCE Instance Template 102 | *****************************************/ 103 | 104 | module "gce_container" { 105 | source = "terraform-google-modules/container-vm/google" 106 | version = "~> 3.2" 107 | 108 | container = { 109 | image = var.image 110 | env = [ 111 | { 112 | name = "TFC_AGENT_NAME" 113 | value = local.instance_name 114 | }, 115 | { 116 | name = "TFC_AGENT_TOKEN" 117 | value = var.tfc_agent_token 118 | }, 119 | { 120 | name = "TFC_ADDRESS" 121 | value = var.tfc_agent_address 122 | }, 123 | { 124 | name = "TFC_AGENT_AUTO_UPDATE" 125 | value = var.tfc_agent_auto_update 126 | }, 127 | { 128 | name = "TFC_AGENT_SINGLE" 129 | value = var.tfc_agent_single 130 | } 131 | ] 132 | 133 | # Declare volumes to be mounted 134 | # This is similar to how Docker volumes are mounted 135 | volumeMounts = concat([ 136 | { 137 | mountPath = "/cache" 138 | name = "tempfs-0" 139 | readOnly = false 140 | } 141 | ], local.dind_volume_mounts) 142 | } 143 | 144 | # Declare the volumes 145 | volumes = concat([ 146 | { 147 | name = "tempfs-0" 148 | 149 | emptyDir = { 150 | medium = "Memory" 151 | } 152 | } 153 | ], local.dind_volumes) 154 | 155 | restart_policy = var.restart_policy 156 | } 157 | 158 | module "mig_template" { 159 | source = "terraform-google-modules/vm/google//modules/instance_template" 160 | version = "~> 12.0" 161 | 162 | region = var.region 163 | project_id = var.project_id 164 | network = local.network_name 165 | subnetwork = local.subnet_name 166 | subnetwork_project = var.subnetwork_project != "" ? var.subnetwork_project : var.project_id 167 | service_account = { 168 | email = local.service_account_email 169 | scopes = [ 170 | "https://www.googleapis.com/auth/cloud-platform", 171 | ] 172 | } 173 | disk_size_gb = 100 174 | disk_type = "pd-ssd" 175 | auto_delete = true 176 | source_image_family = "cos-stable" 177 | source_image_project = "cos-cloud" 178 | startup_script = var.startup_script 179 | name_prefix = var.tfc_agent_name_prefix 180 | source_image = reverse(split("/", module.gce_container.source_image))[0] 181 | metadata = merge(var.additional_metadata, { 182 | google-logging-enabled = "true" 183 | "gce-container-declaration" = module.gce_container.metadata_value 184 | }) 185 | tags = [ 186 | local.instance_name 187 | ] 188 | labels = { 189 | container-vm = module.gce_container.vm_container_label 190 | } 191 | } 192 | 193 | /***************************************** 194 | TFC agent MIG 195 | *****************************************/ 196 | 197 | module "mig" { 198 | source = "terraform-google-modules/vm/google//modules/mig" 199 | version = "~> 12.0" 200 | 201 | region = var.region 202 | project_id = var.project_id 203 | target_size = var.target_size 204 | hostname = local.instance_name 205 | instance_template = module.mig_template.self_link 206 | 207 | /* autoscaler */ 208 | autoscaling_enabled = var.autoscaling_enabled 209 | cooldown_period = var.cooldown_period 210 | } 211 | -------------------------------------------------------------------------------- /modules/tfc-agent-gke/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | locals { 18 | network_name = var.create_network ? google_compute_network.tfc_agent_network[0].name : var.network_name 19 | subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].name : var.subnet_name 20 | service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email 21 | tfc_agent_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" 22 | } 23 | 24 | resource "random_string" "suffix" { 25 | length = 4 26 | special = false 27 | upper = false 28 | } 29 | 30 | /***************************************** 31 | Optional Network 32 | *****************************************/ 33 | 34 | resource "google_compute_network" "tfc_agent_network" { 35 | count = var.create_network ? 1 : 0 36 | name = var.network_name 37 | project = var.project_id 38 | auto_create_subnetworks = false 39 | } 40 | 41 | resource "google_compute_subnetwork" "tfc_agent_subnetwork" { 42 | count = var.create_network ? 1 : 0 43 | project = var.project_id 44 | name = var.subnet_name 45 | ip_cidr_range = var.subnet_ip 46 | region = var.region 47 | network = google_compute_network.tfc_agent_network[0].name 48 | 49 | secondary_ip_range { 50 | range_name = var.ip_range_pods_name 51 | ip_cidr_range = var.ip_range_pods_cidr 52 | } 53 | 54 | secondary_ip_range { 55 | range_name = var.ip_range_services_name 56 | ip_cidr_range = var.ip_range_services_cider 57 | } 58 | } 59 | 60 | /***************************************** 61 | IAM Bindings GKE 62 | *****************************************/ 63 | 64 | resource "google_service_account" "tfc_agent_service_account" { 65 | count = var.create_service_account ? 1 : 0 66 | project = var.project_id 67 | account_id = "tfc-agent-gke" 68 | display_name = "Terraform Cloud agent GKE Service Account" 69 | } 70 | 71 | /***************************************** 72 | TFC agent GKE 73 | *****************************************/ 74 | 75 | module "tfc_agent_cluster" { 76 | source = "terraform-google-modules/kubernetes-engine/google//modules/beta-public-cluster/" 77 | version = "~> 34.0" 78 | project_id = var.project_id 79 | region = var.region 80 | zones = var.zones 81 | network = local.network_name 82 | name = local.tfc_agent_name 83 | subnetwork = local.subnet_name 84 | service_account = local.service_account_email 85 | network_project_id = var.network_project_id != "" ? var.network_project_id : var.project_id 86 | ip_range_pods = var.ip_range_pods_name 87 | ip_range_services = var.ip_range_services_name 88 | logging_service = "logging.googleapis.com/kubernetes" 89 | monitoring_service = "monitoring.googleapis.com/kubernetes" 90 | remove_default_node_pool = true 91 | regional = false 92 | gce_pd_csi_driver = true 93 | deletion_protection = false 94 | node_pools = [ 95 | { 96 | name = "tfc-agent-pool" 97 | min_count = var.min_node_count 98 | max_count = var.max_node_count 99 | auto_upgrade = true 100 | machine_type = var.machine_type 101 | } 102 | ] 103 | } 104 | 105 | /***************************************** 106 | K8S resources for configuring TFC agent 107 | *****************************************/ 108 | 109 | data "google_client_config" "default" { 110 | } 111 | 112 | resource "kubernetes_secret" "tfc_agent_secrets" { 113 | metadata { 114 | name = var.tfc_agent_k8s_secrets 115 | } 116 | data = { 117 | tfc_agent_address = var.tfc_agent_address 118 | tfc_agent_token = var.tfc_agent_token 119 | tfc_agent_single = var.tfc_agent_single 120 | tfc_agent_auto_update = var.tfc_agent_auto_update 121 | tfc_agent_name = local.tfc_agent_name 122 | } 123 | } 124 | 125 | # Deploy the agent 126 | resource "kubernetes_deployment" "tfc_agent_deployment" { 127 | metadata { 128 | name = "${local.tfc_agent_name}-deployment" 129 | } 130 | 131 | spec { 132 | selector { 133 | match_labels = { 134 | app = local.tfc_agent_name 135 | } 136 | } 137 | 138 | replicas = var.tfc_agent_min_replicas 139 | 140 | template { 141 | metadata { 142 | labels = { 143 | app = local.tfc_agent_name 144 | } 145 | } 146 | 147 | spec { 148 | container { 149 | name = local.tfc_agent_name 150 | image = var.tfc_agent_image 151 | 152 | env { 153 | name = "TFC_ADDRESS" 154 | value_from { 155 | secret_key_ref { 156 | name = var.tfc_agent_k8s_secrets 157 | key = "tfc_agent_address" 158 | } 159 | } 160 | } 161 | 162 | env { 163 | name = "TFC_AGENT_TOKEN" 164 | value_from { 165 | secret_key_ref { 166 | name = var.tfc_agent_k8s_secrets 167 | key = "tfc_agent_token" 168 | } 169 | } 170 | } 171 | 172 | env { 173 | name = "TFC_AGENT_NAME" 174 | value_from { 175 | secret_key_ref { 176 | name = var.tfc_agent_k8s_secrets 177 | key = "tfc_agent_name" 178 | } 179 | } 180 | } 181 | 182 | env { 183 | name = "TFC_AGENT_SINGLE" 184 | value_from { 185 | secret_key_ref { 186 | name = var.tfc_agent_k8s_secrets 187 | key = "tfc_agent_single" 188 | } 189 | } 190 | } 191 | 192 | env { 193 | name = "TFC_AGENT_AUTO_UPDATE" 194 | value_from { 195 | secret_key_ref { 196 | name = var.tfc_agent_k8s_secrets 197 | key = "tfc_agent_auto_update" 198 | } 199 | } 200 | } 201 | 202 | # https://developer.hashicorp.com/terraform/cloud-docs/agents/requirements 203 | resources { 204 | requests = { 205 | memory = var.tfc_agent_memory_request 206 | cpu = var.tfc_agent_cpu_request 207 | } 208 | } 209 | } 210 | } 211 | } 212 | } 213 | } 214 | 215 | # Deploy a horizontal pod autoscaler for the agent 216 | resource "kubernetes_horizontal_pod_autoscaler_v2" "tfc_agent_hpa" { 217 | metadata { 218 | name = "${local.tfc_agent_name}-deployment-hpa" 219 | } 220 | 221 | spec { 222 | scale_target_ref { 223 | kind = "Deployment" 224 | name = "${local.tfc_agent_name}-deployment" 225 | } 226 | 227 | min_replicas = var.tfc_agent_min_replicas 228 | max_replicas = var.tfc_agent_max_replicas 229 | 230 | metric { 231 | type = "Resource" 232 | 233 | resource { 234 | name = "cpu" 235 | 236 | target { 237 | type = "Utilization" 238 | average_utilization = 50 239 | } 240 | } 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------