Fix issues with FAST CI/CD support (#3454)

* wip, broken

* wip

* streamline locals

* tfdoc

* update yaml files

* refactor
This commit is contained in:
Ludovico Magnocavallo
2025-10-23 16:40:06 +02:00
committed by GitHub
parent 393e99194a
commit 80988c0bbf
9 changed files with 326 additions and 277 deletions

View File

@@ -646,7 +646,7 @@ Define values for the `var.environments` variable in a tfvars file.
| name | description | modules | resources | | name | description | modules | resources |
|---|---|---|---| |---|---|---|---|
| [billing.tf](./billing.tf) | None | <code>billing-account</code> | | | [billing.tf](./billing.tf) | None | <code>billing-account</code> | |
| [cicd.tf](./cicd.tf) | None | | <code>google_iam_workload_identity_pool</code> · <code>google_iam_workload_identity_pool_provider</code> · <code>google_storage_bucket_object</code> · <code>local_file</code> | | [cicd.tf](./cicd.tf) | None | <code>iam-service-account</code> | <code>google_storage_bucket_object</code> · <code>local_file</code> |
| [factory.tf](./factory.tf) | None | <code>project-factory</code> | | | [factory.tf](./factory.tf) | None | <code>project-factory</code> | |
| [imports.tf](./imports.tf) | None | | | | [imports.tf](./imports.tf) | None | | |
| [main.tf](./main.tf) | Module-level locals and resources. | | <code>terraform_data</code> | | [main.tf](./main.tf) | Module-level locals and resources. | | <code>terraform_data</code> |
@@ -655,6 +655,7 @@ Define values for the `var.environments` variable in a tfvars file.
| [outputs.tf](./outputs.tf) | Module outputs. | | | | [outputs.tf](./outputs.tf) | Module outputs. | | |
| [variables.tf](./variables.tf) | Module variables. | | | | [variables.tf](./variables.tf) | Module variables. | | |
| [wif-definitions.tf](./wif-definitions.tf) | Workload Identity provider definitions. | | | | [wif-definitions.tf](./wif-definitions.tf) | Workload Identity provider definitions. | | |
| [wif-providers.tf](./wif-providers.tf) | None | | <code>google_iam_workload_identity_pool</code> · <code>google_iam_workload_identity_pool_provider</code> |
## Variables ## Variables

View File

@@ -26,20 +26,20 @@ on:
env: env:
FAST_SERVICE_ACCOUNT: ${service_accounts.apply} FAST_SERVICE_ACCOUNT: ${service_accounts.apply}
FAST_SERVICE_ACCOUNT_PLAN: ${service_accounts.plan} FAST_SERVICE_ACCOUNT_PLAN: ${service_accounts.plan}
FAST_WIF_PROVIDER: ${identity_provider} FAST_WIF_PROVIDER: ${workload_identity.pool_id}
SSH_AUTH_SOCK: /tmp/ssh_agent.sock SSH_AUTH_SOCK: /tmp/ssh_agent.sock
TF_PROVIDERS_FILE: ${tf_providers_files.apply} TF_PROVIDERS_FILE: ${provider_files.apply}
TF_PROVIDERS_FILE_PLAN: ${tf_providers_files.plan} TF_PROVIDERS_FILE_PLAN: ${provider_files.plan}
TF_VERSION: 1.12.2 TF_VERSION: 1.12.2
jobs: jobs:
fast-pr: fast-pr:
# Skip PRs which are closed without being merged. # Skip PRs which are closed without being merged.
if: >- if: >-
github.event.action == 'closed' && github.event.action == 'closed' &&
github.event.pull_request.merged == true || github.event.pull_request.merged == true ||
github.event.action == 'opened' || github.event.action == 'opened' ||
github.event.action == 'synchronize' github.event.action == 'synchronize'
permissions: permissions:
contents: read contents: read
id-token: write id-token: write
@@ -99,7 +99,7 @@ jobs:
run: | run: |
gcloud storage cp -r \ gcloud storage cp -r \
"gs://${outputs_bucket}/providers/$${{env.provider_file}}" ./ "gs://${outputs_bucket}/providers/$${{env.provider_file}}" ./
%{~ for f in tf_var_files ~} %{~ for f in tfvars_files ~}
gcloud storage cp -r \ gcloud storage cp -r \
"gs://${outputs_bucket}/tfvars/${f}" ./ "gs://${outputs_bucket}/tfvars/${f}" ./
%{~ endfor ~} %{~ endfor ~}

View File

@@ -15,10 +15,10 @@
variables: variables:
GOOGLE_CREDENTIALS: cicd-sa-credentials.json GOOGLE_CREDENTIALS: cicd-sa-credentials.json
FAST_OUTPUTS_BUCKET: ${outputs_bucket} FAST_OUTPUTS_BUCKET: ${outputs_bucket}
FAST_WIF_PROVIDER: ${identity_provider} FAST_WIF_PROVIDER: ${workload_identity.pool_id}
SSH_AUTH_SOCK: /tmp/ssh_agent.sock SSH_AUTH_SOCK: /tmp/ssh_agent.sock
%{~ if tf_var_files != [] ~} %{~ if tfvars_files != [] ~}
TF_VAR_FILES: ${join("\n ", tf_var_files)} TF_VAR_FILES: ${join("\n ", tfvars_files)}
%{~ endif ~} %{~ endif ~}
workflow: workflow:
@@ -28,13 +28,13 @@ workflow:
variables: variables:
COMMAND: apply COMMAND: apply
FAST_SERVICE_ACCOUNT: ${service_accounts.apply} FAST_SERVICE_ACCOUNT: ${service_accounts.apply}
TF_PROVIDERS_FILE: ${tf_providers_files.apply} TF_PROVIDERS_FILE: ${provider_files.apply}
# pr / plan # pr / plan
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
variables: variables:
COMMAND: plan COMMAND: plan
FAST_SERVICE_ACCOUNT: ${service_accounts.plan} FAST_SERVICE_ACCOUNT: ${service_accounts.plan}
TF_PROVIDERS_FILE: ${tf_providers_files.plan} TF_PROVIDERS_FILE: ${provider_files.plan}
stages: stages:
- gcp-setup - gcp-setup
@@ -50,13 +50,13 @@ gcp-setup:
paths: paths:
- cicd-sa-credentials.json - cicd-sa-credentials.json
- providers.tf - providers.tf
%{~ for f in tf_var_files ~} %{~ for f in tfvars_files ~}
- ${f} - ${f}
%{~ endfor ~} %{~ endfor ~}
id_tokens: id_tokens:
GITLAB_TOKEN: GITLAB_TOKEN:
aud: aud:
%{~ for aud in audiences ~} %{~ for aud in workload_identity.audiences ~}
- ${aud} - ${aud}
%{~ endfor ~} %{~ endfor ~}
before_script: before_script:
@@ -71,7 +71,7 @@ gcp-setup:
--credential-source-file=token.txt --credential-source-file=token.txt
- gcloud config set auth/credential_file_override $GOOGLE_CREDENTIALS - gcloud config set auth/credential_file_override $GOOGLE_CREDENTIALS
- gcloud storage cp -r "gs://$FAST_OUTPUTS_BUCKET/providers/$TF_PROVIDERS_FILE" ./providers.tf - gcloud storage cp -r "gs://$FAST_OUTPUTS_BUCKET/providers/$TF_PROVIDERS_FILE" ./providers.tf
%{~ for f in tf_var_files ~} %{~ for f in tfvars_files ~}
- gcloud storage cp gs://$FAST_OUTPUTS_BUCKET/tfvars/${f} ./ - gcloud storage cp gs://$FAST_OUTPUTS_BUCKET/tfvars/${f} ./
%{~ endfor ~} %{~ endfor ~}
@@ -83,7 +83,7 @@ tf-plan-apply:
id_tokens: id_tokens:
GITLAB_TOKEN: GITLAB_TOKEN:
aud: aud:
%{~ for aud in audiences ~} %{~ for aud in workload_identity.audiences ~}
- ${aud} - ${aud}
%{~ endfor ~} %{~ endfor ~}
image: image:

View File

@@ -15,126 +15,120 @@
*/ */
locals { locals {
_cicd = try(yamldecode(file(local.paths.cicd)), {}) # raw configuration (the wif files are also users of this local)
_cicd_identity_providers = { cicd = try(yamldecode(file(local.paths.cicd)), {})
for k, v in google_iam_workload_identity_pool_provider.default : # dereferencing maps
"$wif_providers:${k}" => v.name cicd_ctx_sa = {
} for k, v in merge(local.ctx.iam_principals, module.factory.iam_principals) :
_cicd_output_files = { "$iam_principals:${k}" => v
for k, v in google_storage_bucket_object.providers :
"$output_files:providers/${k}" => split("/", v.name)[1]
}
cicd_project_ids = {
for k, v in merge(
var.context.project_ids,
module.factory.project_ids
) : "$project_ids:${k}" => v
} }
cicd_ctx_wif = try({
"$wif_pools:${local.wif_pool_name}" = google_iam_workload_identity_pool.default.0.name
}, {})
# normalize workflow configurations
cicd_workflows = { cicd_workflows = {
for k, v in lookup(local._cicd, "workflows", {}) : k => { for k, v in lookup(local.cicd, "workflows", {}) : k => merge(v, {
outputs_bucket = lookup( iam_principal_templates = {
local.of_buckets, branch = local.wif_defs[v.repository.type].principal_branch
v.output_files.storage_bucket, repo = local.wif_defs[v.repository.type].principal_repo
v.output_files.storage_bucket }
) repository = merge(v.repository, {
workflow = templatefile("assets/workflow-${v.template}.yaml", { apply_branches = try(v.repository.apply_branches, [])
identity_provider = lookup(
local._cicd_identity_providers,
v.workload_identity_provider.id,
v.workload_identity_provider.id
)
audiences = try(v.workload_identity_provider.audiences, [])
service_accounts = {
apply = lookup(
local.of_service_accounts,
v.service_accounts.apply,
v.service_accounts.apply
)
plan = lookup(
local.of_service_accounts,
v.service_accounts.plan,
v.service_accounts.plan
)
}
outputs_bucket = lookup(
local.of_buckets,
v.output_files.storage_bucket,
v.output_files.storage_bucket
)
stage_name = k
tf_providers_files = {
apply = lookup(
local._cicd_output_files,
v.output_files.providers.apply,
v.output_files.providers.apply
)
plan = lookup(
local._cicd_output_files,
v.output_files.providers.plan,
v.output_files.providers.plan
)
}
tf_var_files = try(v.output_files.files, [])
}) })
} service_accounts = {
} apply = trimprefix(try(
wif_project = try(local._cicd.workload_identity_federation.project, null) local.cicd_ctx_sa[v.service_accounts.apply], v.service_accounts.apply
wif_providers = { ), "serviceAccount:")
for k, v in try(local._cicd.workload_identity_federation.providers, {}) : plan = trimprefix(try(
k => merge(v, lookup(local.wif_defs, v.issuer, {})) local.cicd_ctx_sa[v.service_accounts.plan], v.service_accounts.plan
} ), "serviceAccount:")
} }
workload_identity = {
resource "google_iam_workload_identity_pool" "default" { audiences = try(v.workload_identity.audiences, [])
count = local.wif_project == null ? 0 : 1 pool_id = try(
project = lookup( local.cicd_ctx_wif[v.workload_identity.pool_id],
local.cicd_project_ids, local.wif_project, local.wif_project v.workload_identity.pool_id
) )
workload_identity_pool_id = try( }
local._cicd.workload_identity_federation.pool_name, "iac-0" })
) if(
} try(local.wif_defs[v.repository.type], null) != null &&
try(v.provider_files.apply, null) != null &&
resource "google_iam_workload_identity_pool_provider" "default" { try(v.provider_files.plan, null) != null &&
for_each = local.wif_providers try(v.repository.name, null) != null &&
project = ( try(v.service_accounts.apply, null) != null &&
google_iam_workload_identity_pool.default[0].project try(v.service_accounts.plan, null) != null &&
) try(v.workload_identity.pool_id, null) != null
workload_identity_pool_id = (
google_iam_workload_identity_pool.default[0].workload_identity_pool_id
)
workload_identity_pool_provider_id = lookup(each.value, "provider_id", each.key)
attribute_condition = lookup(
each.value, "attribute_condition", null
)
attribute_mapping = lookup(
each.value, "attribute_mapping", {}
)
oidc {
# Setting an empty list configures allowed_audiences to the url of the provider
allowed_audiences = try(each.value.custom_settings.audiences, [])
# If users don't provide an issuer_uri, we set the public one for the platform chosen.
issuer_uri = (
try(each.value.custom_settings.issuer_uri, null) != null
? each.value.custom_settings.issuer_uri
: try(each.value.issuer_uri, null)
) )
# OIDC JWKs in JSON String format. If no value is provided, they key is }
# fetched from the `.well-known` path for the issuer_uri # generate workflow files contents
jwks_json = try(each.value.custom_settings.jwks_json, null) cicd_workflows_contents = {
for k, v in local.cicd_workflows : k => templatefile(
"assets/workflow-${v.repository.type}.yaml", merge(v, {
outputs_bucket = local.of_outputs_bucket
stage_name = k
})
)
}
}
module "cicd-sa-apply" {
source = "../../../modules/iam-service-account"
for_each = local.cicd_workflows
name = each.value.service_accounts.apply
service_account_reuse = {
use_data_source = false
}
iam = {
"roles/iam.workloadIdentityUser" = (
length(each.value.repository.apply_branches) == 0
? [
format(
each.value.iam_principal_templates.repo,
each.value.workload_identity.pool_id,
each.value.repository.name
)
]
: [
for v in each.value.repository.apply_branches : format(
each.value.iam_principal_templates.branch,
each.value.workload_identity.pool_id,
each.value.repository.name,
v
)
]
)
}
}
module "cicd-sa-plan" {
source = "../../../modules/iam-service-account"
for_each = local.cicd_workflows
name = each.value.service_accounts.plan
service_account_reuse = {
use_data_source = false
}
iam = {
"roles/iam.workloadIdentityUser" = [
format(
each.value.iam_principal_templates.repo,
each.value.workload_identity.pool_id,
each.value.repository.name
)
]
} }
} }
resource "local_file" "workflows" { resource "local_file" "workflows" {
for_each = local.of_path == null ? {} : local.cicd_workflows for_each = local.of_path == null ? {} : local.cicd_workflows_contents
file_permission = "0644" file_permission = "0644"
filename = "${local.of_path}/workflows/${each.key}.yaml" filename = "${local.of_path}/workflows/${each.key}.yaml"
content = each.value.workflow content = each.value
} }
resource "google_storage_bucket_object" "workflows" { resource "google_storage_bucket_object" "workflows" {
for_each = local.cicd_workflows for_each = local.output_files.storage_bucket == null ? {} : local.cicd_workflows_contents
bucket = each.value.outputs_bucket bucket = local.of_outputs_bucket
name = "workflows/${each.key}.yaml" name = "workflows/${each.key}.yaml"
content = each.value.workflow content = each.value
} }

View File

@@ -28,20 +28,20 @@ workload_identity_federation:
# jwks_json_path: # jwks_json_path:
workflows: workflows:
org-setup: org-setup:
template: github provider_files:
workload_identity_provider: apply: 0-org-setup-providers.tf
id: $wif_providers:github plan: 0-org-setup-providers-ro.tf
audiences: []
repository: repository:
name: org-setup name: gh-org/gh-repo
branch: main type: github
output_files: apply_branches:
storage_bucket: $storage_buckets:iac-0/iac-outputs - master
providers: - fast-dev
apply: $output_files:providers/0-org-setup
plan: $output_files:providers/0-org-setup-ro
files:
- 0-org-setup.auto.tfvars.json
service_accounts: service_accounts:
apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw
plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro
tfvars_files:
- 0-org-setup.auto.tfvars
workload_identity:
pool_id: $wif_pools:iac-0
audiences: []

View File

@@ -4,6 +4,106 @@
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"workflows": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z-][a-z0-9-]+$": {
"type": "object",
"additionalProperties": false,
"required": [
"provider_files",
"repository",
"service_accounts",
"workload_identity"
],
"properties": {
"provider_files": {
"type": "object",
"additionalProperties": false,
"required": [
"apply",
"plan"
],
"properties": {
"apply": {
"type": "string"
},
"plan": {
"type": "string"
}
}
},
"repository": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"type"
],
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"github",
"gitlab"
]
},
"apply_branches": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"service_accounts": {
"type": "object",
"additionalProperties": false,
"required": [
"apply",
"plan"
],
"properties": {
"apply": {
"type": "string"
},
"plan": {
"type": "string"
}
}
},
"tfvars_files": {
"type": "array",
"items": {
"type": "string"
}
},
"workload_identity": {
"type": "object",
"additionalProperties": false,
"required": [
"pool_id"
],
"properties": {
"pool_id": {
"type": "string"
},
"audiences": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
},
"workload_identity_federation": { "workload_identity_federation": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -66,106 +166,6 @@
} }
} }
} }
},
"workflows": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z-][a-z0-9-]+$": {
"type": "object",
"additionalProperties": false,
"minProperties": 5,
"properties": {
"output_files": {
"type": "object",
"additionalProperties": false,
"required": [
"providers",
"storage_bucket"
],
"properties": {
"files": {
"type": "array",
"items": {
"type": "string"
}
},
"providers": {
"type": "object",
"additionalProperties": false,
"required": [
"apply",
"plan"
],
"properties": {
"apply": {
"type": "string"
},
"plan": {
"type": "string"
}
}
},
"storage_bucket": {
"type": "string"
}
}
},
"repository": {
"type": "object",
"additionalProperties": false,
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"branch": {
"type": "string"
}
}
},
"service_accounts": {
"type": "object",
"additionalProperties": false,
"properties": {
"apply": {
"type": "string"
},
"plan": {
"type": "string"
}
}
},
"template": {
"type": "string",
"enum": [
"github",
"gitlab"
]
},
"workload_identity_provider": {
"type": "object",
"additionalProperties": false,
"required": [
"id"
],
"properties": {
"audiences": {
"type": "array",
"items": {
"type": "string"
}
},
"id": {
"type": "string"
}
}
}
}
}
}
} }
} }
} }

