Add context support to artifact-registry, net-lb-app-int, cloudsql modules (#3784)

* artifact-registry

* net-lb-app-int

* copyright

* cloudsql

* fix linting
This commit is contained in:
Ludovico Magnocavallo
2026-03-11 12:35:09 +01:00
committed by GitHub
parent 8c07d09eab
commit a6c284a273
26 changed files with 743 additions and 176 deletions

105
GEMINI.md
View File

@@ -53,16 +53,25 @@ Cloud Foundation Fabric is a comprehensive suite of Terraform modules and end-to
Always format code and update documentation before committing.
```bash
# Format Terraform code
terraform fmt -recursive
# Format Terraform code (check then fix)
terraform fmt -check -recursive modules/<module-name>
terraform fmt -recursive modules/<module-name>
# Update module documentation (variables/outputs tables)
./tools/tfdoc.py modules/<module-name>
# Check README consistency (variables table must match variables.tf)
python3 tools/check_documentation.py modules/<module-name>
# Run all lint checks (wraps pre-commit hooks)
./tools/lint.sh
# Regenerate README variables/outputs tables when check fails
python3 tools/tfdoc.py --replace modules/<module-name>
# YAML linting
yamllint -c .yamllint --no-warnings <yaml-files>
# License/boilerplate check
python3 tools/check_boilerplate.py --scan-files <files>
```
**Common gotcha — unsorted variables (`[SV]` error):** `check_documentation.py` requires variables in `variables.tf` to be in strict alphabetical order. When adding a new variable, insert it at the correct alphabetical position, not at the top of the file.
#### 2. Testing
Tests are written in Python using `pytest` and the [`tftest`](https://pypi.org/project/tftest/) library.
@@ -86,6 +95,90 @@ pytest tests/examples/test_plan.py
* **Commits:** Atomic commits with clear messages.
* **Docs:** Do not manually edit the variables/outputs tables in READMEs; use `tfdoc.py`.
## Adding Context Support to a Module
Several modules support symbolic variable interpolation via a `context` variable. This allows callers to pass symbolic references like `"$project_ids:myprj"` instead of raw values, which get resolved at plan time.
### Pattern
**1. Add a `context` variable** in `variables.tf` at its alphabetical position. Use keys relevant to the module — standard keys are `locations`, `networks`, `project_ids`, `subnets`; module-specific keys may be added (e.g., `kms_keys`, `artifact_registries`, `secrets`):
```hcl
variable "context" {
description = "Context-specific interpolations."
type = object({
kms_keys = optional(map(string), {})
locations = optional(map(string), {})
networks = optional(map(string), {})
project_ids = optional(map(string), {})
})
default = {}
nullable = false
}
```
**2. Build `ctx` and `ctx_p` locals** in `main.tf`. If the module has IAM condition support, exclude `condition_vars` from the flattening (it is passed directly to `templatestring()`):
```hcl
locals {
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
} # add: if k != "condition_vars" — only when condition_vars is a key
}
ctx_p = "$"
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
region = lookup(local.ctx.locations, var.region, var.region)
}
```
**3. Apply lookups in resources.** Three patterns:
```hcl
# Simple field
project = local.project_id
# Nullable field (null must stay null, not looked up)
encryption_key_name = (
var.encryption_key_name == null
? null
: lookup(local.ctx.kms_keys, var.encryption_key_name, var.encryption_key_name)
)
# Deeply optional nested field
private_network = (
try(var.network_config.psa_config.private_network, null) == null
? null
: lookup(local.ctx.networks, var.network_config.psa_config.private_network,
var.network_config.psa_config.private_network)
)
# Per-element list
nat_subnets = [for s in var.nat_subnets : lookup(local.ctx.subnets, s, s)]
```
**4. Long ternaries** are wrapped in parentheses with condition and branches on separate lines:
```hcl
ip_address = (
var.address == null
? null
: lookup(local.ctx.addresses, var.address, var.address)
)
```
### Tests
Add a `context` test alongside existing module tests:
- `tests/modules/<module_name>/tftest.yaml` — declare the module path and list `context:` under `tests:`
- `tests/modules/<module_name>/context.tfvars` — provide all required module variables using symbolic references; include a `context` block with maps that resolve them
- `tests/modules/<module_name>/context.yaml` — assert resolved (concrete) values in the plan output
### README example
Modify one existing README example (do not add a new one) to demonstrate context usage. The resolved values should match the existing inventory YAML so no inventory changes are needed.
## Architecture & Conventions
* **Variables:** Prefer object variables (e.g., `iam = { ... }`) over many individual scalar variables.

View File

@@ -232,15 +232,27 @@ This module implements the same IAM interface than the other modules.
You can choose one (and only one) of the three options below:
```hcl
# Authoritative IAM bindings
# Authoritative IAM bindings with context interpolation for project, location,
# and IAM principals
module "authoritative_iam" {
source = "./fabric/modules/artifact-registry"
project_id = "myproject"
location = "europe-west1"
project_id = "$project_ids:myproject"
location = "$locations:ew1"
name = "myregistry"
format = { docker = { standard = {} } }
context = {
locations = {
ew1 = "europe-west1"
}
iam_principals = {
cicd-team = "group:cicd@example.com"
}
project_ids = {
myproject = "myproject"
}
}
iam = {
"roles/artifactregistry.admin" = ["group:cicd@example.com"]
"roles/artifactregistry.admin" = ["$iam_principals:cicd-team"]
}
}
@@ -300,21 +312,22 @@ module "additive_iam" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [cleanup_policies](variables.tf#L17) | Object containing details about the cleanup policies for an Artifact Registry repository. | <code title="map&#40;object&#40;&#123;&#10; action &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; tag_state &#61; optional&#40;string&#41;&#10; tag_prefixes &#61; optional&#40;list&#40;string&#41;&#41;&#10; older_than &#61; optional&#40;string&#41;&#10; newer_than &#61; optional&#40;string&#41;&#10; package_name_prefixes &#61; optional&#40;list&#40;string&#41;&#41;&#10; version_name_prefixes &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; most_recent_versions &#61; optional&#40;object&#40;&#123;&#10; package_name_prefixes &#61; optional&#40;list&#40;string&#41;&#41;&#10; keep_count &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;&#10;&#10;&#10;default &#61; null">map&#40;object&#40;&#123;&#8230;default &#61; null</code> | ✓ | |
| [format](variables.tf#L62) | Repository format. | <code title="object&#40;&#123;&#10; apt &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; string &#35; &#34;BASE path&#34;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; docker &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; common_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;object&#40;&#123;&#10; immutable_tags &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; kfp &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; generic &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; go &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; googet &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; maven &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;object&#40;&#123;&#10; allow_snapshot_overwrites &#61; optional&#40;bool&#41;&#10; version_policy &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; npm &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; python &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; yum &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; string &#35; &#34;BASE path&#34;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [location](variables.tf#L212) | Registry location. Use `gcloud beta artifacts locations list' to get valid values. | <code>string</code> | ✓ | |
| [name](variables.tf#L217) | Registry name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L222) | Registry project id. | <code>string</code> | ✓ | |
| [format](variables.tf#L79) | Repository format. | <code title="object&#40;&#123;&#10; apt &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; string &#35; &#34;BASE path&#34;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; docker &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; common_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;object&#40;&#123;&#10; immutable_tags &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; kfp &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; generic &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; go &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; googet &#61; optional&#40;object&#40;&#123;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; maven &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;object&#40;&#123;&#10; allow_snapshot_overwrites &#61; optional&#40;bool&#41;&#10; version_policy &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; npm &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; python &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; optional&#40;string&#41;&#10; custom_repository &#61; optional&#40;string&#41;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; virtual &#61; optional&#40;map&#40;object&#40;&#123;&#10; repository &#61; string&#10; priority &#61; number&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#41;&#10; yum &#61; optional&#40;object&#40;&#123;&#10; remote &#61; optional&#40;object&#40;&#123;&#10; public_repository &#61; string &#35; &#34;BASE path&#34;&#10;&#10;&#10; disable_upstream_validation &#61; optional&#40;bool&#41;&#10; upstream_credentials &#61; optional&#40;object&#40;&#123;&#10; username &#61; string&#10; password_secret_version &#61; string&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; standard &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [location](variables.tf#L229) | Registry location. Use `gcloud beta artifacts locations list' to get valid values. | <code>string</code> | ✓ | |
| [name](variables.tf#L234) | Registry name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L239) | Registry project id. | <code>string</code> | ✓ | |
| [cleanup_policy_dry_run](variables.tf#L38) | If true, the cleanup pipeline is prevented from deleting versions in this repository. | <code>bool</code> | | <code>null</code> |
| [description](variables.tf#L44) | An optional description for the repository. | <code>string</code> | | <code>&#34;Terraform-managed registry&#34;</code> |
| [enable_vulnerability_scanning](variables.tf#L50) | Whether vulnerability scanning should be enabled in the repository. | <code>bool</code> | | <code>null</code> |
| [encryption_key](variables.tf#L56) | The KMS key name to use for encryption at rest. | <code>string</code> | | <code>null</code> |
| [context](variables.tf#L44) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; artifact_registries &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; condition_vars &#61; optional&#40;map&#40;map&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; custom_roles &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; iam_principals &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; kms_keys &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; locations &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; project_ids &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; secrets &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; tag_values &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [description](variables.tf#L61) | An optional description for the repository. | <code>string</code> | | <code>&#34;Terraform-managed registry&#34;</code> |
| [enable_vulnerability_scanning](variables.tf#L67) | Whether vulnerability scanning should be enabled in the repository. | <code>bool</code> | | <code>null</code> |
| [encryption_key](variables.tf#L73) | The KMS key name to use for encryption at rest. | <code>string</code> | | <code>null</code> |
| [iam](variables-iam.tf#L36) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings](variables-iam.tf#L43) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings_additive](variables-iam.tf#L58) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_by_principals](variables-iam.tf#L73) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L206) | Labels to be attached to the registry. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L227) | Tag bindings for this repository, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [universe](variables.tf#L234) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | <code title="object&#40;&#123;&#10; package_domain &#61; string&#10; prefix &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [labels](variables.tf#L223) | Labels to be attached to the registry. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L244) | Tag bindings for this repository, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [universe](variables.tf#L251) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | <code title="object&#40;&#123;&#10; package_domain &#61; string&#10; prefix &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2024 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,26 +22,32 @@ moved {
resource "google_artifact_registry_repository_iam_binding" "authoritative" {
provider = google-beta
for_each = local.iam
project = var.project_id
location = google_artifact_registry_repository.registry.location
project = local.project_id
location = local.location
repository = google_artifact_registry_repository.registry.name
role = each.key
members = each.value
role = lookup(local.ctx.custom_roles, each.key, each.key)
members = [
for v in each.value : lookup(local.ctx.iam_principals, v, v)
]
}
# renamed as bindings2 to allow the moved block above
resource "google_artifact_registry_repository_iam_binding" "bindings2" {
for_each = var.iam_bindings
project = var.project_id
location = google_artifact_registry_repository.registry.location
project = local.project_id
location = local.location
repository = google_artifact_registry_repository.registry.name
role = each.value.role
members = each.value.members
role = lookup(local.ctx.custom_roles, each.value.role, each.value.role)
members = [
for v in each.value.members : lookup(local.ctx.iam_principals, v, v)
]
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
content {
expression = each.value.condition.expression
expression = templatestring(
each.value.condition.expression, var.context.condition_vars
)
title = each.value.condition.title
description = each.value.condition.description
}
@@ -50,16 +56,20 @@ resource "google_artifact_registry_repository_iam_binding" "bindings2" {
resource "google_artifact_registry_repository_iam_member" "members" {
for_each = var.iam_bindings_additive
project = var.project_id
location = google_artifact_registry_repository.registry.location
project = local.project_id
location = local.location
repository = google_artifact_registry_repository.registry.name
role = each.value.role
member = each.value.member
role = lookup(local.ctx.custom_roles, each.value.role, each.value.role)
member = lookup(
local.ctx.iam_principals, each.value.member, each.value.member
)
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
content {
expression = each.value.condition.expression
expression = templatestring(
each.value.condition.expression, var.context.condition_vars
)
title = each.value.condition.title
description = each.value.condition.description
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,21 +15,31 @@
*/
locals {
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
} if k != "condition_vars"
}
ctx_p = "$"
format_obj = one([for k, v in var.format : v if v != null])
format_string = one([for k, v in var.format : k if v != null])
location = lookup(local.ctx.locations, var.location, var.location)
mode_string = one([for k, v in local.format_obj : k if v != null && v != false])
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
}
resource "google_artifact_registry_repository" "registry" {
provider = google-beta
project = var.project_id
location = var.location
description = var.description
format = upper(local.format_string)
labels = var.labels
repository_id = var.name
mode = "${upper(local.mode_string)}_REPOSITORY"
kms_key_name = var.encryption_key
provider = google-beta
project = local.project_id
location = local.location
description = var.description
format = upper(local.format_string)
labels = var.labels
repository_id = var.name
mode = "${upper(local.mode_string)}_REPOSITORY"
kms_key_name = var.encryption_key == null ? null : lookup(
local.ctx.kms_keys, var.encryption_key, var.encryption_key
)
cleanup_policy_dry_run = var.cleanup_policy_dry_run
vulnerability_scanning_config {
@@ -95,8 +105,12 @@ resource "google_artifact_registry_repository" "registry" {
for_each = local.format_obj.remote.upstream_credentials != null ? [""] : []
content {
username_password_credentials {
username = local.format_obj.remote.upstream_credentials.username
password_secret_version = local.format_obj.remote.upstream_credentials.password_secret_version
username = local.format_obj.remote.upstream_credentials.username
password_secret_version = lookup(
local.ctx.secrets,
local.format_obj.remote.upstream_credentials.password_secret_version,
local.format_obj.remote.upstream_credentials.password_secret_version
)
}
}
}
@@ -199,9 +213,13 @@ resource "google_artifact_registry_repository" "registry" {
dynamic "upstream_policies" {
for_each = local.format_obj.virtual
content {
id = upstream_policies.key
repository = upstream_policies.value.repository
priority = upstream_policies.value.priority
id = upstream_policies.key
repository = lookup(
local.ctx.artifact_registries,
upstream_policies.value.repository,
upstream_policies.value.repository
)
priority = upstream_policies.value.priority
}
}
}
@@ -221,6 +239,6 @@ resource "google_artifact_registry_repository" "registry" {
resource "google_tags_location_tag_binding" "binding" {
for_each = var.tag_bindings
parent = "//artifactregistry.googleapis.com/${google_artifact_registry_repository.registry.id}"
location = var.location
tag_value = each.value
location = local.location
tag_value = lookup(local.ctx.tag_values, each.value, each.value)
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2024 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,14 +18,14 @@ locals {
url = (
var.universe == null
? join("/", [
"${var.location}-${local.format_string}.pkg.dev",
var.project_id,
"${local.location}-${local.format_string}.pkg.dev",
local.project_id,
var.name
])
: join("/", [
"${local.format_string}.${var.universe.package_domain}",
var.universe.prefix,
element(split(":", var.project_id), 1),
element(split(":", local.project_id), 1),
var.name
])
)

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2024 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,6 +41,23 @@ variable "cleanup_policy_dry_run" {
default = null
}
variable "context" {
description = "Context-specific interpolations."
type = object({
artifact_registries = optional(map(string), {})
condition_vars = optional(map(map(string)), {})
custom_roles = optional(map(string), {})
iam_principals = optional(map(string), {})
kms_keys = optional(map(string), {})
locations = optional(map(string), {})
project_ids = optional(map(string), {})
secrets = optional(map(string), {})
tag_values = optional(map(string), {})
})
default = {}
nullable = false
}
variable "description" {
description = "An optional description for the repository."
type = string

View File

@@ -86,17 +86,22 @@ module "db" {
```hcl
module "db" {
source = "./fabric/modules/cloudsql-instance"
project_id = var.project_id
project_id = "$project_ids:myprj"
context = {
networks = { myvpc = "https://www.googleapis.com/compute/v1/projects/xxx/global/networks/aaa" }
locations = { ew8 = "europe-west8" }
project_ids = { myprj = "project-id" }
}
network_config = {
connectivity = {
psa_config = {
private_network = var.vpc.self_link
private_network = "$networks:myvpc"
}
}
}
name = "db"
prefix = "myprefix"
region = var.region
region = "$locations:ew8"
database_version = "POSTGRES_16"
tier = "db-g1-small"
@@ -408,38 +413,39 @@ module "db" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [database_version](variables.tf#L72) | Database type and version to create. | <code>string</code> | ✓ | |
| [name](variables.tf#L188) | Name of primary instance. | <code>string</code> | ✓ | |
| [network_config](variables.tf#L193) | Network configuration for the instance. Only one between private_network and psc_config can be used. | <code title="object&#40;&#123;&#10; authorized_networks &#61; optional&#40;map&#40;string&#41;&#41;&#10; connectivity &#61; object&#40;&#123;&#10; public_ipv4 &#61; optional&#40;bool, false&#41;&#10; psa_config &#61; optional&#40;object&#40;&#123;&#10; private_network &#61; string&#10; allocated_ip_ranges &#61; optional&#40;object&#40;&#123;&#10; primary &#61; optional&#40;string&#41;&#10; replica &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; psc_allowed_consumer_projects &#61; optional&#40;list&#40;string&#41;&#41;&#10; enable_private_path_for_services &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [project_id](variables.tf#L236) | The ID of the project where this instances will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L241) | Region of the primary instance. | <code>string</code> | ✓ | |
| [tier](variables.tf#L293) | The machine type to use for the instances. | <code>string</code> | ✓ | |
| [activation_policy](variables.tf#L16) | This variable specifies when the instance should be active. Can be either ALWAYS, NEVER or ON_DEMAND. Default is ALWAYS. | <code>string</code> | | <code>&#34;ALWAYS&#34;</code> |
| [availability_type](variables.tf#L27) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>&#34;ZONAL&#34;</code> |
| [backup_configuration](variables.tf#L33) | Backup settings for primary instance. Set to null to leave existing GCP backup settings unmanaged. When set, all fields are managed by Terraform including disabling backups when enabled=false. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; binary_log_enabled &#61; optional&#40;bool, false&#41;&#10; start_time &#61; optional&#40;string, &#34;23:00&#34;&#41;&#10; location &#61; optional&#40;string&#41;&#10; log_retention_days &#61; optional&#40;number, 7&#41;&#10; point_in_time_recovery_enabled &#61; optional&#40;bool&#41;&#10; retention_count &#61; optional&#40;number, 7&#41;&#10; retain_backups_on_delete &#61; optional&#40;bool&#41;&#10; final_backup &#61; optional&#40;object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; retention_days &#61; optional&#40;number, 7&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [collation](variables.tf#L53) | The name of server instance collation. | <code>string</code> | | <code>null</code> |
| [connector_enforcement](variables.tf#L59) | Specifies if connections must use Cloud SQL connectors. | <code>string</code> | | <code>null</code> |
| [data_cache](variables.tf#L65) | Enable data cache. Only used for Enterprise MYSQL and PostgreSQL. | <code>bool</code> | | <code>false</code> |
| [databases](variables.tf#L77) | Databases to create once the primary instance is created. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [disk_autoresize_limit](variables.tf#L83) | The maximum size to which storage capacity can be automatically increased. The default value is 0, which specifies that there is no limit. | <code>number</code> | | <code>0</code> |
| [disk_size](variables.tf#L89) | Disk size in GB. Set to null to enable autoresize. | <code>number</code> | | <code>null</code> |
| [disk_type](variables.tf#L95) | The type of data disk: `PD_SSD` or `PD_HDD`. | <code>string</code> | | <code>&#34;PD_SSD&#34;</code> |
| [edition](variables.tf#L101) | The edition of the instance, can be ENTERPRISE or ENTERPRISE_PLUS. | <code>string</code> | | <code>&#34;ENTERPRISE&#34;</code> |
| [encryption_key_name](variables.tf#L107) | The full path to the encryption key used for the CMEK disk encryption of the primary instance. | <code>string</code> | | <code>null</code> |
| [flags](variables.tf#L113) | Map FLAG_NAME=>VALUE for database-specific tuning. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [gcp_deletion_protection](variables.tf#L119) | Set Google's deletion protection attribute which applies across all surfaces (UI, API, & Terraform). | <code>bool</code> | | <code>true</code> |
| [insights_config](variables.tf#L126) | Query Insights configuration. Defaults to null which disables Query Insights. | <code title="object&#40;&#123;&#10; query_string_length &#61; optional&#40;number, 1024&#41;&#10; record_application_tags &#61; optional&#40;bool, false&#41;&#10; record_client_address &#61; optional&#40;bool, false&#41;&#10; query_plans_per_minute &#61; optional&#40;number, 5&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [labels](variables.tf#L137) | Labels to be attached to all instances. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [maintenance_config](variables.tf#L143) | Set maintenance window configuration and maintenance deny period (up to 90 days). Date format: 'yyyy-mm-dd'. | <code title="object&#40;&#123;&#10; maintenance_window &#61; optional&#40;object&#40;&#123;&#10; day &#61; optional&#40;number&#41;&#10; hour &#61; number&#10; update_track &#61; optional&#40;string, null&#41;&#10; &#125;&#41;, null&#41;&#10; deny_maintenance_period &#61; optional&#40;object&#40;&#123;&#10; start_date &#61; string&#10; end_date &#61; string&#10; start_time &#61; optional&#40;string, &#34;00:00:00&#34;&#41;&#10; &#125;&#41;, null&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [managed_connection_pooling_config](variables.tf#L178) | Configuration for Managed Connection Pooling. NOTE: This feature is only available for PostgreSQL on Enterprise Plus edition instances. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; flags &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [password_validation_policy](variables.tf#L212) | Password validation policy configuration for instances. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, true&#41;&#10; change_interval &#61; optional&#40;number&#41;&#10; default_complexity &#61; optional&#40;bool&#41;&#10; disallow_username_substring &#61; optional&#40;bool&#41;&#10; min_length &#61; optional&#40;number&#41;&#10; reuse_interval &#61; optional&#40;number&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [prefix](variables.tf#L226) | Optional prefix used to generate instance names. | <code>string</code> | | <code>null</code> |
| [replicas](variables.tf#L246) | Map of NAME=> {REGION, KMS_KEY, AVAILABILITY_TYPE} for additional read replicas. Set to null to disable replica creation. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; encryption_key_name &#61; optional&#40;string&#41;&#10; availability_type &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [root_password](variables.tf#L257) | Root password of the Cloud SQL instance, or flag to create a random password. Required for MS SQL Server. | <code title="object&#40;&#123;&#10; password &#61; optional&#40;string&#41;&#10; random_password &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [ssl](variables.tf#L271) | Setting to enable SSL, set config and certificates. | <code title="object&#40;&#123;&#10; client_certificates &#61; optional&#40;list&#40;string&#41;&#41;&#10; mode &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [terraform_deletion_protection](variables.tf#L286) | Prevent terraform from deleting instances. | <code>bool</code> | | <code>true</code> |
| [time_zone](variables.tf#L298) | The time_zone to be used by the database engine (supported only for SQL Server), in SQL Server timezone format. | <code>string</code> | | <code>null</code> |
| [users](variables.tf#L304) | Map of users to create in the primary instance (and replicated to other replicas). For MySQL, anything after the first `@` (if present) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'BUILT_IN', 'CLOUD_IAM_USER' or 'CLOUD_IAM_SERVICE_ACCOUNT'. | <code title="map&#40;object&#40;&#123;&#10; password &#61; optional&#40;string&#41;&#10; password_version &#61; optional&#40;number&#41;&#10; type &#61; optional&#40;string, &#34;BUILT_IN&#34;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [database_version](variables.tf#L85) | Database type and version to create. | <code>string</code> | ✓ | |
| [name](variables.tf#L201) | Name of primary instance. | <code>string</code> | ✓ | |
| [network_config](variables.tf#L206) | Network configuration for the instance. Only one between private_network and psc_config can be used. | <code title="object&#40;&#123;&#10; authorized_networks &#61; optional&#40;map&#40;string&#41;&#41;&#10; connectivity &#61; object&#40;&#123;&#10; public_ipv4 &#61; optional&#40;bool, false&#41;&#10; psa_config &#61; optional&#40;object&#40;&#123;&#10; private_network &#61; string&#10; allocated_ip_ranges &#61; optional&#40;object&#40;&#123;&#10; primary &#61; optional&#40;string&#41;&#10; replica &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;&#10; psc_allowed_consumer_projects &#61; optional&#40;list&#40;string&#41;&#41;&#10; enable_private_path_for_services &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [project_id](variables.tf#L249) | The ID of the project where this instances will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L254) | Region of the primary instance. | <code>string</code> | ✓ | |
| [tier](variables.tf#L306) | The machine type to use for the instances. | <code>string</code> | ✓ | |
| [activation_policy](variables.tf#L17) | This variable specifies when the instance should be active. Can be either ALWAYS, NEVER or ON_DEMAND. Default is ALWAYS. | <code>string</code> | | <code>&#34;ALWAYS&#34;</code> |
| [availability_type](variables.tf#L28) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>&#34;ZONAL&#34;</code> |
| [backup_configuration](variables.tf#L34) | Backup settings for primary instance. Set to null to leave existing GCP backup settings unmanaged. When set, all fields are managed by Terraform including disabling backups when enabled=false. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; binary_log_enabled &#61; optional&#40;bool, false&#41;&#10; start_time &#61; optional&#40;string, &#34;23:00&#34;&#41;&#10; location &#61; optional&#40;string&#41;&#10; log_retention_days &#61; optional&#40;number, 7&#41;&#10; point_in_time_recovery_enabled &#61; optional&#40;bool&#41;&#10; retention_count &#61; optional&#40;number, 7&#41;&#10; retain_backups_on_delete &#61; optional&#40;bool&#41;&#10; final_backup &#61; optional&#40;object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; retention_days &#61; optional&#40;number, 7&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [collation](variables.tf#L54) | The name of server instance collation. | <code>string</code> | | <code>null</code> |
| [connector_enforcement](variables.tf#L60) | Specifies if connections must use Cloud SQL connectors. | <code>string</code> | | <code>null</code> |
| [context](variables.tf#L66) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; kms_keys &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; locations &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; networks &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; project_ids &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_cache](variables.tf#L78) | Enable data cache. Only used for Enterprise MYSQL and PostgreSQL. | <code>bool</code> | | <code>false</code> |
| [databases](variables.tf#L90) | Databases to create once the primary instance is created. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [disk_autoresize_limit](variables.tf#L96) | The maximum size to which storage capacity can be automatically increased. The default value is 0, which specifies that there is no limit. | <code>number</code> | | <code>0</code> |
| [disk_size](variables.tf#L102) | Disk size in GB. Set to null to enable autoresize. | <code>number</code> | | <code>null</code> |
| [disk_type](variables.tf#L108) | The type of data disk: `PD_SSD` or `PD_HDD`. | <code>string</code> | | <code>&#34;PD_SSD&#34;</code> |
| [edition](variables.tf#L114) | The edition of the instance, can be ENTERPRISE or ENTERPRISE_PLUS. | <code>string</code> | | <code>&#34;ENTERPRISE&#34;</code> |
| [encryption_key_name](variables.tf#L120) | The full path to the encryption key used for the CMEK disk encryption of the primary instance. | <code>string</code> | | <code>null</code> |
| [flags](variables.tf#L126) | Map FLAG_NAME=>VALUE for database-specific tuning. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [gcp_deletion_protection](variables.tf#L132) | Set Google's deletion protection attribute which applies across all surfaces (UI, API, & Terraform). | <code>bool</code> | | <code>true</code> |
| [insights_config](variables.tf#L139) | Query Insights configuration. Defaults to null which disables Query Insights. | <code title="object&#40;&#123;&#10; query_string_length &#61; optional&#40;number, 1024&#41;&#10; record_application_tags &#61; optional&#40;bool, false&#41;&#10; record_client_address &#61; optional&#40;bool, false&#41;&#10; query_plans_per_minute &#61; optional&#40;number, 5&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [labels](variables.tf#L150) | Labels to be attached to all instances. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [maintenance_config](variables.tf#L156) | Set maintenance window configuration and maintenance deny period (up to 90 days). Date format: 'yyyy-mm-dd'. | <code title="object&#40;&#123;&#10; maintenance_window &#61; optional&#40;object&#40;&#123;&#10; day &#61; optional&#40;number&#41;&#10; hour &#61; number&#10; update_track &#61; optional&#40;string, null&#41;&#10; &#125;&#41;, null&#41;&#10; deny_maintenance_period &#61; optional&#40;object&#40;&#123;&#10; start_date &#61; string&#10; end_date &#61; string&#10; start_time &#61; optional&#40;string, &#34;00:00:00&#34;&#41;&#10; &#125;&#41;, null&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [managed_connection_pooling_config](variables.tf#L191) | Configuration for Managed Connection Pooling. NOTE: This feature is only available for PostgreSQL on Enterprise Plus edition instances. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; flags &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [password_validation_policy](variables.tf#L225) | Password validation policy configuration for instances. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, true&#41;&#10; change_interval &#61; optional&#40;number&#41;&#10; default_complexity &#61; optional&#40;bool&#41;&#10; disallow_username_substring &#61; optional&#40;bool&#41;&#10; min_length &#61; optional&#40;number&#41;&#10; reuse_interval &#61; optional&#40;number&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [prefix](variables.tf#L239) | Optional prefix used to generate instance names. | <code>string</code> | | <code>null</code> |
| [replicas](variables.tf#L259) | Map of NAME=> {REGION, KMS_KEY, AVAILABILITY_TYPE} for additional read replicas. Set to null to disable replica creation. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; encryption_key_name &#61; optional&#40;string&#41;&#10; availability_type &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [root_password](variables.tf#L270) | Root password of the Cloud SQL instance, or flag to create a random password. Required for MS SQL Server. | <code title="object&#40;&#123;&#10; password &#61; optional&#40;string&#41;&#10; random_password &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [ssl](variables.tf#L284) | Setting to enable SSL, set config and certificates. | <code title="object&#40;&#123;&#10; client_certificates &#61; optional&#40;list&#40;string&#41;&#41;&#10; mode &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [terraform_deletion_protection](variables.tf#L299) | Prevent terraform from deleting instances. | <code>bool</code> | | <code>true</code> |
| [time_zone](variables.tf#L311) | The time_zone to be used by the database engine (supported only for SQL Server), in SQL Server timezone format. | <code>string</code> | | <code>null</code> |
| [users](variables.tf#L317) | Map of users to create in the primary instance (and replicated to other replicas). For MySQL, anything after the first `@` (if present) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'BUILT_IN', 'CLOUD_IAM_USER' or 'CLOUD_IAM_SERVICE_ACCOUNT'. | <code title="map&#40;object&#40;&#123;&#10; password &#61; optional&#40;string&#41;&#10; password_version &#61; optional&#40;number&#41;&#10; type &#61; optional&#40;string, &#34;BUILT_IN&#34;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -1,5 +1,5 @@
/** TO MOD
* Copyright 2024 Google LLC
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,11 +15,33 @@
*/
locals {
prefix = var.prefix == null ? "" : "${var.prefix}-"
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
}
}
ctx_p = "$"
encryption_key_name = (
var.encryption_key_name == null
? null
: lookup(local.ctx.kms_keys, var.encryption_key_name, var.encryption_key_name)
)
has_replicas = length(var.replicas) > 0
is_mysql = can(regex("^MYSQL", var.database_version))
is_postgres = can(regex("^POSTGRES", var.database_version))
has_replicas = length(var.replicas) > 0
is_regional = var.availability_type == "REGIONAL" ? true : false
psa_private_network = (
try(var.network_config.connectivity.psa_config.private_network, null) == null
? null
: lookup(
local.ctx.networks,
var.network_config.connectivity.psa_config.private_network,
var.network_config.connectivity.psa_config.private_network
)
)
prefix = var.prefix == null ? "" : "${var.prefix}-"
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
region = lookup(local.ctx.locations, var.region, var.region)
users = {
for k, v in var.users : k =>
@@ -41,11 +63,11 @@ locals {
resource "google_sql_database_instance" "primary" {
provider = google-beta
project = var.project_id
project = local.project_id
name = "${local.prefix}${var.name}"
region = var.region
region = local.region
database_version = var.database_version
encryption_key_name = var.encryption_key_name
encryption_key_name = local.encryption_key_name
root_password = var.root_password.random_password ? random_password.root_password[0].result : var.root_password.password
settings {
@@ -65,10 +87,8 @@ resource "google_sql_database_instance" "primary" {
retain_backups_on_delete = try(var.backup_configuration.retain_backups_on_delete, null)
ip_configuration {
ipv4_enabled = var.network_config.connectivity.public_ipv4
private_network = try(
var.network_config.connectivity.psa_config.private_network, null
)
ipv4_enabled = var.network_config.connectivity.public_ipv4
private_network = local.psa_private_network
allocated_ip_range = try(
var.network_config.connectivity.psa_config.allocated_ip_ranges.primary, null
)
@@ -234,13 +254,17 @@ resource "google_sql_database_instance" "primary" {
}
resource "google_sql_database_instance" "replicas" {
provider = google-beta
for_each = local.has_replicas ? var.replicas : {}
project = var.project_id
name = "${local.prefix}${each.key}"
region = each.value.region
database_version = var.database_version
encryption_key_name = each.value.encryption_key_name
provider = google-beta
for_each = local.has_replicas ? var.replicas : {}
project = local.project_id
name = "${local.prefix}${each.key}"
region = lookup(local.ctx.locations, each.value.region, each.value.region)
database_version = var.database_version
encryption_key_name = (
each.value.encryption_key_name == null
? null
: lookup(local.ctx.kms_keys, each.value.encryption_key_name, each.value.encryption_key_name)
)
master_instance_name = google_sql_database_instance.primary.name
settings {
@@ -263,9 +287,7 @@ resource "google_sql_database_instance" "replicas" {
ipv4_enabled = (
var.network_config.connectivity.public_ipv4
)
private_network = (
try(var.network_config.connectivity.psa_config.private_network, null)
)
private_network = local.psa_private_network
allocated_ip_range = try(
var.network_config.connectivity.psa_config.allocated_ip_ranges.replica, null
)
@@ -314,7 +336,7 @@ resource "google_sql_database_instance" "replicas" {
resource "google_sql_database" "databases" {
for_each = var.databases != null ? toset(var.databases) : toset([])
project = var.project_id
project = local.project_id
instance = google_sql_database_instance.primary.name
name = each.key
}
@@ -345,7 +367,7 @@ resource "random_password" "root_password" {
resource "google_sql_user" "users" {
for_each = local.users
project = var.project_id
project = local.project_id
instance = google_sql_database_instance.primary.name
name = each.value.name
host = each.value.host
@@ -365,7 +387,7 @@ resource "google_sql_ssl_cert" "client_certificates" {
: toset([])
)
provider = google-beta
project = var.project_id
project = local.project_id
instance = google_sql_database_instance.primary.name
common_name = each.key
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
variable "activation_policy" {
description = "This variable specifies when the instance should be active. Can be either ALWAYS, NEVER or ON_DEMAND. Default is ALWAYS."
type = string
@@ -62,6 +63,18 @@ variable "connector_enforcement" {
default = null
}
variable "context" {
description = "Context-specific interpolations."
type = object({
kms_keys = optional(map(string), {})
locations = optional(map(string), {})
networks = optional(map(string), {})
project_ids = optional(map(string), {})
})
default = {}
nullable = false
}
variable "data_cache" {
description = "Enable data cache. Only used for Enterprise MYSQL and PostgreSQL."
type = bool

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,10 +47,10 @@ resource "google_compute_region_backend_service" "default" {
for_each = var.backend_service_configs
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
region = var.region
region = local.region
name = coalesce(each.value.name, "${var.name}-${each.key}")
description = each.value.description
affinity_cookie_ttl_sec = each.value.affinity_cookie_ttl_sec

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2023 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ resource "google_compute_instance_group" "default" {
for_each = var.group_configs
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
zone = each.value.zone

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ resource "google_compute_health_check" "default" {
for_each = var.health_check_configs
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
name = coalesce(each.value.name, "${var.name}-${each.key}")

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,19 @@
* limitations under the License.
*/
locals {
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
}
}
ctx_p = "$"
network = lookup(local.ctx.networks, var.vpc_config.network, var.vpc_config.network)
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
region = lookup(local.ctx.locations, var.region, var.region)
subnetwork = lookup(local.ctx.subnets, var.vpc_config.subnetwork, var.vpc_config.subnetwork)
}
locals {
# we need keys in the endpoint type to address issue #1055
_neg_endpoints = flatten([
@@ -60,18 +73,22 @@ locals {
}
resource "google_compute_forwarding_rule" "default" {
provider = google-beta
project = var.project_id
region = var.region
name = var.name
description = var.description
ip_address = var.address
provider = google-beta
project = local.project_id
region = local.region
name = var.name
description = var.description
ip_address = (
var.address == null
? null
: lookup(local.ctx.addresses, var.address, var.address)
)
ip_protocol = "TCP"
load_balancing_scheme = "INTERNAL_MANAGED"
network = var.vpc_config.network
network = local.network
network_tier = var.network_tier_premium ? "PREMIUM" : "STANDARD"
port_range = join(",", local.fwd_rule_ports)
subnetwork = var.vpc_config.subnetwork
subnetwork = local.subnetwork
labels = var.labels
target = local.fwd_rule_target
# during the preview phase you cannot change this attribute on an existing rule
@@ -87,8 +104,8 @@ resource "google_compute_forwarding_rule" "default" {
resource "google_compute_region_ssl_certificate" "default" {
for_each = var.ssl_certificates.create_configs
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = coalesce(each.value.name, "${var.name}-${each.key}")
certificate = each.value.certificate
private_key = each.value.private_key
@@ -100,8 +117,8 @@ resource "google_compute_region_ssl_certificate" "default" {
resource "google_compute_region_target_http_proxy" "default" {
count = var.protocol == "HTTPS" ? 0 : 1
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = coalesce(var.https_proxy_config.name, var.name)
description = var.http_proxy_config.description
url_map = google_compute_region_url_map.default.id
@@ -109,8 +126,8 @@ resource "google_compute_region_target_http_proxy" "default" {
resource "google_compute_region_target_https_proxy" "default" {
count = var.protocol == "HTTPS" ? 1 : 0
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = coalesce(var.https_proxy_config.name, var.name)
description = var.https_proxy_config.description
ssl_certificates = length(local.proxy_ssl_certificates) == 0 ? null : local.proxy_ssl_certificates
@@ -121,12 +138,14 @@ resource "google_compute_region_target_https_proxy" "default" {
resource "google_compute_service_attachment" "default" {
count = var.service_attachment == null ? 0 : 1
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = var.name
description = var.description
target_service = google_compute_forwarding_rule.default.id
nat_subnets = var.service_attachment.nat_subnets
nat_subnets = [
for s in var.service_attachment.nat_subnets : lookup(local.ctx.subnets, s, s)
]
connection_preference = (
var.service_attachment.automatic_connection
? "ACCEPT_AUTOMATIC"
@@ -154,7 +173,7 @@ resource "google_compute_network_endpoint_group" "default" {
for_each = local.neg_zonal
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
zone = each.value.zone
@@ -164,12 +183,12 @@ resource "google_compute_network_endpoint_group" "default" {
description = var.description
network_endpoint_type = each.value.type
network = (
each.value.network != null ? each.value.network : var.vpc_config.network
each.value.network != null ? each.value.network : local.network
)
subnetwork = (
each.value.type == "NON_GCP_PRIVATE_IP_PORT"
? null
: coalesce(each.value.subnetwork, var.vpc_config.subnetwork)
: coalesce(each.value.subnetwork, local.subnetwork)
)
}
@@ -191,7 +210,7 @@ resource "google_compute_region_network_endpoint_group" "default" {
for_each = local.neg_regional
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
region = each.value.region
@@ -211,7 +230,7 @@ resource "google_compute_region_network_endpoint_group" "psc" {
for_each = local.neg_regional_psc
project = (
each.value.project_id == null
? var.project_id
? local.project_id
: each.value.project_id
)
region = each.value.psc.region
@@ -246,7 +265,7 @@ locals {
resource "google_compute_region_network_endpoint_group" "internet" {
for_each = local.neg_internet
project = var.project_id
project = local.project_id
name = "${var.name}-${each.key}"
region = each.value.internet.region
# re-enable once provider properly supports this
@@ -255,7 +274,7 @@ resource "google_compute_region_network_endpoint_group" "internet" {
network_endpoint_type = (
each.value.internet.use_fqdn ? "INTERNET_FQDN_PORT" : "INTERNET_IP_PORT"
)
network = var.vpc_config.network
network = local.network
}
resource "google_compute_region_network_endpoint" "internet" {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,8 +24,8 @@ locals {
resource "google_compute_region_url_map" "default" {
provider = google-beta
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = var.name
description = var.urlmap_config.description
default_service = (

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,19 @@ variable "address" {
default = null
}
variable "context" {
description = "Context-specific interpolations."
type = object({
addresses = optional(map(string), {})
locations = optional(map(string), {})
networks = optional(map(string), {})
project_ids = optional(map(string), {})
subnets = optional(map(string), {})
})
default = {}
nullable = false
}
variable "description" {
description = "Optional description used for resources."
type = string

View File

@@ -0,0 +1,73 @@
context = {
artifact_registries = {
upstream-one = "projects/actual-project-id/locations/europe-west8/repositories/upstream"
}
condition_vars = {
organization = {
id = "1234567890"
}
}
custom_roles = {
myrole_one = "organizations/366118655033/roles/myRoleOne"
myrole_two = "organizations/366118655033/roles/myRoleTwo"
myrole_three = "organizations/366118655033/roles/myRoleThree"
myrole_four = "organizations/366118655033/roles/myRoleFour"
}
iam_principals = {
mysa = "serviceAccount:test@test-project.iam.gserviceaccount.com"
myuser = "user:test-user@example.com"
myuser2 = "user:test-user2@example.com"
}
locations = {
ew8 = "europe-west8"
}
project_ids = {
myproject = "actual-project-id"
}
tag_values = {
"test/one" = "tagValues/1234567890"
}
}
project_id = "$project_ids:myproject"
name = "myregistry"
location = "$locations:ew8"
format = {
docker = {
virtual = {
upstream-one = {
repository = "$artifact_registries:upstream-one"
priority = 100
}
}
}
}
iam = {
"$custom_roles:myrole_one" = ["$iam_principals:myuser"]
"roles/viewer" = ["$iam_principals:mysa"]
}
iam_bindings = {
myrole_two = {
role = "$custom_roles:myrole_two"
members = ["$iam_principals:mysa"]
condition = {
title = "Test"
expression = "resource.matchTag('$${organization.id}/environment', 'development')"
}
}
}
iam_bindings_additive = {
myrole_three = {
role = "$custom_roles:myrole_three"
member = "$iam_principals:mysa"
}
}
iam_by_principals = {
"$iam_principals:myuser2" = [
"$custom_roles:myrole_three",
"$custom_roles:myrole_four",
"roles/owner",
]
}
tag_bindings = {
foo = "$tag_values:test/one"
}

View File

@@ -0,0 +1,108 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
google_artifact_registry_repository.registry:
cleanup_policies: []
cleanup_policy_dry_run: null
description: Terraform-managed registry
docker_config: []
effective_labels:
goog-terraform-provisioned: 'true'
format: DOCKER
kms_key_name: null
labels: null
location: europe-west8
maven_config: []
mode: VIRTUAL_REPOSITORY
project: actual-project-id
remote_repository_config: []
repository_id: myregistry
terraform_labels:
goog-terraform-provisioned: 'true'
timeouts: null
virtual_repository_config:
- upstream_policies:
- id: upstream-one
priority: 100
repository: projects/actual-project-id/locations/europe-west8/repositories/upstream
google_artifact_registry_repository_iam_binding.authoritative["$custom_roles:myrole_four"]:
condition: []
location: europe-west8
members:
- user:test-user2@example.com
project: actual-project-id
role: organizations/366118655033/roles/myRoleFour
google_artifact_registry_repository_iam_binding.authoritative["$custom_roles:myrole_one"]:
condition: []
location: europe-west8
members:
- user:test-user@example.com
project: actual-project-id
role: organizations/366118655033/roles/myRoleOne
google_artifact_registry_repository_iam_binding.authoritative["$custom_roles:myrole_three"]:
condition: []
location: europe-west8
members:
- user:test-user2@example.com
project: actual-project-id
role: organizations/366118655033/roles/myRoleThree
google_artifact_registry_repository_iam_binding.authoritative["roles/owner"]:
condition: []
location: europe-west8
members:
- user:test-user2@example.com
project: actual-project-id
role: roles/owner
google_artifact_registry_repository_iam_binding.authoritative["roles/viewer"]:
condition: []
location: europe-west8
members:
- serviceAccount:test@test-project.iam.gserviceaccount.com
project: actual-project-id
role: roles/viewer
google_artifact_registry_repository_iam_binding.bindings2["myrole_two"]:
condition:
- description: null
expression: resource.matchTag('1234567890/environment', 'development')
title: Test
location: europe-west8
members:
- serviceAccount:test@test-project.iam.gserviceaccount.com
project: actual-project-id
role: organizations/366118655033/roles/myRoleTwo
google_artifact_registry_repository_iam_member.members["myrole_three"]:
condition: []
location: europe-west8
member: serviceAccount:test@test-project.iam.gserviceaccount.com
project: actual-project-id
role: organizations/366118655033/roles/myRoleThree
google_tags_location_tag_binding.binding["foo"]:
location: europe-west8
tag_value: tagValues/1234567890
timeouts: null
counts:
google_artifact_registry_repository: 1
google_artifact_registry_repository_iam_binding: 6
google_artifact_registry_repository_iam_member: 1
google_tags_location_tag_binding: 1
modules: 0
resources: 9
outputs:
id: __missing__
name: __missing__
repository: __missing__
url: europe-west8-docker.pkg.dev/actual-project-id/myregistry

View File

@@ -15,4 +15,5 @@
module: modules/artifact-registry
tests:
context:
universe:

View File

@@ -0,0 +1,21 @@
context = {
kms_keys = { mykey = "projects/myprj/locations/europe-west8/keyRings/mykr/cryptoKeys/mykey" }
locations = { ew8 = "europe-west8" }
networks = { myvpc = "projects/myprj/global/networks/myvpc" }
project_ids = { myprj = "my-project" }
}
project_id = "$project_ids:myprj"
region = "$locations:ew8"
name = "db-test"
database_version = "POSTGRES_13"
tier = "db-g1-small"
network_config = {
connectivity = {
psa_config = {
private_network = "$networks:myvpc"
}
}
}
encryption_key_name = "$kms_keys:mykey"
gcp_deletion_protection = false
terraform_deletion_protection = false

View File

@@ -0,0 +1,30 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
google_sql_database_instance.primary:
database_version: POSTGRES_13
encryption_key_name: projects/myprj/locations/europe-west8/keyRings/mykr/cryptoKeys/mykey
name: db-test
project: my-project
region: europe-west8
settings:
- ip_configuration:
- ipv4_enabled: false
private_network: projects/myprj/global/networks/myvpc
counts:
google_sql_database_instance: 1
modules: 0
resources: 1

View File

@@ -0,0 +1,18 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module: modules/cloudsql-instance
tests:
context:

View File

@@ -0,0 +1,35 @@
context = {
addresses = {
test = "10.0.0.10"
}
locations = {
ew8 = "europe-west8"
}
networks = {
test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
}
project_ids = {
test = "foo-test-0"
}
subnets = {
test = "projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/gce"
test-nat = "projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/test-nat"
}
}
project_id = "$project_ids:test"
region = "$locations:ew8"
vpc_config = {
network = "$networks:test"
subnetwork = "$subnets:test"
}
address = "$addresses:test"
backend_service_configs = {
default = {
backends = [{
group = "projects/foo-test-0/zones/europe-west8-a/instanceGroups/my-ig"
}]
}
}
service_attachment = {
nat_subnets = ["$subnets:test-nat"]
}

View File

@@ -0,0 +1,49 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
google_compute_forwarding_rule.default:
ip_address: 10.0.0.10
load_balancing_scheme: INTERNAL_MANAGED
name: ilb-l7-test
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
project: foo-test-0
region: europe-west8
subnetwork: projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/gce
google_compute_health_check.default["default"]:
project: foo-test-0
google_compute_region_backend_service.default["default"]:
project: foo-test-0
region: europe-west8
google_compute_region_target_http_proxy.default[0]:
project: foo-test-0
region: europe-west8
google_compute_region_url_map.default:
project: foo-test-0
region: europe-west8
google_compute_service_attachment.default[0]:
nat_subnets:
- projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/test-nat
project: foo-test-0
region: europe-west8
counts:
google_compute_forwarding_rule: 1
google_compute_health_check: 1
google_compute_region_backend_service: 1
google_compute_region_target_http_proxy: 1
google_compute_region_url_map: 1
google_compute_service_attachment: 1
modules: 0
resources: 6

View File

@@ -1,4 +1,4 @@
# Copyright 2023 Google LLC
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@ module: modules/net-lb-app-int
common_tfvars:
- common.tfvars
tests:
context:
defaults:
groups:
health-checks-custom: