diff --git a/modules/looker-core/README.md b/modules/looker-core/README.md
new file mode 100644
index 000000000..55c34dc37
--- /dev/null
+++ b/modules/looker-core/README.md
@@ -0,0 +1,195 @@
+# Looker Core module
+
+This module manages the creation of a [Looker Core instance](https://cloud.google.com/looker/docs/looker-core).
+
+This module accepts Oauth client ID and secret in the input variable `oauth_config` in case you have
+already [set up an oauth client and credentials](https://cloud.google.com/looker/docs/looker-core-create-oauth).
+If that is not the case it is possible to specify support_email in the same variable `oauth_config` for a default oauth
+client id and secret setup within the terraform script, be aware that **such an oauth client id is not suitable for
+authenticating end users**, and it is only used to provision the looker core instance.
+You'll still be forced to create a new oauth and update the looker core instance from the console (or gcloud) as there
+is no terraform support for these resources.
+
+
+> [!WARNING]
+> Please be aware that, at the time of this writing, deleting the looker core instance via terraform is not possible due
+> to https://github.com/hashicorp/terraform-provider-google/issues/19467. The work-around is to delete the instance from the
+> console (or gcloud with force option) and remove the corresponding resource from the terraform state.
+
+
+
+* [Looker Core module](#looker-core-module)
+ * [Examples](#examples)
+ * [Simple example](#simple-example)
+ * [Looker Core private instance with PSA](#looker-core-private-instance-with-psa)
+ * [Looker Core full example](#looker-core-full-example)
+ * [Variables](#variables)
+ * [Outputs](#outputs)
+
+
+
+## Examples
+
+### Simple example
+
+This example shows how to set up a public Looker Core instance.
+
+```hcl
+module "looker" {
+ source = "./fabric/modules/looker-core"
+ project_id = var.project_id
+ region = var.region
+ name = "looker"
+ network_config = {
+ public = true
+ }
+ oauth_config = {
+ support_email = "support@google.com"
+ }
+}
+# tftest modules=1 resources=3 inventory=simple.yaml
+```
+
+### Looker Core private instance with PSA
+
+```hcl
+module "project" {
+ source = "./fabric/modules/project"
+ billing_account = var.billing_account_id
+ parent = var.folder_id
+ name = "looker"
+ prefix = var.prefix
+ services = [
+ "servicenetworking.googleapis.com",
+ "looker.googleapis.com",
+ ]
+}
+
+module "vpc" {
+ source = "./fabric/modules/net-vpc"
+ project_id = module.project.project_id
+ name = "my-network"
+ psa_configs = [
+ {
+ ranges = { looker = "10.60.0.0/16" }
+ }
+ ]
+}
+
+module "looker" {
+ source = "./fabric/modules/looker-core"
+ project_id = module.project.project_id
+ region = var.region
+ name = "looker"
+ network_config = {
+ psa_config = {
+ network = module.vpc.id
+ }
+ }
+ oauth_config = {
+ support_email = "support@google.com"
+ }
+ platform_edition = "LOOKER_CORE_ENTERPRISE_ANNUAL"
+}
+# tftest modules=3 resources=16 inventory=psa.yaml
+```
+
+### Looker Core full example
+
+```hcl
+module "project" {
+ source = "./fabric/modules/project"
+ billing_account = var.billing_account_id
+ parent = var.folder_id
+ name = "looker"
+ prefix = var.prefix
+ services = [
+ "cloudkms.googleapis.com",
+ "iap.googleapis.com",
+ "looker.googleapis.com",
+ "servicenetworking.googleapis.com"
+ ]
+}
+
+module "vpc" {
+ source = "./fabric/modules/net-vpc"
+ project_id = module.project.project_id
+ name = "my-network"
+ psa_configs = [
+ {
+ ranges = { looker = "10.60.0.0/16" }
+ }
+ ]
+}
+
+module "kms" {
+ source = "./fabric/modules/kms"
+ project_id = module.project.project_id
+ keyring = {
+ location = var.region
+ name = "keyring"
+ }
+ keys = {
+ "key-regional" = {
+ }
+ }
+ iam = {
+ "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
+ module.project.service_agents.looker.iam_email
+ ]
+ }
+}
+
+module "looker" {
+ source = "./fabric/modules/looker-core"
+ project_id = module.project.project_id
+ region = var.region
+ name = "looker"
+ admin_settings = {
+ allowed_email_domains = ["google.com"]
+ }
+ encryption_config = {
+ kms_key_name = module.kms.keys.key-regional.id
+ }
+ network_config = {
+ psa_config = {
+ network = module.vpc.id
+ }
+ }
+ oauth_config = {
+ client_id = "xxxxxxxxx"
+ client_secret = "xxxxxxxx"
+ }
+ platform_edition = "LOOKER_CORE_ENTERPRISE_ANNUAL"
+}
+# tftest modules=4 resources=22 inventory=full.yaml
+```
+
+## Variables
+
+| name | description | type | required | default |
+|---|---|:---:|:---:|:---:|
+| [name](variables.tf#L85) | Name of the looker core instance. | string | ✓ | |
+| [network_config](variables.tf#L90) | Network configuration for cluster and instance. Only one between psa_config and psc_config can be used. | object({…}) | ✓ | |
+| [oauth_config](variables.tf#L108) | Looker Core Oauth config. Either client ID and secret (existing oauth client) or support email (temporary internal oauth client setup) must be specified. | object({…}) | ✓ | |
+| [project_id](variables.tf#L141) | The ID of the project where this instances will be created. | string | ✓ | |
+| [region](variables.tf#L146) | Region for the Looker core instance. | string | ✓ | |
+| [admin_settings](variables.tf#L17) | Looker Core admins settings. | object({…}) | | null |
+| [encryption_config](variables.tf#L26) | Set encryption configuration. KMS name format: 'projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]'. | object({…}) | | null |
+| [maintenance_config](variables.tf#L35) | Set maintenance window configuration and maintenance deny period (up to 90 days). Date format: 'yyyy-mm-dd'. | object({…}) | | {} |
+| [platform_edition](variables.tf#L121) | Platform editions for a Looker instance. Each edition maps to a set of instance features, like its size. | string | | "LOOKER_CORE_TRIAL" |
+| [prefix](variables.tf#L131) | Optional prefix used to generate instance names. | string | | null |
+
+## Outputs
+
+| name | description | sensitive |
+|---|---|:---:|
+| [egress_public_ip](outputs.tf#L17) | Public IP address of Looker instance for egress. | |
+| [id](outputs.tf#L22) | Fully qualified primary instance id. | |
+| [ingress_private_ip](outputs.tf#L27) | Private IP address of Looker instance for ingress. | |
+| [ingress_public_ip](outputs.tf#L32) | Public IP address of Looker instance for ingress. | |
+| [instance](outputs.tf#L37) | Looker Core instance resource. | ✓ |
+| [instance_name](outputs.tf#L43) | Name of the looker instance. | |
+| [looker_uri](outputs.tf#L48) | Looker core URI. | |
+| [looker_version](outputs.tf#L53) | Looker core version. | |
+
diff --git a/modules/looker-core/main.tf b/modules/looker-core/main.tf
new file mode 100644
index 000000000..389faf4fc
--- /dev/null
+++ b/modules/looker-core/main.tf
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2024 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 {
+ bootstrap_oauth_client = var.oauth_config.client_secret == null || var.oauth_config.client_id == null
+ looker_instance_name = "${local.prefix}${var.name}"
+ oauth_client_id = local.bootstrap_oauth_client ? google_iap_client.looker_client[0].client_id : var.oauth_config.client_id
+ oauth_client_secret = local.bootstrap_oauth_client ? google_iap_client.looker_client[0].secret : var.oauth_config.client_secret
+ prefix = var.prefix == null ? "" : "${var.prefix}-"
+}
+
+resource "google_looker_instance" "looker" {
+ project = var.project_id
+ name = local.looker_instance_name
+ consumer_network = try(var.network_config.psa_config.network, null)
+ platform_edition = var.platform_edition
+ private_ip_enabled = try(var.network_config.psa_config.enable_private_ip, null)
+ public_ip_enabled = coalesce(var.network_config.public, false) || try(var.network_config.psa_config.enable_public_ip, false)
+ region = var.region
+ reserved_range = try(var.network_config.psa_config.allocated_ip_range, null)
+
+ oauth_config {
+ client_id = local.oauth_client_id
+ client_secret = local.oauth_client_secret
+ }
+
+ dynamic "admin_settings" {
+ for_each = var.admin_settings != null ? [""] : []
+ content {
+ allowed_email_domains = var.admin_settings.allowed_email_domains
+ }
+ }
+ dynamic "deny_maintenance_period" {
+ for_each = var.maintenance_config.deny_maintenance_period != null ? [1] : []
+ content {
+ start_date {
+ year = var.maintenance_config.deny_maintenance_period.start_date.year
+ month = var.maintenance_config.deny_maintenance_period.start_date.month
+ day = var.maintenance_config.deny_maintenance_period.start_date.day
+ }
+ end_date {
+ year = var.maintenance_config.deny_maintenance_period.start_date.year
+ month = var.maintenance_config.deny_maintenance_period.start_date.month
+ day = var.maintenance_config.deny_maintenance_period.start_date.day
+ }
+ time {
+ hours = var.maintenance_config.deny_maintenance_period.start_times.hours
+ minutes = var.maintenance_config.deny_maintenance_period.start_times.minutes
+ seconds = var.maintenance_config.deny_maintenance_period.start_times.seconds
+ nanos = var.maintenance_config.deny_maintenance_period.start_times.nanos
+ }
+ }
+ }
+ dynamic "encryption_config" {
+ for_each = var.encryption_config != null ? [""] : []
+ content {
+ kms_key_name = var.encryption_config.kms_key_name
+ }
+ }
+ dynamic "maintenance_window" {
+ for_each = var.maintenance_config.maintenance_window != null ? [""] : []
+ content {
+ day_of_week = var.maintenance_config.maintenance_window.day
+ start_time {
+ hours = var.maintenance_config.maintenance_window.start_times.hours
+ minutes = var.maintenance_config.maintenance_window.start_times.minutes
+ seconds = var.maintenance_config.maintenance_window.start_times.seconds
+ nanos = var.maintenance_config.maintenance_window.start_times.nanos
+ }
+ }
+ }
+ lifecycle {
+ ignore_changes = [
+ oauth_config # do not replace target oauth client updated on the console with default one
+ ]
+ }
+}
+
+
+# Only "Organization Internal" brands can be created programmatically via API. To convert it into an external brands please use the GCP Console.
+resource "google_iap_brand" "looker_brand" {
+ count = local.bootstrap_oauth_client ? 1 : 0
+ support_email = var.oauth_config.support_email
+ # application_title = "Looker Core Application"
+ application_title = "Cloud IAP protected Application"
+ project = var.project_id
+}
+
+# Only internal org clients can be created via declarative tools. External clients must be manually created via the GCP console.
+# This is a temporary IAP oauth client to be replaced after Looker Core is provisioned.
+resource "google_iap_client" "looker_client" {
+ count = local.bootstrap_oauth_client ? 1 : 0
+ display_name = "Looker Core default oauth client."
+ brand = google_iap_brand.looker_brand[0].name
+}
diff --git a/modules/looker-core/outputs.tf b/modules/looker-core/outputs.tf
new file mode 100644
index 000000000..9c2af964f
--- /dev/null
+++ b/modules/looker-core/outputs.tf
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2024 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.
+ */
+
+output "egress_public_ip" {
+ description = "Public IP address of Looker instance for egress."
+ value = google_looker_instance.looker.egress_public_ip
+}
+
+output "id" {
+ description = "Fully qualified primary instance id."
+ value = google_looker_instance.looker.id
+}
+
+output "ingress_private_ip" {
+ description = "Private IP address of Looker instance for ingress."
+ value = google_looker_instance.looker.ingress_private_ip
+}
+
+output "ingress_public_ip" {
+ description = "Public IP address of Looker instance for ingress."
+ value = google_looker_instance.looker.ingress_public_ip
+}
+
+output "instance" {
+ description = "Looker Core instance resource."
+ value = google_looker_instance.looker.id
+ sensitive = true
+}
+
+output "instance_name" {
+ description = "Name of the looker instance."
+ value = google_looker_instance.looker.name
+}
+
+output "looker_uri" {
+ description = "Looker core URI."
+ value = google_looker_instance.looker.looker_uri
+}
+
+output "looker_version" {
+ description = "Looker core version."
+ value = google_looker_instance.looker.looker_version
+}
diff --git a/modules/looker-core/variables.tf b/modules/looker-core/variables.tf
new file mode 100644
index 000000000..ab54d1f0a
--- /dev/null
+++ b/modules/looker-core/variables.tf
@@ -0,0 +1,149 @@
+/**
+ * Copyright 2024 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.
+ */
+
+variable "admin_settings" {
+ description = "Looker Core admins settings."
+ type = object({
+ allowed_email_domains = list(string)
+ })
+ default = null
+ nullable = true
+}
+
+variable "encryption_config" {
+ description = "Set encryption configuration. KMS name format: 'projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]'."
+ type = object({
+ kms_key_name = string
+ })
+ default = null
+ nullable = true
+}
+
+variable "maintenance_config" {
+ description = "Set maintenance window configuration and maintenance deny period (up to 90 days). Date format: 'yyyy-mm-dd'."
+ type = object({
+ maintenance_window = optional(object({
+ day = optional(string, "SUNDAY")
+ start_time = optional(object({
+ hours = optional(number, 23)
+ minutes = optional(number, 0)
+ seconds = optional(number, 0)
+ nanos = optional(number, 0)
+ }), {})
+ }), null)
+ deny_maintenance_period = optional(object({
+ start_date = object({
+ year = number
+ month = number
+ day = number
+ })
+ end_date = object({
+ year = number
+ month = number
+ day = number
+ })
+ start_time = optional(object({
+ hours = optional(number, 23)
+ minutes = optional(number, 0)
+ seconds = optional(number, 0)
+ nanos = optional(number, 0)
+ }), {})
+ }), null)
+ })
+ default = {}
+ validation {
+ condition = (
+ try(var.maintenance_config.maintenance_window, null) == null ? true : (
+ var.maintenance_config.start_time.hours >= 0 &&
+ var.maintenance_config.start_time.hours <= 23 &&
+ var.maintenance_config.start_time.minutes == 0 &&
+ var.maintenance_config.start_time.seconds == 0 &&
+ var.maintenance_config.start_time.nanos == 0 &&
+ # Maintenance window day validation
+ contains([
+ "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"
+ ], var.maintenance_config.day)
+ )
+ )
+ error_message = "Maintenance window day must be between 1 and 7, maintenance window hour must be between 0 and 23 and maintenance window update_track must be 'stable' or 'canary'."
+ }
+}
+
+variable "name" {
+ description = "Name of the looker core instance."
+ type = string
+}
+
+variable "network_config" {
+ description = "Network configuration for cluster and instance. Only one between psa_config and psc_config can be used."
+ type = object({
+ psa_config = optional(object({
+ network = string
+ allocated_ip_range = optional(string)
+ enable_public_ip = optional(bool, false)
+ enable_private_ip = optional(bool, true)
+ }))
+ public = optional(bool, false)
+ })
+ nullable = false
+ validation {
+ condition = (coalesce(var.network_config.public, false)) == (var.network_config.psa_config == null)
+ error_message = "Please specify either psa_config or public to true."
+ }
+}
+
+variable "oauth_config" {
+ description = "Looker Core Oauth config. Either client ID and secret (existing oauth client) or support email (temporary internal oauth client setup) must be specified."
+ type = object({
+ client_id = optional(string, null)
+ client_secret = optional(string, null)
+ support_email = optional(string, null)
+ })
+ validation {
+ condition = (var.oauth_config.client_id == null && var.oauth_config.client_secret == null) != (var.oauth_config.support_email == null)
+ error_message = "Please specify either client_id and client_secret or support email."
+ }
+}
+
+variable "platform_edition" {
+ description = "Platform editions for a Looker instance. Each edition maps to a set of instance features, like its size."
+ type = string
+ default = "LOOKER_CORE_TRIAL"
+ validation {
+ condition = contains(["LOOKER_CORE_TRIAL", "LOOKER_CORE_STANDARD", "LOOKER_CORE_STANDARD_ANNUAL", "LOOKER_CORE_ENTERPRISE_ANNUAL", "LOOKER_CORE_EMBED_ANNUAL"], var.platform_edition)
+ error_message = "Platform Edition type must one of 'LOOKER_CORE_TRIAL', 'LOOKER_CORE_STANDARD', 'LOOKER_CORE_STANDARD_ANNUAL', 'LOOKER_CORE_ENTERPRISE_ANNUAL', 'LOOKER_CORE_EMBED_ANNUAL'."
+ }
+}
+
+variable "prefix" {
+ description = "Optional prefix used to generate instance names."
+ type = string
+ default = null
+ validation {
+ condition = var.prefix != ""
+ error_message = "Prefix cannot be empty, please use null instead."
+ }
+}
+
+variable "project_id" {
+ description = "The ID of the project where this instances will be created."
+ type = string
+}
+
+variable "region" {
+ description = "Region for the Looker core instance."
+ type = string
+}
diff --git a/modules/looker-core/versions.tf b/modules/looker-core/versions.tf
new file mode 100644
index 000000000..f569ce5af
--- /dev/null
+++ b/modules/looker-core/versions.tf
@@ -0,0 +1,29 @@
+# Copyright 2024 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
+#
+# https://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.
+
+# Fabric release: v35.0.0
+
+terraform {
+ required_version = ">= 1.7.4"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 6.1.0, < 7.0.0" # tftest
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 6.1.0, < 7.0.0" # tftest
+ }
+ }
+}
diff --git a/tests/examples_e2e/setup_module/main.tf b/tests/examples_e2e/setup_module/main.tf
index accf880fd..82b59b840 100644
--- a/tests/examples_e2e/setup_module/main.tf
+++ b/tests/examples_e2e/setup_module/main.tf
@@ -41,7 +41,9 @@ locals {
"dns.googleapis.com",
"eventarc.googleapis.com",
"iam.googleapis.com",
+ "iap.googleapis.com",
"logging.googleapis.com",
+ "looker.googleapis.com",
"monitoring.googleapis.com",
"networkconnectivity.googleapis.com",
"pubsub.googleapis.com",
diff --git a/tests/modules/looker_core/examples/full.yaml b/tests/modules/looker_core/examples/full.yaml
new file mode 100644
index 000000000..0a84020c7
--- /dev/null
+++ b/tests/modules/looker_core/examples/full.yaml
@@ -0,0 +1,204 @@
+# Copyright 2024 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.kms.google_kms_crypto_key.default["key-regional"]:
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ labels: null
+ name: key-regional
+ purpose: ENCRYPT_DECRYPT
+ rotation_period: null
+ skip_initial_version_creation: false
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.kms.google_kms_key_ring.default[0]:
+ location: europe-west8
+ name: keyring
+ project: test-looker
+ timeouts: null
+ module.kms.google_kms_key_ring_iam_binding.authoritative["roles/cloudkms.cryptoKeyEncrypterDecrypter"]:
+ condition: []
+ role: roles/cloudkms.cryptoKeyEncrypterDecrypter
+ module.looker.google_looker_instance.looker:
+ admin_settings:
+ - allowed_email_domains:
+ - google.com
+ custom_domain: []
+ deny_maintenance_period: []
+ encryption_config:
+ - {}
+ maintenance_window: []
+ name: looker
+ oauth_config:
+ - client_id: xxxxxxxxx
+ client_secret: xxxxxxxx
+ platform_edition: LOOKER_CORE_ENTERPRISE_ANNUAL
+ private_ip_enabled: true
+ project: test-looker
+ public_ip_enabled: false
+ region: europe-west8
+ reserved_range: null
+ timeouts: null
+ user_metadata: []
+ module.project.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-looker
+ org_id: null
+ project_id: test-looker
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.project.google_project_iam_member.service_agents["cloudkms"]:
+ condition: []
+ project: test-looker
+ role: roles/cloudkms.serviceAgent
+ module.project.google_project_iam_member.service_agents["looker"]:
+ condition: []
+ project: test-looker
+ role: roles/looker.serviceAgent
+ module.project.google_project_iam_member.service_agents["service-networking"]:
+ condition: []
+ project: test-looker
+ role: roles/servicenetworking.serviceAgent
+ module.project.google_project_service.project_services["cloudkms.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: cloudkms.googleapis.com
+ timeouts: null
+ module.project.google_project_service.project_services["iap.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: iap.googleapis.com
+ timeouts: null
+ module.project.google_project_service.project_services["looker.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: looker.googleapis.com
+ timeouts: null
+ module.project.google_project_service.project_services["servicenetworking.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["cloudkms.googleapis.com"]:
+ project: test-looker
+ service: cloudkms.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["iap.googleapis.com"]:
+ project: test-looker
+ service: iap.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["looker.googleapis.com"]:
+ project: test-looker
+ service: looker.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["servicenetworking.googleapis.com"]:
+ project: test-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ module.vpc.google_compute_global_address.psa_ranges["servicenetworking-googleapis-com-looker"]:
+ address: 10.60.0.0
+ address_type: INTERNAL
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_version: null
+ labels: null
+ name: servicenetworking-googleapis-com-looker
+ prefix_length: 16
+ project: test-looker
+ purpose: VPC_PEERING
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpc.google_compute_network.network[0]:
+ auto_create_subnetworks: false
+ delete_default_routes_on_create: false
+ description: Terraform-managed.
+ enable_ula_internal_ipv6: null
+ name: my-network
+ network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
+ project: test-looker
+ routing_mode: GLOBAL
+ timeouts: null
+ module.vpc.google_compute_network_peering_routes_config.psa_routes["servicenetworking.googleapis.com"]:
+ export_custom_routes: false
+ import_custom_routes: false
+ network: my-network
+ project: test-looker
+ timeouts: null
+ module.vpc.google_compute_route.gateway["private-googleapis"]:
+ description: Terraform-managed.
+ dest_range: 199.36.153.8/30
+ name: my-network-private-googleapis
+ network: my-network
+ next_hop_gateway: default-internet-gateway
+ next_hop_ilb: null
+ next_hop_instance: null
+ next_hop_vpn_tunnel: null
+ priority: 1000
+ project: test-looker
+ tags: null
+ timeouts: null
+ module.vpc.google_compute_route.gateway["restricted-googleapis"]:
+ description: Terraform-managed.
+ dest_range: 199.36.153.4/30
+ name: my-network-restricted-googleapis
+ network: my-network
+ next_hop_gateway: default-internet-gateway
+ next_hop_ilb: null
+ next_hop_instance: null
+ next_hop_vpn_tunnel: null
+ priority: 1000
+ project: test-looker
+ tags: null
+ timeouts: null
+ module.vpc.google_service_networking_connection.psa_connection["servicenetworking.googleapis.com"]:
+ deletion_policy: null
+ reserved_peering_ranges:
+ - servicenetworking-googleapis-com-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ update_on_creation_fail: null
+
+counts:
+ google_compute_global_address: 1
+ google_compute_network: 1
+ google_compute_network_peering_routes_config: 1
+ google_compute_route: 2
+ google_kms_crypto_key: 1
+ google_kms_key_ring: 1
+ google_kms_key_ring_iam_binding: 1
+ google_looker_instance: 1
+ google_project: 1
+ google_project_iam_member: 3
+ google_project_service: 4
+ google_project_service_identity: 4
+ google_service_networking_connection: 1
+ modules: 4
+ resources: 22
+
+outputs: {}
diff --git a/tests/modules/looker_core/examples/psa.yaml b/tests/modules/looker_core/examples/psa.yaml
new file mode 100644
index 000000000..af56f18de
--- /dev/null
+++ b/tests/modules/looker_core/examples/psa.yaml
@@ -0,0 +1,164 @@
+# Copyright 2024 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.looker.google_iap_brand.looker_brand[0]:
+ application_title: Cloud IAP protected Application
+ project: test-looker
+ support_email: support@google.com
+ timeouts: null
+ module.looker.google_iap_client.looker_client[0]:
+ display_name: Looker Core default oauth client.
+ timeouts: null
+ module.looker.google_looker_instance.looker:
+ admin_settings: []
+ custom_domain: []
+ deny_maintenance_period: []
+ maintenance_window: []
+ name: looker
+ oauth_config:
+ - {}
+ platform_edition: LOOKER_CORE_ENTERPRISE_ANNUAL
+ private_ip_enabled: true
+ project: test-looker
+ public_ip_enabled: false
+ region: europe-west8
+ reserved_range: null
+ timeouts: null
+ user_metadata: []
+ module.project.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-looker
+ org_id: null
+ project_id: test-looker
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.project.google_project_iam_member.service_agents["looker"]:
+ condition: []
+ project: test-looker
+ role: roles/looker.serviceAgent
+ module.project.google_project_iam_member.service_agents["service-networking"]:
+ condition: []
+ project: test-looker
+ role: roles/servicenetworking.serviceAgent
+ module.project.google_project_service.project_services["looker.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: looker.googleapis.com
+ timeouts: null
+ module.project.google_project_service.project_services["servicenetworking.googleapis.com"]:
+ disable_dependent_services: false
+ disable_on_destroy: false
+ project: test-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["looker.googleapis.com"]:
+ project: test-looker
+ service: looker.googleapis.com
+ timeouts: null
+ module.project.google_project_service_identity.default["servicenetworking.googleapis.com"]:
+ project: test-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ module.vpc.google_compute_global_address.psa_ranges["servicenetworking-googleapis-com-looker"]:
+ address: 10.60.0.0
+ address_type: INTERNAL
+ description: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ ip_version: null
+ labels: null
+ name: servicenetworking-googleapis-com-looker
+ prefix_length: 16
+ project: test-looker
+ purpose: VPC_PEERING
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ module.vpc.google_compute_network.network[0]:
+ auto_create_subnetworks: false
+ delete_default_routes_on_create: false
+ description: Terraform-managed.
+ enable_ula_internal_ipv6: null
+ name: my-network
+ network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
+ project: test-looker
+ routing_mode: GLOBAL
+ timeouts: null
+ module.vpc.google_compute_network_peering_routes_config.psa_routes["servicenetworking.googleapis.com"]:
+ export_custom_routes: false
+ import_custom_routes: false
+ network: my-network
+ project: test-looker
+ timeouts: null
+ module.vpc.google_compute_route.gateway["private-googleapis"]:
+ description: Terraform-managed.
+ dest_range: 199.36.153.8/30
+ name: my-network-private-googleapis
+ network: my-network
+ next_hop_gateway: default-internet-gateway
+ next_hop_ilb: null
+ next_hop_instance: null
+ next_hop_vpn_tunnel: null
+ priority: 1000
+ project: test-looker
+ tags: null
+ timeouts: null
+ module.vpc.google_compute_route.gateway["restricted-googleapis"]:
+ description: Terraform-managed.
+ dest_range: 199.36.153.4/30
+ name: my-network-restricted-googleapis
+ network: my-network
+ next_hop_gateway: default-internet-gateway
+ next_hop_ilb: null
+ next_hop_instance: null
+ next_hop_vpn_tunnel: null
+ priority: 1000
+ project: test-looker
+ tags: null
+ timeouts: null
+ module.vpc.google_service_networking_connection.psa_connection["servicenetworking.googleapis.com"]:
+ deletion_policy: null
+ reserved_peering_ranges:
+ - servicenetworking-googleapis-com-looker
+ service: servicenetworking.googleapis.com
+ timeouts: null
+ update_on_creation_fail: null
+
+counts:
+ google_compute_global_address: 1
+ google_compute_network: 1
+ google_compute_network_peering_routes_config: 1
+ google_compute_route: 2
+ google_iap_brand: 1
+ google_iap_client: 1
+ google_looker_instance: 1
+ google_project: 1
+ google_project_iam_member: 2
+ google_project_service: 2
+ google_project_service_identity: 2
+ google_service_networking_connection: 1
+ modules: 3
+ resources: 16
+
+outputs: {}
+
diff --git a/tests/modules/looker_core/examples/simple.yaml b/tests/modules/looker_core/examples/simple.yaml
new file mode 100644
index 000000000..a14d02cef
--- /dev/null
+++ b/tests/modules/looker_core/examples/simple.yaml
@@ -0,0 +1,49 @@
+# Copyright 2024 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.looker.google_iap_brand.looker_brand[0]:
+ application_title: Cloud IAP protected Application
+ project: project-id
+ support_email: support@google.com
+ timeouts: null
+ module.looker.google_iap_client.looker_client[0]:
+ display_name: Looker Core default oauth client.
+ timeouts: null
+ module.looker.google_looker_instance.looker:
+ admin_settings: []
+ consumer_network: null
+ custom_domain: []
+ deny_maintenance_period: []
+ maintenance_window: []
+ name: looker
+ oauth_config:
+ - {}
+ platform_edition: LOOKER_CORE_TRIAL
+ private_ip_enabled: false
+ project: project-id
+ public_ip_enabled: true
+ region: europe-west8
+ reserved_range: null
+ timeouts: null
+ user_metadata: []
+
+counts:
+ google_iap_brand: 1
+ google_iap_client: 1
+ google_looker_instance: 1
+ modules: 1
+ resources: 3
+
+outputs: {}