Create a GCP project with org/gcp/project-factory¶
Purpose: Create (or converge) a GCP project using the Terraform Google Project Factory module via HyOps.
Owner: Platform operations
Trigger: First-time GCP bootstrap for an environment; new project required.
Impact: Creates cloud resources and links billing; may incur cost.
Severity: P2
Pre-reqs: hyops init gcp completed for the environment; gcloud installed and authenticated (ADC); Terraform Cloud token available (recommended: run hyops init terraform-cloud --env <env>), unless you run with local state (HYOPS_TERRAFORM_BACKEND_MODE=local).
Rollback strategy: Use hyops destroy only if you intentionally want to delete the project. Note: the upstream module defaults deletion_policy=PREVENT, so destroy will fail unless you first apply with deletion_policy: "DELETE" (see Destroy / purge).
Context¶
This runbook covers the project creation step. It assumes you have already initialised GCP credentials with:
- Runbook:
RB-026-hyops-init-gcp.md
org/gcp/project-factory runs via:
- Driver:
iac/terragrunt - Profile:
gcp@v1.0 - Pack:
gcp/org/00-project-factory@v1.0
After apply, re-run hyops init gcp --force so HyOps can auto-derive the Terraform impersonation target (service account email) from module state and validate it.
In the preferred GCP operating model, this project is the env-scoped
control project by default. That makes it the clean place for:
- GCP Secret Manager
- env-scoped backup bucket modules
- other env-scoped control services
It does not need to be the same project that owns the Shared VPC, Cloud NAT, or runner VM placement.
State backend (cloud vs local)¶
By default, the gcp@v1.0 Terragrunt profile uses HCP Terraform (Terraform Cloud) backend for state (cloud state, local execution).
- Default:
HYOPS_TERRAFORM_BACKEND_MODE=cloud - Local state (for offline/dev):
HYOPS_TERRAFORM_BACKEND_MODE=local(writes tfstate under<root>/state/terraform/)
Example:
# recommended for cloud provider stacks
export HYOPS_TERRAFORM_BACKEND_MODE=cloud
# or: local state backend
export HYOPS_TERRAFORM_BACKEND_MODE=local
Preconditions and safety checks¶
-
Ensure you are targeting the correct environment:
echo "HYOPS_ENV=$HYOPS_ENV" -
Confirm you have a billing account:
gcloud beta billing accounts list -
(Optional) Check if you have an Organization:
Notes:gcloud organizations list - Personal/trial accounts often show
Listed 0 items.This is OK. In that case, omitorg_idandfolder_idin inputs.
Inputs¶
Create a local inputs file (do not commit it to a public repo if it contains real billing/org identifiers).
Minimal example (trial/personal accounts, no Organization)¶
project_id: hybridops-pf-dev
region: europe-west2
billing_account_id: "01B1FD-FAC417-423408"
activate_apis:
- cloudresourcemanager.googleapis.com
- iam.googleapis.com
- secretmanager.googleapis.com
labels:
owner: hybridops
env: dev
Enterprise example (Organization or Folder)¶
name_prefix: platform
context_id: dev
project_id: hybridops-pf-dev
region: europe-west2
billing_account_id: "01B1FD-FAC417-423408"
org_id: "123456789012" # OR folder_id: "123456789012"
activate_apis:
- cloudresourcemanager.googleapis.com
- iam.googleapis.com
- secretmanager.googleapis.com
labels:
owner: hybridops
env: dev
Notes:
- HyOps accepts billing_account_id (legacy alias) and will map it to the upstream input billing_account.
- org_id / folder_id are optional (recommended for enterprise governance).
- secretmanager.googleapis.com should be enabled by default if you plan to use GCP Secret Manager as the external secret authority for runner-driven DR.
Steps¶
1) Preflight
INPUTS=/tmp/hyops-gcp-project-factory.dev.yml
hyops preflight --env dev --strict --module org/gcp/project-factory --inputs "$INPUTS"
2) Apply
hyops apply --env dev --module org/gcp/project-factory --inputs "$INPUTS"
3) Re-run GCP init to validate impersonation
hyops init gcp --env dev --force
4) Destroy / purge (optional)
By default, the upstream Project Factory module sets deletion_policy=PREVENT. That is a safe default, but it means hyops destroy cannot delete the project.
To intentionally delete the project:
# 1) converge deletion_policy into state
# (edit your inputs file and add: deletion_policy: "DELETE")
hyops apply --env dev --module org/gcp/project-factory --inputs "$INPUTS"
# 2) destroy using the same inputs
hyops destroy --env dev --module org/gcp/project-factory --inputs "$INPUTS"
Notes:
- GCP project deletion is asynchronous. A deleted project ID may remain reserved for a period of time, so immediate re-create with the same project_id can fail with 409 alreadyExists.
- For iterative testing, prefer a new project_id per run (for example hybridops-pf-dev2).
Verification¶
-
Confirm module state exists:
ls -la ~/.hybridops/envs/dev/state/modules/org__gcp__project-factory/latest.json -
Confirm GCP readiness marker includes
impersonation_validated=true:cat ~/.hybridops/envs/dev/meta/gcp.ready.json
Troubleshooting¶
- If apply fails with permission errors:
- Use an existing project and skip project-factory, or
-
Ask an admin to create the project / grant permissions (project create + billing link).
-
If you have no Organization (
gcloud organizations listis empty): - Omit
org_id/folder_idand proceed only if your account can create projects under “No organization”.
Maintainer: HybridOps.Studio License: MIT-0 for code, CC-BY-4.0 for documentation