View File

@@ -0,0 +1,62 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
locals {
wif_ctx_project_ids = {
for k, v in merge(var.context.project_ids, module.factory.project_ids) :
"$project_ids:${k}" => v
}
wif_pool_name = try(
local.cicd.workload_identity_federation.pool_name, "iac-0"
)
wif_project = try(local.cicd.workload_identity_federation.project, null)
wif_providers = local.wif_project == null ? {} : {
for k, v in try(local.cicd.workload_identity_federation.providers, {}) :
k => merge(v, lookup(local.wif_defs, v.issuer, {}))
}
}
resource "google_iam_workload_identity_pool" "default" {
count = local.wif_project == null ? 0 : 1
project = lookup(
local.wif_ctx_project_ids, local.wif_project, local.wif_project
)
workload_identity_pool_id = local.wif_pool_name
}
resource "google_iam_workload_identity_pool_provider" "default" {
for_each = local.wif_providers
project = google_iam_workload_identity_pool.default[0].project
workload_identity_pool_id = (
google_iam_workload_identity_pool.default[0].workload_identity_pool_id
)
workload_identity_pool_provider_id = lookup(each.value, "provider_id", each.key)
attribute_condition = lookup(each.value, "attribute_condition", null)
attribute_mapping = lookup(each.value, "attribute_mapping", {})
oidc {
# Setting an empty list configures allowed_audiences to the url of the provider
allowed_audiences = try(each.value.custom_settings.audiences, [])
# If users don't provide an issuer_uri, we set the public one for the platform chosen.
issuer_uri = (
try(each.value.custom_settings.issuer_uri, null) != null
? each.value.custom_settings.issuer_uri
: try(each.value.issuer_uri, null)
)
# OIDC JWKs in JSON String format. If no value is provided, they key is
# fetched from the `.well-known` path for the issuer_uri
jwks_json = try(each.value.custom_settings.jwks_json, null)
}
}

