Terraform
Pick this when the project’s IAM and APIs already live in your Terraform. A resource created by hand shows up as drift on the next plan; adding the module keeps the plan clean.
Verified with Terraform 1.15 and hashicorp/google 6.50.
Add the module
Section titled “Add the module”module "applane" { source = "github.com/<ORG>/applane//infra/terraform/customer-gcp" project_id = "<GCP_PROJECT_ID>" builders_group_email = "applane-builders@<YOUR_DOMAIN>" applane_extension_id = "<APPLANE_EXTENSION_ID>"
# optional: budget alert at 50%, 90%, 100% of budget_amount per month billing_account_id = "<BILLING_ACCOUNT_ID>" budget_amount = 50}
output "applane_next_steps" { value = module.applane.consent_screen_instructions}The module source with the organisation filled in is on the Applane console’s Setup page. Inputs and outputs are listed in the Terraform module reference.
If another module already manages google_project_service on this project, set enable_apis = false and enable the five APIs there instead. Two Terraform resources for the same API fight each other.
Or run the example on its own
Section titled “Or run the example on its own”git clone <APPLANE_SETUP_REPO_URL> applane && cd applane/infra/terraform/customer-gcpcp examples/basic/terraform.tfvars.example examples/basic/terraform.tfvars # fill in project, group, extension idcd examples/basicgcloud auth application-default loginterraform initterraform planterraform applyterraform output consent_screen_instructionsCreating the project too
Section titled “Creating the project too”The module never creates projects. If you want one config to do both, add a google_project in your root module and pass existing_project = false so the module’s billing check is skipped at plan time:
resource "google_project" "applane" { name = "Applane" project_id = "acme-applane" org_id = var.org_id # or folder_id billing_account = var.billing_account_id}
module "applane" { source = "github.com/<ORG>/applane//infra/terraform/customer-gcp" project_id = google_project.applane.project_id builders_group_email = "applane-builders@acme.com" billing_account_id = var.billing_account_id existing_project = false}What it creates
Section titled “What it creates”| Resource | What | Why |
|---|---|---|
google_project_service x5 |
script, aiplatform, sheets, drive, docs .googleapis.com |
Google checks API enablement on the project that owns the OAuth client. disable_on_destroy = false: destroying the module never switches an API off. |
google_project_iam_member |
roles/aiplatform.user to group:<builders_group_email> |
Lets builders call Gemini on Vertex AI. No service accounts, no keys. |
google_billing_budget |
50%, 90%, 100% of budget_amount per month |
Only when billing_account_id is set. Alerts go to the billing admins; nothing is cut off. Also enables billingbudgets.googleapis.com. |
A data "google_project" read checks that billing is linked and fails the plan with a clear message if it is not.
Why the consent screen and the client are not in Terraform
Section titled “Why the consent screen and the client are not in Terraform”Google has no API for the OAuth consent screen or for a standard OAuth 2.0 client. The provider’s google_iap_client and google_iap_brand only create clients for Identity-Aware Proxy, and an IAP client does not work with the extension’s sign-in flow. So two steps stay in the console: OAuth consent screen and OAuth client. The module prints them in consent_screen_instructions.
Verify
Section titled “Verify”terraform plan after apply shows no changes. Then run the setup checker.
Remove it
Section titled “Remove it”terraform destroy removes the IAM binding and the budget. The five APIs stay enabled on purpose; disable them by hand if the project is dedicated to Applane, then delete the OAuth client in the console. See Uninstall.
For AI agents: llms.txt, llms-full.txt, or any page with a .md suffix.