diff --git a/modules/data-catalog-policy-tag/README.md b/modules/data-catalog-policy-tag/README.md
index a9906ed63..207ab0aef 100644
--- a/modules/data-catalog-policy-tag/README.md
+++ b/modules/data-catalog-policy-tag/README.md
@@ -81,17 +81,17 @@ module "cmn-dc" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [location](variables.tf#L29) | Data Catalog Taxonomy location. | string | ✓ | |
-| [name](variables.tf#L34) | Name of this taxonomy. | string | ✓ | |
-| [project_id](variables.tf#L49) | GCP project id. | string | ✓ | |
+| [location](variables.tf#L52) | Data Catalog Taxonomy location. | string | ✓ | |
+| [name](variables.tf#L58) | Name of this taxonomy. | string | ✓ | |
+| [project_id](variables.tf#L64) | GCP project id. | string | ✓ | |
| [activated_policy_types](variables.tf#L17) | A list of policy types that are activated for this taxonomy. | list(string) | | ["FINE_GRAINED_ACCESS_CONTROL"] |
-| [description](variables.tf#L23) | Description of this taxonomy. | string | | "Taxonomy - Terraform managed" |
+| [context](variables.tf#L32) | Context-specific interpolations. | object({…}) | | {} |
+| [description](variables.tf#L45) | Description of this taxonomy. | string | | "Taxonomy - Terraform managed" |
| [iam](variables-iam.tf#L23) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_bindings](variables-iam.tf#L29) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_bindings_additive](variables-iam.tf#L44) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_by_principals](variables-iam.tf#L17) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} |
-| [prefix](variables.tf#L39) | Optional prefix used to generate project id and name. | string | | null |
-| [tags](variables.tf#L54) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…})) | | {} |
+| [tags](variables.tf#L70) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…})) | | {} |
## Outputs
diff --git a/modules/data-catalog-policy-tag/iam.tf b/modules/data-catalog-policy-tag/iam.tf
index 4abd98a92..ef3fb914a 100644
--- a/modules/data-catalog-policy-tag/iam.tf
+++ b/modules/data-catalog-policy-tag/iam.tf
@@ -46,20 +46,28 @@ resource "google_data_catalog_taxonomy_iam_binding" "authoritative" {
provider = google-beta
for_each = local.iam
taxonomy = google_data_catalog_taxonomy.default.id
- 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)
+ ]
}
resource "google_data_catalog_taxonomy_iam_binding" "bindings" {
provider = google-beta
for_each = var.iam_bindings
taxonomy = google_data_catalog_taxonomy.default.id
- 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
}
@@ -70,12 +78,14 @@ resource "google_data_catalog_taxonomy_iam_member" "bindings" {
provider = google-beta
for_each = var.iam_bindings_additive
taxonomy = google_data_catalog_taxonomy.default.id
- 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
}
@@ -88,6 +98,9 @@ resource "google_data_catalog_policy_tag_iam_binding" "authoritative" {
for v in local.tags_iam : "${v.tag}.${v.role}" => v
}
policy_tag = google_data_catalog_policy_tag.default[each.value.tag].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)
+ ]
}
diff --git a/modules/data-catalog-policy-tag/main.tf b/modules/data-catalog-policy-tag/main.tf
index 0ccd9235f..4b2677ccf 100644
--- a/modules/data-catalog-policy-tag/main.tf
+++ b/modules/data-catalog-policy-tag/main.tf
@@ -17,24 +17,30 @@
# tfdoc:file:description Data Catalog Taxonomy definition
locals {
- name = (
- var.name != null ? var.name : "${local.prefix}taxonomy"
+ 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 = "$"
+ location = try(local.ctx.locations[var.location], var.location)
+ project_id = var.project_id == null ? null : lookup(
+ local.ctx.project_ids, var.project_id, var.project_id
)
- prefix = var.prefix == null ? "" : "${var.prefix}-"
}
resource "google_data_catalog_taxonomy" "default" {
provider = google-beta
- project = var.project_id
- region = var.location
- display_name = local.name
+ project = local.project_id
+ region = local.location
+ display_name = var.name
description = var.description
activated_policy_types = var.activated_policy_types
}
resource "google_data_catalog_policy_tag" "default" {
- for_each = var.tags
provider = google-beta
+ for_each = var.tags
taxonomy = google_data_catalog_taxonomy.default.id
display_name = each.key
description = coalesce(
diff --git a/modules/data-catalog-policy-tag/variables.tf b/modules/data-catalog-policy-tag/variables.tf
index c294b086e..51a16de8d 100644
--- a/modules/data-catalog-policy-tag/variables.tf
+++ b/modules/data-catalog-policy-tag/variables.tf
@@ -17,38 +17,54 @@
variable "activated_policy_types" {
description = "A list of policy types that are activated for this taxonomy."
type = list(string)
+ nullable = true
default = ["FINE_GRAINED_ACCESS_CONTROL"]
+ validation {
+ condition = alltrue([
+ for v in coalesce(var.activated_policy_types, []) : contains(
+ ["FINE_GRAINED_ACCESS_CONTROL", "POLICY_TYPE_UNSPECIFIED"], v
+ )
+ ])
+ error_message = "Invalid policy type activation value."
+ }
+}
+
+variable "context" {
+ description = "Context-specific interpolations."
+ type = object({
+ condition_vars = optional(map(map(string)), {})
+ custom_roles = optional(map(string), {})
+ iam_principals = optional(map(string), {})
+ locations = optional(map(string), {})
+ project_ids = optional(map(string), {})
+ })
+ default = {}
+ nullable = false
}
variable "description" {
description = "Description of this taxonomy."
type = string
+ nullable = true
default = "Taxonomy - Terraform managed"
}
variable "location" {
description = "Data Catalog Taxonomy location."
type = string
+ nullable = false
}
variable "name" {
description = "Name of this taxonomy."
type = string
-}
-
-variable "prefix" {
- description = "Optional prefix used to generate project id and name."
- type = string
- default = null
- validation {
- condition = var.prefix != ""
- error_message = "Prefix cannot be empty, please use null instead."
- }
+ nullable = false
}
variable "project_id" {
description = "GCP project id."
type = string
+ nullable = false
}
variable "tags" {
diff --git a/modules/dataplex-aspect-types/README.md b/modules/dataplex-aspect-types/README.md
index 9977282d2..0dc341694 100644
--- a/modules/dataplex-aspect-types/README.md
+++ b/modules/dataplex-aspect-types/README.md
@@ -75,13 +75,13 @@ IAM attributes can leverage substitutions for principals, which need to be defin
module "aspect-types" {
source = "./fabric/modules/dataplex-aspect-types"
project_id = "test-project"
+ context = {
+ iam_principals = {
+ test-sa = "serviceAccount:sa-0@test-project.iam.gserviceaccount.com"
+ }
+ }
factories_config = {
aspect_types = "data/aspect-types"
- context = {
- iam_principals = {
- test-sa = "serviceAccount:sa-0@test-project.iam.gserviceaccount.com"
- }
- }
}
}
# tftest modules=1 resources=4 files=aspect-0,aspect-1
@@ -125,7 +125,7 @@ display_name: "Test template 1."
iam_bindings_additive:
user:
role: roles/dataplex.aspectTypeUser
- member: test-sa
+ member: $iam_principals:test-sa
metadata_template: |
{
"name": "tf-test-template-1",
@@ -158,10 +158,11 @@ metadata_template: |
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [project_id](variables.tf#L67) | Project id where resources will be created. | string | ✓ | |
+| [project_id](variables.tf#L77) | Project id where resources will be created. | string | ✓ | |
| [aspect_types](variables.tf#L17) | Aspect templates. Merged with those defined via the factory. | map(object({…})) | | {} |
-| [factories_config](variables.tf#L48) | Paths to folders for the optional factories. | object({…}) | | {} |
-| [location](variables.tf#L60) | Location for aspect types. | string | | "global" |
+| [context](variables.tf#L48) | Context-specific interpolations. | object({…}) | | {} |
+| [factories_config](variables.tf#L61) | Paths to folders for the optional factories. | object({…}) | | {} |
+| [location](variables.tf#L70) | Location for aspect types. | string | | "global" |
## Outputs
diff --git a/modules/dataplex-aspect-types/iam.tf b/modules/dataplex-aspect-types/iam.tf
index 2cbfbcb77..32b805319 100644
--- a/modules/dataplex-aspect-types/iam.tf
+++ b/modules/dataplex-aspect-types/iam.tf
@@ -53,26 +53,28 @@ resource "google_dataplex_aspect_type_iam_binding" "authoritative" {
for binding in local.iam :
"${binding.aspect_type_id}.${binding.role}" => binding
}
- role = each.value.role
aspect_type_id = google_dataplex_aspect_type.default[each.value.aspect_type_id].id
+ role = lookup(local.ctx.custom_roles, each.value.role, each.value.role)
members = [
for v in each.value.members :
- lookup(var.factories_config.context.iam_principals, v, v)
+ lookup(local.ctx.iam_principals, v, v)
]
}
resource "google_dataplex_aspect_type_iam_binding" "bindings" {
for_each = local.iam_bindings
- role = each.value.role
aspect_type_id = google_dataplex_aspect_type.default[each.value.aspect_type_id].id
+ role = lookup(local.ctx.custom_roles, each.value.role, each.value.role)
members = [
for v in each.value.members :
- lookup(var.factories_config.context.iam_principals, v, v)
+ 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
}
@@ -82,14 +84,16 @@ resource "google_dataplex_aspect_type_iam_binding" "bindings" {
resource "google_dataplex_aspect_type_iam_member" "members" {
for_each = local.iam_bindings_additive
aspect_type_id = google_dataplex_aspect_type.default[each.value.aspect_type_id].id
- role = each.value.role
+ role = lookup(local.ctx.custom_roles, each.value.role, each.value.role)
member = lookup(
- var.factories_config.context.iam_principals, each.value.member, each.value.member
+ 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
}
diff --git a/modules/dataplex-aspect-types/main.tf b/modules/dataplex-aspect-types/main.tf
index 1b6df7404..5f2f57097 100644
--- a/modules/dataplex-aspect-types/main.tf
+++ b/modules/dataplex-aspect-types/main.tf
@@ -37,12 +37,22 @@ locals {
metadata_template = lookup(v, "metadata_template", null)
}
})
+ 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 = "$"
+ location = try(local.ctx.locations[var.location], var.location)
+ project_id = var.project_id == null ? null : lookup(
+ local.ctx.project_ids, var.project_id, var.project_id
+ )
}
resource "google_dataplex_aspect_type" "default" {
for_each = local.aspect_types
- project = var.project_id
- location = var.location
+ project = local.project_id
+ location = local.location
aspect_type_id = each.key
description = each.value.description
display_name = each.value.display_name
diff --git a/modules/dataplex-aspect-types/schemas/aspect-type.schema.json b/modules/dataplex-aspect-types/schemas/aspect-type.schema.json
index 5148fdd9e..f2fbf31c0 100644
--- a/modules/dataplex-aspect-types/schemas/aspect-type.schema.json
+++ b/modules/dataplex-aspect-types/schemas/aspect-type.schema.json
@@ -31,11 +31,11 @@
"type": "object",
"additionalProperties": false,
"patternProperties": {
- "^roles/": {
+ "^(?:roles/|\\$custom_roles:)": {
"type": "array",
"items": {
"type": "string",
- "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|[a-z])"
+ "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\\$iam_principals:[a-z0-9_-]+)"
}
}
}
@@ -52,12 +52,12 @@
"type": "array",
"items": {
"type": "string",
- "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|[a-z])"
+ "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)"
}
},
"role": {
"type": "string",
- "pattern": "^roles/"
+ "pattern": "^(?:roles/|\\$custom_roles:)"
},
"condition": {
"type": "object",
@@ -92,11 +92,11 @@
"properties": {
"member": {
"type": "string",
- "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|[a-z])"
+ "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)"
},
"role": {
"type": "string",
- "pattern": "^roles/"
+ "pattern": "^(?:roles/|\\$custom_roles:)"
},
"condition": {
"type": "object",
diff --git a/modules/dataplex-aspect-types/variables.tf b/modules/dataplex-aspect-types/variables.tf
index bc52caaaf..4397b8ea7 100644
--- a/modules/dataplex-aspect-types/variables.tf
+++ b/modules/dataplex-aspect-types/variables.tf
@@ -45,13 +45,23 @@ variable "aspect_types" {
default = {}
}
+variable "context" {
+ description = "Context-specific interpolations."
+ type = object({
+ condition_vars = optional(map(map(string)), {})
+ custom_roles = optional(map(string), {})
+ iam_principals = optional(map(string), {})
+ locations = optional(map(string), {})
+ project_ids = optional(map(string), {})
+ })
+ default = {}
+ nullable = false
+}
+
variable "factories_config" {
description = "Paths to folders for the optional factories."
type = object({
aspect_types = optional(string)
- context = optional(object({
- iam_principals = optional(map(string), {})
- }), {})
})
nullable = false
default = {}
diff --git a/tests/modules/data_catalog_policy_tag/context.tfvars b/tests/modules/data_catalog_policy_tag/context.tfvars
new file mode 100644
index 000000000..82e3f9349
--- /dev/null
+++ b/tests/modules/data_catalog_policy_tag/context.tfvars
@@ -0,0 +1,51 @@
+context = {
+ condition_vars = {
+ organization = {
+ id = 1234567890
+ }
+ }
+ custom_roles = {
+ myrole = "organizations/366118655033/roles/myRoleOne"
+ }
+ iam_principals = {
+ mygroup = "group:test-group@example.com"
+ 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 = {
+ test = "myproject"
+ }
+}
+project_id = "$project_ids:test"
+location = "$locations:ew8"
+name = "test"
+tags = {
+ low = {}
+ medium = {}
+ high = {
+ iam = {
+ "roles/datacatalog.categoryFineGrainedReader" = [
+ "$iam_principals:mysa"
+ ]
+ }
+ }
+}
+iam = {
+ "roles/datacatalog.categoryAdmin" = [
+ "$iam_principals:mygroup"
+ ]
+}
+iam_bindings_additive = {
+ am1-admin = {
+ member = "$iam_principals:myuser"
+ role = "$custom_roles:myrole"
+ condition = {
+ title = "Test"
+ expression = "resource.matchTag('$${organization.id}/environment', 'development')"
+ }
+ }
+}
diff --git a/tests/modules/data_catalog_policy_tag/context.yaml b/tests/modules/data_catalog_policy_tag/context.yaml
new file mode 100644
index 000000000..96b468f40
--- /dev/null
+++ b/tests/modules/data_catalog_policy_tag/context.yaml
@@ -0,0 +1,63 @@
+# 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:
+ google_data_catalog_policy_tag.default["high"]:
+ description: high - Terraform managed.
+ display_name: high
+ parent_policy_tag: null
+ timeouts: null
+ google_data_catalog_policy_tag.default["low"]:
+ description: low - Terraform managed.
+ display_name: low
+ parent_policy_tag: null
+ timeouts: null
+ google_data_catalog_policy_tag.default["medium"]:
+ description: medium - Terraform managed.
+ display_name: medium
+ parent_policy_tag: null
+ timeouts: null
+ google_data_catalog_policy_tag_iam_binding.authoritative["high.roles/datacatalog.categoryFineGrainedReader"]:
+ condition: []
+ members:
+ - serviceAccount:test@test-project.iam.gserviceaccount.com
+ role: roles/datacatalog.categoryFineGrainedReader
+ google_data_catalog_taxonomy.default:
+ activated_policy_types:
+ - FINE_GRAINED_ACCESS_CONTROL
+ description: Taxonomy - Terraform managed
+ display_name: test
+ project: myproject
+ region: europe-west8
+ timeouts: null
+ google_data_catalog_taxonomy_iam_binding.authoritative["roles/datacatalog.categoryAdmin"]:
+ condition: []
+ members:
+ - group:test-group@example.com
+ role: roles/datacatalog.categoryAdmin
+ google_data_catalog_taxonomy_iam_member.bindings["am1-admin"]:
+ condition:
+ - description: null
+ expression: resource.matchTag('1234567890/environment', 'development')
+ title: Test
+ member: user:test-user@example.com
+ role: organizations/366118655033/roles/myRoleOne
+counts:
+ google_data_catalog_policy_tag: 3
+ google_data_catalog_policy_tag_iam_binding: 1
+ google_data_catalog_taxonomy: 1
+ google_data_catalog_taxonomy_iam_binding: 1
+ google_data_catalog_taxonomy_iam_member: 1
+ modules: 0
+ resources: 7
diff --git a/tests/modules/data_catalog_policy_tag/tftest.yaml b/tests/modules/data_catalog_policy_tag/tftest.yaml
new file mode 100644
index 000000000..483e0f4da
--- /dev/null
+++ b/tests/modules/data_catalog_policy_tag/tftest.yaml
@@ -0,0 +1,17 @@
+# 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.
+
+module: modules/data-catalog-policy-tag
+tests:
+ context:
diff --git a/tests/modules/dataplex_aspect_types/context.tfvars b/tests/modules/dataplex_aspect_types/context.tfvars
new file mode 100644
index 000000000..59832970d
--- /dev/null
+++ b/tests/modules/dataplex_aspect_types/context.tfvars
@@ -0,0 +1,57 @@
+context = {
+ 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 = {
+ mygroup = "group:test-group@example.com"
+ 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 = {
+ test = "myproject"
+ }
+ tag_values = {
+ "test/one" = "tagValues/1234567890"
+ }
+}
+project_id = "$project_ids:test"
+location = "$locations:ew8"
+aspect_types = {
+ tf-test-template = {
+ display_name = "Test template."
+ iam = {
+ "roles/dataplex.aspectTypeOwner" = ["$iam_principals:mygroup"]
+ }
+ 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 = {
+ user = {
+ role = "roles/dataplex.aspectTypeUser"
+ member = "$iam_principals:mysa"
+ }
+ }
+ metadata_template = "{}"
+ }
+}
diff --git a/tests/modules/dataplex_aspect_types/context.yaml b/tests/modules/dataplex_aspect_types/context.yaml
new file mode 100644
index 000000000..3ba54bb52
--- /dev/null
+++ b/tests/modules/dataplex_aspect_types/context.yaml
@@ -0,0 +1,52 @@
+# 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:
+ google_dataplex_aspect_type.default["tf-test-template"]:
+ aspect_type_id: tf-test-template
+ description: null
+ display_name: Test template.
+ effective_labels:
+ goog-terraform-provisioned: 'true'
+ labels: null
+ location: europe-west8
+ metadata_template: '{}'
+ project: myproject
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
+ timeouts: null
+ google_dataplex_aspect_type_iam_binding.authoritative["tf-test-template.roles/dataplex.aspectTypeOwner"]:
+ condition: []
+ members:
+ - group:test-group@example.com
+ role: roles/dataplex.aspectTypeOwner
+ google_dataplex_aspect_type_iam_binding.bindings["myrole_two"]:
+ condition:
+ - description: null
+ expression: resource.matchTag('1234567890/environment', 'development')
+ title: Test
+ members:
+ - serviceAccount:test@test-project.iam.gserviceaccount.com
+ role: organizations/366118655033/roles/myRoleTwo
+ google_dataplex_aspect_type_iam_member.members["user"]:
+ condition: []
+ member: serviceAccount:test@test-project.iam.gserviceaccount.com
+ role: roles/dataplex.aspectTypeUser
+
+counts:
+ google_dataplex_aspect_type: 1
+ google_dataplex_aspect_type_iam_binding: 2
+ google_dataplex_aspect_type_iam_member: 1
+ modules: 0
+ resources: 4
diff --git a/tests/modules/dataplex_aspect_types/tftest.yaml b/tests/modules/dataplex_aspect_types/tftest.yaml
new file mode 100644
index 000000000..39f49922a
--- /dev/null
+++ b/tests/modules/dataplex_aspect_types/tftest.yaml
@@ -0,0 +1,17 @@
+# 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.
+
+module: modules/dataplex-aspect-types
+tests:
+ context: