diff --git a/modules/project/README.md b/modules/project/README.md
index e3bb4d186..0863d29b1 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -34,6 +34,7 @@ This module implements the creation and management of one GCP project including
- [Privileged Access Manager (PAM) Entitlements Factory](#privileged-access-manager-pam-entitlements-factory)
- [VPC Service Controls](#vpc-service-controls)
- [Default compute network tier](#default-compute-network-tier)
+- [BigQuery Reservations](#bigquery-reservations)
- [Project Related Outputs](#project-related-outputs)
- [Managing project related configuration without creating it](#managing-project-related-configuration-without-creating-it)
- [Observability](#observability)
@@ -1501,6 +1502,50 @@ module "project" {
# tftest modules=1 resources=4
```
+## BigQuery Reservations
+
+BigQuery reservations are primarily used to manage and allocate dedicated compute capacity for running queries, which helps provide predictable and consistent performance and costs. You can configure BigQuery reservations and assign projects, folders, or organizations to them by specifying the job type.
+
+```hcl
+module "project-bq-billing" {
+ source = "./fabric/modules/project"
+ billing_account = var.billing_account_id
+ name = "project-billing"
+ parent = var.folder_id
+ prefix = var.prefix
+ services = [
+ "container.googleapis.com",
+ "bigquery.googleapis.com",
+ "bigqueryreservation.googleapis.com",
+ "stackdriver.googleapis.com"
+ ]
+ bigquery_reservations = {
+ "ew8" = {
+ location = "europe-west8"
+ slot_capacity = 0
+ assignments = {
+ "QUERY" = ["projects/{$module.project-bq-data.project_id}"]
+ }
+ }
+ }
+}
+
+module "project-bq-data" {
+ source = "./fabric/modules/project"
+ billing_account = var.billing_account_id
+ name = "project-data"
+ parent = var.folder_id
+ prefix = var.prefix
+ services = [
+ "container.googleapis.com",
+ "bigquery.googleapis.com",
+ "bigqueryreservation.googleapis.com",
+ "stackdriver.googleapis.com"
+ ]
+}
+# tftest modules=2 resources=20 inventory=bigqueryreservation.yaml
+```
+
## Project Related Outputs
Most of this module's outputs depend on its resources, to allow Terraform to compute all dependencies required for the project to be correctly configured. This allows you to reference outputs like `project_id` in other modules or resources without having to worry about setting `depends_on` blocks manually.
@@ -1918,6 +1963,7 @@ alerts:
| name | description | resources |
|---|---|---|
| [alerts.tf](./alerts.tf) | None | google_monitoring_alert_policy |
+| [bigquery-reservation.tf](./bigquery-reservation.tf) | None | google_bigquery_reservation · google_bigquery_reservation_assignment |
| [cmek.tf](./cmek.tf) | Service Agent IAM Bindings for CMEK | google_kms_crypto_key_iam_member |
| [iam.tf](./iam.tf) | IAM bindings. | google_project_iam_binding · google_project_iam_custom_role · google_project_iam_member |
| [logging-metrics.tf](./logging-metrics.tf) | None | google_logging_metric |
@@ -1946,26 +1992,27 @@ alerts:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L133) | Project name and id suffix. | string | ✓ | |
+| [name](variables.tf#L170) | Project name and id suffix. | string | ✓ | |
| [alerts](variables-observability.tf#L17) | Monitoring alerts. | map(object({…})) | | {} |
| [auto_create_network](variables.tf#L17) | Whether to create the default network for the project. | bool | | false |
-| [billing_account](variables.tf#L23) | Billing account id. | string | | null |
-| [compute_metadata](variables.tf#L29) | Optional compute metadata key/values. Only usable if compute API has been enabled. | map(string) | | {} |
-| [contacts](variables.tf#L36) | List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. | map(list(string)) | | {} |
-| [context](variables.tf#L43) | Context-specific interpolations. | object({…}) | | {} |
-| [custom_roles](variables.tf#L62) | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} |
-| [default_network_tier](variables.tf#L69) | Default compute network tier for the project. | string | | null |
-| [default_service_account](variables.tf#L75) | Project default service account setting: can be one of `delete`, `deprivilege`, `disable`, or `keep`. | string | | "keep" |
-| [deletion_policy](variables.tf#L88) | Deletion policy setting for this project. | string | | "DELETE" |
-| [descriptive_name](variables.tf#L99) | Name of the project name. Used for project name instead of `name` variable. | string | | null |
-| [factories_config](variables.tf#L105) | Paths to data files and folders that enable factory functionality. | object({…}) | | {} |
+| [bigquery_reservations](variables.tf#L23) | BigQuery reservations and assignments. Assignment specified as {JOB_TYPE = ['projects/PROJECT_ID']}. | map(object({…})) | | {} |
+| [billing_account](variables.tf#L60) | Billing account id. | string | | null |
+| [compute_metadata](variables.tf#L66) | Optional compute metadata key/values. Only usable if compute API has been enabled. | map(string) | | {} |
+| [contacts](variables.tf#L73) | List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. | map(list(string)) | | {} |
+| [context](variables.tf#L80) | Context-specific interpolations. | object({…}) | | {} |
+| [custom_roles](variables.tf#L99) | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} |
+| [default_network_tier](variables.tf#L106) | Default compute network tier for the project. | string | | null |
+| [default_service_account](variables.tf#L112) | Project default service account setting: can be one of `delete`, `deprivilege`, `disable`, or `keep`. | string | | "keep" |
+| [deletion_policy](variables.tf#L125) | Deletion policy setting for this project. | string | | "DELETE" |
+| [descriptive_name](variables.tf#L136) | Name of the project name. Used for project name instead of `name` variable. | string | | null |
+| [factories_config](variables.tf#L142) | Paths to data files and folders that enable factory functionality. | object({…}) | | {} |
| [iam](variables-iam.tf#L17) | Authoritative IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_bindings](variables-iam.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_bindings_additive](variables-iam.tf#L39) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | map(list(string)) | | {} |
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | map(list(string)) | | {} |
-| [labels](variables.tf#L120) | Resource labels. | map(string) | | {} |
-| [lien_reason](variables.tf#L127) | If non-empty, creates a project lien with this description. | string | | null |
+| [labels](variables.tf#L157) | Resource labels. | map(string) | | {} |
+| [lien_reason](variables.tf#L164) | If non-empty, creates a project lien with this description. | string | | null |
| [log_scopes](variables-observability.tf#L117) | Log scopes under this project. | map(object({…})) | | {} |
| [logging_data_access](variables-observability.tf#L127) | Control activation of data access logs. The special 'allServices' key denotes configuration for all services. | map(object({…})) | | {} |
| [logging_exclusions](variables-observability.tf#L138) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string) | | {} |
@@ -1974,51 +2021,52 @@ alerts:
| [metric_scopes](variables-observability.tf#L216) | List of projects that will act as metric scopes for this project. | list(string) | | [] |
| [network_tags](variables-tags.tf#L17) | Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} |
| [notification_channels](variables-observability.tf#L223) | Monitoring notification channels. | map(object({…})) | | {} |
-| [org_policies](variables.tf#L138) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
+| [org_policies](variables.tf#L175) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
| [pam_entitlements](variables-pam.tf#L17) | Privileged Access Manager entitlements for this resource, keyed by entitlement ID. | map(object({…})) | | {} |
-| [parent](variables.tf#L166) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
-| [prefix](variables.tf#L180) | Optional prefix used to generate project id and name. | string | | null |
-| [project_reuse](variables.tf#L190) | Reuse existing project if not null. If name and number are not passed in, a data source is used. | object({…}) | | null |
+| [parent](variables.tf#L203) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
+| [prefix](variables.tf#L217) | Optional prefix used to generate project id and name. | string | | null |
+| [project_reuse](variables.tf#L227) | Reuse existing project if not null. If name and number are not passed in, a data source is used. | object({…}) | | null |
| [quotas](variables-quotas.tf#L17) | Service quota configuration. | map(object({…})) | | {} |
| [scc_sha_custom_modules](variables-scc.tf#L17) | SCC custom modules keyed by module name. | map(object({…})) | | {} |
-| [service_agents_config](variables.tf#L210) | Automatic service agent configuration options. | object({…}) | | {} |
-| [service_config](variables.tf#L220) | Configure service API activation. | object({…}) | | {…} |
-| [service_encryption_key_ids](variables.tf#L232) | Service Agents to be granted encryption/decryption permissions over Cloud KMS encryption keys. Format {SERVICE_AGENT => [KEY_ID]}. | map(list(string)) | | {} |
-| [services](variables.tf#L239) | Service APIs to enable. | list(string) | | [] |
-| [shared_vpc_host_config](variables.tf#L245) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
-| [shared_vpc_service_config](variables.tf#L255) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
-| [skip_delete](variables.tf#L292) | Deprecated. Use deletion_policy. | bool | | null |
+| [service_agents_config](variables.tf#L247) | Automatic service agent configuration options. | object({…}) | | {} |
+| [service_config](variables.tf#L257) | Configure service API activation. | object({…}) | | {…} |
+| [service_encryption_key_ids](variables.tf#L269) | Service Agents to be granted encryption/decryption permissions over Cloud KMS encryption keys. Format {SERVICE_AGENT => [KEY_ID]}. | map(list(string)) | | {} |
+| [services](variables.tf#L276) | Service APIs to enable. | list(string) | | [] |
+| [shared_vpc_host_config](variables.tf#L282) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
+| [shared_vpc_service_config](variables.tf#L292) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
+| [skip_delete](variables.tf#L329) | Deprecated. Use deletion_policy. | bool | | null |
| [tag_bindings](variables-tags.tf#L82) | Tag bindings for this project, in key => tag value id format. | map(string) | | null |
| [tags](variables-tags.tf#L89) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} |
| [tags_config](variables-tags.tf#L154) | Fine-grained control on tag resource and IAM creation. | object({…}) | | {} |
-| [universe](variables.tf#L304) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | object({…}) | | null |
-| [vpc_sc](variables.tf#L315) | VPC-SC configuration for the project, use when `ignore_changes` for resources is set in the VPC-SC module. | object({…}) | | null |
+| [universe](variables.tf#L341) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | object({…}) | | null |
+| [vpc_sc](variables.tf#L352) | VPC-SC configuration for the project, use when `ignore_changes` for resources is set in the VPC-SC module. | object({…}) | | null |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [alert_ids](outputs.tf#L17) | Monitoring alert IDs. | |
-| [custom_role_id](outputs.tf#L25) | Map of custom role IDs created in the project. | |
-| [custom_roles](outputs.tf#L30) | Map of custom roles resources created in the project. | |
-| [default_service_accounts](outputs.tf#L35) | Emails of the default service accounts for this project. | |
-| [id](outputs.tf#L43) | Project id. | |
-| [name](outputs.tf#L61) | Project name. | |
-| [network_tag_keys](outputs.tf#L73) | Tag key resources. | |
-| [network_tag_values](outputs.tf#L82) | Tag value resources. | |
-| [notification_channel_names](outputs.tf#L90) | Notification channel names. | |
-| [notification_channels](outputs.tf#L98) | Full notification channel objects. | |
-| [number](outputs.tf#L103) | Project number. | |
-| [organization_policies_ids](outputs.tf#L118) | Map of ORGANIZATION_POLICIES => ID in the organization. | |
-| [project_id](outputs.tf#L125) | Project id. | |
-| [quota_configs](outputs.tf#L143) | Quota configurations. | |
-| [quotas](outputs.tf#L154) | Quota resources. | |
-| [scc_custom_sha_modules_ids](outputs.tf#L159) | Map of SCC CUSTOM SHA MODULES => ID in the project. | |
-| [service_agents](outputs.tf#L164) | List of all (active) service agents for this project. | |
-| [services](outputs.tf#L173) | Service APIs to enable in the project. | |
-| [sink_writer_identities](outputs.tf#L182) | Writer identities created for each sink. | |
-| [tag_keys](outputs.tf#L189) | Tag key resources. | |
-| [tag_values](outputs.tf#L198) | Tag value resources. | |
+| [bigquery_reservations](outputs.tf#L25) | BigQuery reservations and assignments. | |
+| [custom_role_id](outputs.tf#L33) | Map of custom role IDs created in the project. | |
+| [custom_roles](outputs.tf#L38) | Map of custom roles resources created in the project. | |
+| [default_service_accounts](outputs.tf#L43) | Emails of the default service accounts for this project. | |
+| [id](outputs.tf#L51) | Project id. | |
+| [name](outputs.tf#L69) | Project name. | |
+| [network_tag_keys](outputs.tf#L81) | Tag key resources. | |
+| [network_tag_values](outputs.tf#L90) | Tag value resources. | |
+| [notification_channel_names](outputs.tf#L98) | Notification channel names. | |
+| [notification_channels](outputs.tf#L106) | Full notification channel objects. | |
+| [number](outputs.tf#L111) | Project number. | |
+| [organization_policies_ids](outputs.tf#L126) | Map of ORGANIZATION_POLICIES => ID in the organization. | |
+| [project_id](outputs.tf#L133) | Project id. | |
+| [quota_configs](outputs.tf#L151) | Quota configurations. | |
+| [quotas](outputs.tf#L162) | Quota resources. | |
+| [scc_custom_sha_modules_ids](outputs.tf#L167) | Map of SCC CUSTOM SHA MODULES => ID in the project. | |
+| [service_agents](outputs.tf#L172) | List of all (active) service agents for this project. | |
+| [services](outputs.tf#L181) | Service APIs to enable in the project. | |
+| [sink_writer_identities](outputs.tf#L190) | Writer identities created for each sink. | |
+| [tag_keys](outputs.tf#L197) | Tag key resources. | |
+| [tag_values](outputs.tf#L206) | Tag value resources. | |
## Fixtures
diff --git a/modules/project/bigquery-reservation.tf b/modules/project/bigquery-reservation.tf
new file mode 100644
index 000000000..7d0559f25
--- /dev/null
+++ b/modules/project/bigquery-reservation.tf
@@ -0,0 +1,66 @@
+/**
+ * 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 {
+ _assignments = flatten([
+ for reservation_name, reservation in var.bigquery_reservations : [
+ for job_type, assignees in reservation.assignments : [
+ for assignee in assignees : {
+ key = "${reservation_name}-${job_type}-${assignee}"
+ reservation_name = reservation_name
+ location = reservation.location
+ job_type = job_type
+ assignee = assignee
+ }
+ ]
+ ]
+ ])
+ assignments = { for a in local._assignments : a.key => a }
+}
+
+resource "google_bigquery_reservation" "default" {
+ for_each = var.bigquery_reservations
+
+ project = local.project.project_id
+ location = each.value.location
+ name = each.key
+ slot_capacity = each.value.slot_capacity
+ ignore_idle_slots = each.value.ignore_idle_slots
+ concurrency = each.value.concurrency
+ edition = each.value.edition
+ secondary_location = each.value.secondary_location
+
+ dynamic "autoscale" {
+ for_each = each.value.max_slots == null ? [] : [each.value.max_slots]
+ content {
+ max_slots = autoscale.value
+ }
+ }
+
+ depends_on = [
+ google_project_service.project_services
+ ]
+}
+
+resource "google_bigquery_reservation_assignment" "default" {
+ for_each = local.assignments
+
+ project = local.project.project_id
+ location = each.value.location
+ reservation = google_bigquery_reservation.default[each.value.reservation_name].id
+ assignee = each.value.assignee
+ job_type = each.value.job_type
+}
diff --git a/modules/project/main.tf b/modules/project/main.tf
index 3979a14d7..d78947cb1 100644
--- a/modules/project/main.tf
+++ b/modules/project/main.tf
@@ -19,6 +19,20 @@ locals {
_observability_factory_path = pathexpand(coalesce(
var.factories_config.observability, "-"
))
+ bigquery_reservations_assigments = {
+ for reservation_name, reservation in google_bigquery_reservation.default :
+ reservation_name => {
+ (reservation.location) = {
+ for job_type in distinct([
+ for a in values(google_bigquery_reservation_assignment.default) : a.job_type
+ if a.reservation == reservation.id
+ ]) : job_type => [
+ for a in values(google_bigquery_reservation_assignment.default) : a.assignee
+ if a.reservation == reservation.id && a.job_type == job_type
+ ]
+ }
+ }
+ }
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
diff --git a/modules/project/outputs.tf b/modules/project/outputs.tf
index dcc35c57f..9a3d42394 100644
--- a/modules/project/outputs.tf
+++ b/modules/project/outputs.tf
@@ -22,6 +22,14 @@ output "alert_ids" {
}
}
+output "bigquery_reservations" {
+ description = "BigQuery reservations and assignments."
+ value = {
+ reservations = google_bigquery_reservation.default
+ assignments = local.bigquery_reservations_assigments
+ }
+}
+
output "custom_role_id" {
description = "Map of custom role IDs created in the project."
value = local.custom_role_ids
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index 6b771c1c5..f0a0e76f8 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -20,6 +20,43 @@ variable "auto_create_network" {
default = false
}
+variable "bigquery_reservations" {
+ description = "BigQuery reservations and assignments. Assignment specified as {JOB_TYPE = ['projects/PROJECT_ID']}."
+ type = map(object({
+ location = string
+ slot_capacity = number
+ ignore_idle_slots = optional(bool, false)
+ concurrency = optional(number)
+ edition = optional(string, "STANDARD")
+ secondary_location = optional(string)
+ max_slots = optional(number)
+ scaling_mode = optional(string, "AUTOSCALE_ONLY")
+ assignments = optional(map(list(string)), {})
+ }))
+ validation {
+ condition = alltrue([
+ for name, reservation in var.bigquery_reservations :
+ # Check the keys of the 'assignments' map within each reservation object.
+ # If 'assignments' is omitted (defaults to {}), the inner 'alltrue' evaluates to true.
+ alltrue([
+ for key in keys(reservation.assignments) :
+ contains(["JOB_TYPE_UNSPECIFIED",
+ "PIPELINE",
+ "QUERY",
+ "ML_EXTERNAL",
+ "BACKGROUND",
+ "CONTINUOUS",
+ "BACKGROUND_CHANGE_DATA_CAPTURE",
+ "BACKGROUND_COLUMN_METADATA_INDEX",
+ "BACKGROUND_SEARCH_INDEX_REFRESH"], key)
+ ])
+ ])
+ error_message = "All keys in the nested 'assignments' map (within 'bigquery_reservations') must be one of the following allowed values: ML_EXTERNAL, QUERY, or BACKGROUND."
+ }
+ default = {}
+ nullable = false
+}
+
variable "billing_account" {
description = "Billing account id."
type = string
diff --git a/tests/modules/project/examples/bigqueryreservation.yaml b/tests/modules/project/examples/bigqueryreservation.yaml
new file mode 100644
index 000000000..bbe7e8d52
--- /dev/null
+++ b/tests/modules/project/examples/bigqueryreservation.yaml
@@ -0,0 +1,142 @@
+# 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.
+
+values:
+ module.project-bq-billing.data.google_bigquery_default_service_account.bq_sa[0]:
+ project: test-project-billing
+ module.project-bq-billing.google_bigquery_reservation.default["ew8"]:
+ autoscale: []
+ concurrency: 0
+ edition: STANDARD
+ ignore_idle_slots: false
+ location: europe-west8
+ name: ew8
+ project: test-project-billing
+ secondary_location: null
+ slot_capacity: 0
+ timeouts: null
+ module.project-bq-billing.google_project.project[0]:
+ auto_create_network: false
+ billing_account: 123456-123456-123456
+ deletion_policy: DELETE
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ folder_id: '1122334455'
+ labels: null
+ name: test-project-billing
+ org_id: null
+ project_id: test-project-billing
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.project-bq-billing.google_project_iam_member.service_agents["container-engine-robot"]:
+ condition: []
+ project: test-project-billing
+ role: roles/container.serviceAgent
+ module.project-bq-billing.google_project_iam_member.service_agents["gkenode"]:
+ condition: []
+ project: test-project-billing
+ role: roles/container.defaultNodeServiceAgent
+ module.project-bq-billing.google_project_service.project_services["bigquery.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-billing
+ service: bigquery.googleapis.com
+ timeouts: null
+ module.project-bq-billing.google_project_service.project_services["bigqueryreservation.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-billing
+ service: bigqueryreservation.googleapis.com
+ timeouts: null
+ module.project-bq-billing.google_project_service.project_services["container.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-billing
+ service: container.googleapis.com
+ timeouts: null
+ module.project-bq-billing.google_project_service.project_services["stackdriver.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-billing
+ service: stackdriver.googleapis.com
+ timeouts: null
+ module.project-bq-billing.google_project_service_identity.default["container.googleapis.com"]:
+ project: test-project-billing
+ service: container.googleapis.com
+ timeouts: null
+ module.project-bq-data.data.google_bigquery_default_service_account.bq_sa[0]:
+ project: test-project-data
+ module.project-bq-data.google_project.project[0]:
+ auto_create_network: false
+ billing_account: 123456-123456-123456
+ deletion_policy: DELETE
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ folder_id: '1122334455'
+ labels: null
+ name: test-project-data
+ org_id: null
+ project_id: test-project-data
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.project-bq-data.google_project_iam_member.service_agents["container-engine-robot"]:
+ condition: []
+ project: test-project-data
+ role: roles/container.serviceAgent
+ module.project-bq-data.google_project_iam_member.service_agents["gkenode"]:
+ condition: []
+ project: test-project-data
+ role: roles/container.defaultNodeServiceAgent
+ module.project-bq-data.google_project_service.project_services["bigquery.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-data
+ service: bigquery.googleapis.com
+ timeouts: null
+ module.project-bq-data.google_project_service.project_services["bigqueryreservation.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-data
+ service: bigqueryreservation.googleapis.com
+ timeouts: null
+ module.project-bq-data.google_project_service.project_services["container.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-data
+ service: container.googleapis.com
+ timeouts: null
+ module.project-bq-data.google_project_service.project_services["stackdriver.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-project-data
+ service: stackdriver.googleapis.com
+ timeouts: null
+ module.project-bq-data.google_project_service_identity.default["container.googleapis.com"]:
+ project: test-project-data
+ service: container.googleapis.com
+ timeouts: null
+
+counts:
+ google_bigquery_default_service_account: 2
+ google_bigquery_reservation: 1
+ google_project: 2
+ google_project_iam_member: 4
+ google_project_service: 8
+ google_project_service_identity: 2
+ modules: 2
+ resources: 20