View File

@@ -14,6 +14,22 @@
# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/cicd.schema.json # yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/cicd.schema.json
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../schemas/cicd.schema.json
workload_identity_federation: workload_identity_federation:
pool_name: iac-0 pool_name: iac-0
project: $project_ids:iac-0 project: $project_ids:iac-0
@@ -28,20 +44,20 @@ workload_identity_federation:
# jwks_json_path: # jwks_json_path:
workflows: workflows:
org-setup: org-setup:
template: github provider_files:
workload_identity_provider: apply: 0-org-setup-providers.tf
id: $wif_providers:github plan: 0-org-setup-providers-ro.tf
audiences: []
repository: repository:
name: org-setup name: gh-org/gh-repo
branch: main type: github
output_files: apply_branches:
storage_bucket: $storage_buckets:iac-0/iac-outputs - master
providers: - fast-dev
apply: $output_files:providers/0-org-setup
plan: $output_files:providers/0-org-setup-ro
files:
- tfvars/0-boostrap.auto.tfvars.json
service_accounts: service_accounts:
apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw
plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro
tfvars_files:
- 0-org-setup.auto.tfvars
workload_identity:
pool_id: $wif_pools:iac-0
audiences: []

View File

@@ -277,24 +277,6 @@ values:
source_md5hash: null source_md5hash: null
temporary_hold: null temporary_hold: null
timeouts: null timeouts: null
google_storage_bucket_object.workflows["org-setup"]:
bucket: ft0-prod-iac-core-0-iac-outputs
cache_control: null
content_disposition: null
content_encoding: null
content_language: null
customer_encryption: []
deletion_policy: null
detect_md5hash: different hash
event_based_hold: null
force_empty_content_type: null
metadata: null
name: workflows/org-setup.yaml
retention: []
source: null
source_md5hash: null
temporary_hold: null
timeouts: null
local_file.providers["0-org-setup"]: local_file.providers["0-org-setup"]:
content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\ content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\
\ License, Version 2.0 (the \"License\");\n * you may not use this file except\ \ License, Version 2.0 (the \"License\");\n * you may not use this file except\
@@ -440,13 +422,6 @@ values:
filename: /tmp/fast-config/tfvars/0-org-setup.auto.tfvars.json filename: /tmp/fast-config/tfvars/0-org-setup.auto.tfvars.json
sensitive_content: null sensitive_content: null
source: null source: null
local_file.workflows["org-setup"]:
content_base64: null
directory_permission: '0777'
file_permission: '0644'
filename: /tmp/fast-config/workflows/org-setup.yaml
sensitive_content: null
source: null
module.billing-accounts["default"].google_billing_account_iam_member.bindings["billing_admin_org_admins"]: module.billing-accounts["default"].google_billing_account_iam_member.bindings["billing_admin_org_admins"]:
billing_account_id: 012345-012345-012345 billing_account_id: 012345-012345-012345
condition: [] condition: []
@@ -2846,6 +2821,7 @@ counts:
google_project_service: 33 google_project_service: 33
google_project_service_identity: 9 google_project_service_identity: 9
google_service_account: 14 google_service_account: 14
google_service_account_iam_binding: 2
google_service_account_iam_member: 4 google_service_account_iam_member: 4
google_storage_bucket: 3 google_storage_bucket: 3
google_storage_bucket_iam_binding: 4 google_storage_bucket_iam_binding: 4
@@ -2858,6 +2834,6 @@ counts:
google_tags_tag_value: 5 google_tags_tag_value: 5
google_tags_tag_value_iam_binding: 4 google_tags_tag_value_iam_binding: 4
local_file: 9 local_file: 9
modules: 46 modules: 48
resources: 309 resources: 311
terraform_data: 2 terraform_data: 2