Create GCP Data Catalog Tags

The gcp:datacatalog/tag:Tag resource, part of the Pulumi GCP provider, attaches custom metadata to Data Catalog entries or entry groups based on tag template schemas. This resource is deprecated and will be removed in a future release; for migration guidance, see the Dataplex Catalog transition documentation. This guide focuses on three capabilities: entry-level tagging, entry group tagging, and column-level metadata.

Tags reference existing entries, entry groups, and tag templates that define field schemas and validation rules. The examples are intentionally small. Combine them with your own catalog infrastructure and IAM policies.

Attach metadata to a catalog entry

Data governance teams use tags to classify and document individual catalog entries, enabling discovery and compliance tracking.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const entryGroup = new gcp.datacatalog.EntryGroup("entry_group", {entryGroupId: "my_entry_group"});
const entry = new gcp.datacatalog.Entry("entry", {
    entryGroup: entryGroup.id,
    entryId: "my_entry",
    userSpecifiedType: "my_custom_type",
    userSpecifiedSystem: "SomethingExternal",
});
const tagTemplate = new gcp.datacatalog.TagTemplate("tag_template", {
    tagTemplateId: "my_template",
    region: "us-central1",
    displayName: "Demo Tag Template",
    fields: [
        {
            fieldId: "source",
            displayName: "Source of data asset",
            type: {
                primitiveType: "STRING",
            },
            isRequired: true,
        },
        {
            fieldId: "num_rows",
            displayName: "Number of rows in the data asset",
            type: {
                primitiveType: "DOUBLE",
            },
        },
        {
            fieldId: "pii_type",
            displayName: "PII type",
            type: {
                enumType: {
                    allowedValues: [
                        {
                            displayName: "EMAIL",
                        },
                        {
                            displayName: "SOCIAL SECURITY NUMBER",
                        },
                        {
                            displayName: "NONE",
                        },
                    ],
                },
            },
        },
    ],
    forceDelete: false,
});
const basicTag = new gcp.datacatalog.Tag("basic_tag", {
    parent: entry.id,
    template: tagTemplate.id,
    fields: [{
        fieldName: "source",
        stringValue: "my-string",
    }],
});
import pulumi
import pulumi_gcp as gcp

entry_group = gcp.datacatalog.EntryGroup("entry_group", entry_group_id="my_entry_group")
entry = gcp.datacatalog.Entry("entry",
    entry_group=entry_group.id,
    entry_id="my_entry",
    user_specified_type="my_custom_type",
    user_specified_system="SomethingExternal")
tag_template = gcp.datacatalog.TagTemplate("tag_template",
    tag_template_id="my_template",
    region="us-central1",
    display_name="Demo Tag Template",
    fields=[
        {
            "field_id": "source",
            "display_name": "Source of data asset",
            "type": {
                "primitive_type": "STRING",
            },
            "is_required": True,
        },
        {
            "field_id": "num_rows",
            "display_name": "Number of rows in the data asset",
            "type": {
                "primitive_type": "DOUBLE",
            },
        },
        {
            "field_id": "pii_type",
            "display_name": "PII type",
            "type": {
                "enum_type": {
                    "allowed_values": [
                        {
                            "display_name": "EMAIL",
                        },
                        {
                            "display_name": "SOCIAL SECURITY NUMBER",
                        },
                        {
                            "display_name": "NONE",
                        },
                    ],
                },
            },
        },
    ],
    force_delete=False)
basic_tag = gcp.datacatalog.Tag("basic_tag",
    parent=entry.id,
    template=tag_template.id,
    fields=[{
        "field_name": "source",
        "string_value": "my-string",
    }])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/datacatalog"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		entryGroup, err := datacatalog.NewEntryGroup(ctx, "entry_group", &datacatalog.EntryGroupArgs{
			EntryGroupId: pulumi.String("my_entry_group"),
		})
		if err != nil {
			return err
		}
		entry, err := datacatalog.NewEntry(ctx, "entry", &datacatalog.EntryArgs{
			EntryGroup:          entryGroup.ID(),
			EntryId:             pulumi.String("my_entry"),
			UserSpecifiedType:   pulumi.String("my_custom_type"),
			UserSpecifiedSystem: pulumi.String("SomethingExternal"),
		})
		if err != nil {
			return err
		}
		tagTemplate, err := datacatalog.NewTagTemplate(ctx, "tag_template", &datacatalog.TagTemplateArgs{
			TagTemplateId: pulumi.String("my_template"),
			Region:        pulumi.String("us-central1"),
			DisplayName:   pulumi.String("Demo Tag Template"),
			Fields: datacatalog.TagTemplateFieldArray{
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("source"),
					DisplayName: pulumi.String("Source of data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("STRING"),
					},
					IsRequired: pulumi.Bool(true),
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("num_rows"),
					DisplayName: pulumi.String("Number of rows in the data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("DOUBLE"),
					},
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("pii_type"),
					DisplayName: pulumi.String("PII type"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						EnumType: &datacatalog.TagTemplateFieldTypeEnumTypeArgs{
							AllowedValues: datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArray{
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("EMAIL"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("SOCIAL SECURITY NUMBER"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("NONE"),
								},
							},
						},
					},
				},
			},
			ForceDelete: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewTag(ctx, "basic_tag", &datacatalog.TagArgs{
			Parent:   entry.ID(),
			Template: tagTemplate.ID(),
			Fields: datacatalog.TagFieldArray{
				&datacatalog.TagFieldArgs{
					FieldName:   pulumi.String("source"),
					StringValue: pulumi.String("my-string"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var entryGroup = new Gcp.DataCatalog.EntryGroup("entry_group", new()
    {
        EntryGroupId = "my_entry_group",
    });

    var entry = new Gcp.DataCatalog.Entry("entry", new()
    {
        EntryGroup = entryGroup.Id,
        EntryId = "my_entry",
        UserSpecifiedType = "my_custom_type",
        UserSpecifiedSystem = "SomethingExternal",
    });

    var tagTemplate = new Gcp.DataCatalog.TagTemplate("tag_template", new()
    {
        TagTemplateId = "my_template",
        Region = "us-central1",
        DisplayName = "Demo Tag Template",
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "source",
                DisplayName = "Source of data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "STRING",
                },
                IsRequired = true,
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "num_rows",
                DisplayName = "Number of rows in the data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "DOUBLE",
                },
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "pii_type",
                DisplayName = "PII type",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    EnumType = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeArgs
                    {
                        AllowedValues = new[]
                        {
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "EMAIL",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "SOCIAL SECURITY NUMBER",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "NONE",
                            },
                        },
                    },
                },
            },
        },
        ForceDelete = false,
    });

    var basicTag = new Gcp.DataCatalog.Tag("basic_tag", new()
    {
        Parent = entry.Id,
        Template = tagTemplate.Id,
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "source",
                StringValue = "my-string",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.datacatalog.EntryGroup;
import com.pulumi.gcp.datacatalog.EntryGroupArgs;
import com.pulumi.gcp.datacatalog.Entry;
import com.pulumi.gcp.datacatalog.EntryArgs;
import com.pulumi.gcp.datacatalog.TagTemplate;
import com.pulumi.gcp.datacatalog.TagTemplateArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeEnumTypeArgs;
import com.pulumi.gcp.datacatalog.Tag;
import com.pulumi.gcp.datacatalog.TagArgs;
import com.pulumi.gcp.datacatalog.inputs.TagFieldArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var entryGroup = new EntryGroup("entryGroup", EntryGroupArgs.builder()
            .entryGroupId("my_entry_group")
            .build());

        var entry = new Entry("entry", EntryArgs.builder()
            .entryGroup(entryGroup.id())
            .entryId("my_entry")
            .userSpecifiedType("my_custom_type")
            .userSpecifiedSystem("SomethingExternal")
            .build());

        var tagTemplate = new TagTemplate("tagTemplate", TagTemplateArgs.builder()
            .tagTemplateId("my_template")
            .region("us-central1")
            .displayName("Demo Tag Template")
            .fields(            
                TagTemplateFieldArgs.builder()
                    .fieldId("source")
                    .displayName("Source of data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("STRING")
                        .build())
                    .isRequired(true)
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("num_rows")
                    .displayName("Number of rows in the data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("DOUBLE")
                        .build())
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("pii_type")
                    .displayName("PII type")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .enumType(TagTemplateFieldTypeEnumTypeArgs.builder()
                            .allowedValues(                            
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("EMAIL")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("SOCIAL SECURITY NUMBER")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("NONE")
                                    .build())
                            .build())
                        .build())
                    .build())
            .forceDelete(false)
            .build());

        var basicTag = new Tag("basicTag", TagArgs.builder()
            .parent(entry.id())
            .template(tagTemplate.id())
            .fields(TagFieldArgs.builder()
                .fieldName("source")
                .stringValue("my-string")
                .build())
            .build());

    }
}
resources:
  entry:
    type: gcp:datacatalog:Entry
    properties:
      entryGroup: ${entryGroup.id}
      entryId: my_entry
      userSpecifiedType: my_custom_type
      userSpecifiedSystem: SomethingExternal
  entryGroup:
    type: gcp:datacatalog:EntryGroup
    name: entry_group
    properties:
      entryGroupId: my_entry_group
  tagTemplate:
    type: gcp:datacatalog:TagTemplate
    name: tag_template
    properties:
      tagTemplateId: my_template
      region: us-central1
      displayName: Demo Tag Template
      fields:
        - fieldId: source
          displayName: Source of data asset
          type:
            primitiveType: STRING
          isRequired: true
        - fieldId: num_rows
          displayName: Number of rows in the data asset
          type:
            primitiveType: DOUBLE
        - fieldId: pii_type
          displayName: PII type
          type:
            enumType:
              allowedValues:
                - displayName: EMAIL
                - displayName: SOCIAL SECURITY NUMBER
                - displayName: NONE
      forceDelete: 'false'
  basicTag:
    type: gcp:datacatalog:Tag
    name: basic_tag
    properties:
      parent: ${entry.id}
      template: ${tagTemplate.id}
      fields:
        - fieldName: source
          stringValue: my-string

The parent property targets the specific entry to tag. The template property references a tag template that defines which fields are required and their types. The fields array maps field IDs from the template to actual values; here, stringValue provides the required “source” field.

Tag an entire entry group

When multiple entries share common metadata, tagging the entry group propagates that metadata to all entries automatically.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const entryGroup = new gcp.datacatalog.EntryGroup("entry_group", {entryGroupId: "my_entry_group"});
const firstEntry = new gcp.datacatalog.Entry("first_entry", {
    entryGroup: entryGroup.id,
    entryId: "first_entry",
    userSpecifiedType: "my_custom_type",
    userSpecifiedSystem: "SomethingExternal",
});
const secondEntry = new gcp.datacatalog.Entry("second_entry", {
    entryGroup: entryGroup.id,
    entryId: "second_entry",
    userSpecifiedType: "another_custom_type",
    userSpecifiedSystem: "SomethingElseExternal",
});
const tagTemplate = new gcp.datacatalog.TagTemplate("tag_template", {
    tagTemplateId: "my_template",
    region: "us-central1",
    displayName: "Demo Tag Template",
    fields: [
        {
            fieldId: "source",
            displayName: "Source of data asset",
            type: {
                primitiveType: "STRING",
            },
            isRequired: true,
        },
        {
            fieldId: "num_rows",
            displayName: "Number of rows in the data asset",
            type: {
                primitiveType: "DOUBLE",
            },
        },
        {
            fieldId: "pii_type",
            displayName: "PII type",
            type: {
                enumType: {
                    allowedValues: [
                        {
                            displayName: "EMAIL",
                        },
                        {
                            displayName: "SOCIAL SECURITY NUMBER",
                        },
                        {
                            displayName: "NONE",
                        },
                    ],
                },
            },
        },
    ],
    forceDelete: false,
});
const entryGroupTag = new gcp.datacatalog.Tag("entry_group_tag", {
    parent: entryGroup.id,
    template: tagTemplate.id,
    fields: [{
        fieldName: "source",
        stringValue: "my-string",
    }],
});
import pulumi
import pulumi_gcp as gcp

entry_group = gcp.datacatalog.EntryGroup("entry_group", entry_group_id="my_entry_group")
first_entry = gcp.datacatalog.Entry("first_entry",
    entry_group=entry_group.id,
    entry_id="first_entry",
    user_specified_type="my_custom_type",
    user_specified_system="SomethingExternal")
second_entry = gcp.datacatalog.Entry("second_entry",
    entry_group=entry_group.id,
    entry_id="second_entry",
    user_specified_type="another_custom_type",
    user_specified_system="SomethingElseExternal")
tag_template = gcp.datacatalog.TagTemplate("tag_template",
    tag_template_id="my_template",
    region="us-central1",
    display_name="Demo Tag Template",
    fields=[
        {
            "field_id": "source",
            "display_name": "Source of data asset",
            "type": {
                "primitive_type": "STRING",
            },
            "is_required": True,
        },
        {
            "field_id": "num_rows",
            "display_name": "Number of rows in the data asset",
            "type": {
                "primitive_type": "DOUBLE",
            },
        },
        {
            "field_id": "pii_type",
            "display_name": "PII type",
            "type": {
                "enum_type": {
                    "allowed_values": [
                        {
                            "display_name": "EMAIL",
                        },
                        {
                            "display_name": "SOCIAL SECURITY NUMBER",
                        },
                        {
                            "display_name": "NONE",
                        },
                    ],
                },
            },
        },
    ],
    force_delete=False)
entry_group_tag = gcp.datacatalog.Tag("entry_group_tag",
    parent=entry_group.id,
    template=tag_template.id,
    fields=[{
        "field_name": "source",
        "string_value": "my-string",
    }])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/datacatalog"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		entryGroup, err := datacatalog.NewEntryGroup(ctx, "entry_group", &datacatalog.EntryGroupArgs{
			EntryGroupId: pulumi.String("my_entry_group"),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewEntry(ctx, "first_entry", &datacatalog.EntryArgs{
			EntryGroup:          entryGroup.ID(),
			EntryId:             pulumi.String("first_entry"),
			UserSpecifiedType:   pulumi.String("my_custom_type"),
			UserSpecifiedSystem: pulumi.String("SomethingExternal"),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewEntry(ctx, "second_entry", &datacatalog.EntryArgs{
			EntryGroup:          entryGroup.ID(),
			EntryId:             pulumi.String("second_entry"),
			UserSpecifiedType:   pulumi.String("another_custom_type"),
			UserSpecifiedSystem: pulumi.String("SomethingElseExternal"),
		})
		if err != nil {
			return err
		}
		tagTemplate, err := datacatalog.NewTagTemplate(ctx, "tag_template", &datacatalog.TagTemplateArgs{
			TagTemplateId: pulumi.String("my_template"),
			Region:        pulumi.String("us-central1"),
			DisplayName:   pulumi.String("Demo Tag Template"),
			Fields: datacatalog.TagTemplateFieldArray{
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("source"),
					DisplayName: pulumi.String("Source of data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("STRING"),
					},
					IsRequired: pulumi.Bool(true),
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("num_rows"),
					DisplayName: pulumi.String("Number of rows in the data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("DOUBLE"),
					},
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("pii_type"),
					DisplayName: pulumi.String("PII type"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						EnumType: &datacatalog.TagTemplateFieldTypeEnumTypeArgs{
							AllowedValues: datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArray{
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("EMAIL"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("SOCIAL SECURITY NUMBER"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("NONE"),
								},
							},
						},
					},
				},
			},
			ForceDelete: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewTag(ctx, "entry_group_tag", &datacatalog.TagArgs{
			Parent:   entryGroup.ID(),
			Template: tagTemplate.ID(),
			Fields: datacatalog.TagFieldArray{
				&datacatalog.TagFieldArgs{
					FieldName:   pulumi.String("source"),
					StringValue: pulumi.String("my-string"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var entryGroup = new Gcp.DataCatalog.EntryGroup("entry_group", new()
    {
        EntryGroupId = "my_entry_group",
    });

    var firstEntry = new Gcp.DataCatalog.Entry("first_entry", new()
    {
        EntryGroup = entryGroup.Id,
        EntryId = "first_entry",
        UserSpecifiedType = "my_custom_type",
        UserSpecifiedSystem = "SomethingExternal",
    });

    var secondEntry = new Gcp.DataCatalog.Entry("second_entry", new()
    {
        EntryGroup = entryGroup.Id,
        EntryId = "second_entry",
        UserSpecifiedType = "another_custom_type",
        UserSpecifiedSystem = "SomethingElseExternal",
    });

    var tagTemplate = new Gcp.DataCatalog.TagTemplate("tag_template", new()
    {
        TagTemplateId = "my_template",
        Region = "us-central1",
        DisplayName = "Demo Tag Template",
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "source",
                DisplayName = "Source of data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "STRING",
                },
                IsRequired = true,
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "num_rows",
                DisplayName = "Number of rows in the data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "DOUBLE",
                },
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "pii_type",
                DisplayName = "PII type",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    EnumType = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeArgs
                    {
                        AllowedValues = new[]
                        {
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "EMAIL",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "SOCIAL SECURITY NUMBER",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "NONE",
                            },
                        },
                    },
                },
            },
        },
        ForceDelete = false,
    });

    var entryGroupTag = new Gcp.DataCatalog.Tag("entry_group_tag", new()
    {
        Parent = entryGroup.Id,
        Template = tagTemplate.Id,
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "source",
                StringValue = "my-string",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.datacatalog.EntryGroup;
import com.pulumi.gcp.datacatalog.EntryGroupArgs;
import com.pulumi.gcp.datacatalog.Entry;
import com.pulumi.gcp.datacatalog.EntryArgs;
import com.pulumi.gcp.datacatalog.TagTemplate;
import com.pulumi.gcp.datacatalog.TagTemplateArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeEnumTypeArgs;
import com.pulumi.gcp.datacatalog.Tag;
import com.pulumi.gcp.datacatalog.TagArgs;
import com.pulumi.gcp.datacatalog.inputs.TagFieldArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var entryGroup = new EntryGroup("entryGroup", EntryGroupArgs.builder()
            .entryGroupId("my_entry_group")
            .build());

        var firstEntry = new Entry("firstEntry", EntryArgs.builder()
            .entryGroup(entryGroup.id())
            .entryId("first_entry")
            .userSpecifiedType("my_custom_type")
            .userSpecifiedSystem("SomethingExternal")
            .build());

        var secondEntry = new Entry("secondEntry", EntryArgs.builder()
            .entryGroup(entryGroup.id())
            .entryId("second_entry")
            .userSpecifiedType("another_custom_type")
            .userSpecifiedSystem("SomethingElseExternal")
            .build());

        var tagTemplate = new TagTemplate("tagTemplate", TagTemplateArgs.builder()
            .tagTemplateId("my_template")
            .region("us-central1")
            .displayName("Demo Tag Template")
            .fields(            
                TagTemplateFieldArgs.builder()
                    .fieldId("source")
                    .displayName("Source of data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("STRING")
                        .build())
                    .isRequired(true)
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("num_rows")
                    .displayName("Number of rows in the data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("DOUBLE")
                        .build())
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("pii_type")
                    .displayName("PII type")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .enumType(TagTemplateFieldTypeEnumTypeArgs.builder()
                            .allowedValues(                            
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("EMAIL")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("SOCIAL SECURITY NUMBER")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("NONE")
                                    .build())
                            .build())
                        .build())
                    .build())
            .forceDelete(false)
            .build());

        var entryGroupTag = new Tag("entryGroupTag", TagArgs.builder()
            .parent(entryGroup.id())
            .template(tagTemplate.id())
            .fields(TagFieldArgs.builder()
                .fieldName("source")
                .stringValue("my-string")
                .build())
            .build());

    }
}
resources:
  firstEntry:
    type: gcp:datacatalog:Entry
    name: first_entry
    properties:
      entryGroup: ${entryGroup.id}
      entryId: first_entry
      userSpecifiedType: my_custom_type
      userSpecifiedSystem: SomethingExternal
  secondEntry:
    type: gcp:datacatalog:Entry
    name: second_entry
    properties:
      entryGroup: ${entryGroup.id}
      entryId: second_entry
      userSpecifiedType: another_custom_type
      userSpecifiedSystem: SomethingElseExternal
  entryGroup:
    type: gcp:datacatalog:EntryGroup
    name: entry_group
    properties:
      entryGroupId: my_entry_group
  tagTemplate:
    type: gcp:datacatalog:TagTemplate
    name: tag_template
    properties:
      tagTemplateId: my_template
      region: us-central1
      displayName: Demo Tag Template
      fields:
        - fieldId: source
          displayName: Source of data asset
          type:
            primitiveType: STRING
          isRequired: true
        - fieldId: num_rows
          displayName: Number of rows in the data asset
          type:
            primitiveType: DOUBLE
        - fieldId: pii_type
          displayName: PII type
          type:
            enumType:
              allowedValues:
                - displayName: EMAIL
                - displayName: SOCIAL SECURITY NUMBER
                - displayName: NONE
      forceDelete: 'false'
  entryGroupTag:
    type: gcp:datacatalog:Tag
    name: entry_group_tag
    properties:
      parent: ${entryGroup.id}
      template: ${tagTemplate.id}
      fields:
        - fieldName: source
          stringValue: my-string

By setting parent to entryGroup.id instead of a specific entry, the tag applies to all entries within that group. This reduces duplication when entries share organizational context or data lineage.

Tag specific columns with multiple field types

Schemas with nested columns often require column-level tagging to mark sensitive fields or document lineage at a granular level.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const entryGroup = new gcp.datacatalog.EntryGroup("entry_group", {entryGroupId: "my_entry_group"});
const entry = new gcp.datacatalog.Entry("entry", {
    entryGroup: entryGroup.id,
    entryId: "my_entry",
    userSpecifiedType: "my_custom_type",
    userSpecifiedSystem: "SomethingExternal",
    schema: `{
  \\"columns\\": [
    {
      \\"column\\": \\"first_name\\",
      \\"description\\": \\"First name\\",
      \\"mode\\": \\"REQUIRED\\",
      \\"type\\": \\"STRING\\"
    },
    {
      \\"column\\": \\"last_name\\",
      \\"description\\": \\"Last name\\",
      \\"mode\\": \\"REQUIRED\\",
      \\"type\\": \\"STRING\\"
    },
    {
      \\"column\\": \\"address\\",
      \\"description\\": \\"Address\\",
      \\"mode\\": \\"REPEATED\\",
      \\"subcolumns\\": [
        {
          \\"column\\": \\"city\\",
          \\"description\\": \\"City\\",
          \\"mode\\": \\"NULLABLE\\",
          \\"type\\": \\"STRING\\"
        },
        {
          \\"column\\": \\"state\\",
          \\"description\\": \\"State\\",
          \\"mode\\": \\"NULLABLE\\",
          \\"type\\": \\"STRING\\"
        }
      ],
      \\"type\\": \\"RECORD\\"
    }
  ]
}
`,
});
const tagTemplate = new gcp.datacatalog.TagTemplate("tag_template", {
    tagTemplateId: "my_template",
    region: "us-central1",
    displayName: "Demo Tag Template",
    fields: [
        {
            fieldId: "source",
            displayName: "Source of data asset",
            type: {
                primitiveType: "STRING",
            },
            isRequired: true,
        },
        {
            fieldId: "num_rows",
            displayName: "Number of rows in the data asset",
            type: {
                primitiveType: "DOUBLE",
            },
        },
        {
            fieldId: "pii_type",
            displayName: "PII type",
            type: {
                enumType: {
                    allowedValues: [
                        {
                            displayName: "EMAIL",
                        },
                        {
                            displayName: "SOCIAL SECURITY NUMBER",
                        },
                        {
                            displayName: "NONE",
                        },
                    ],
                },
            },
        },
    ],
    forceDelete: false,
});
const basicTag = new gcp.datacatalog.Tag("basic_tag", {
    parent: entry.id,
    template: tagTemplate.id,
    fields: [
        {
            fieldName: "source",
            stringValue: "my-string",
        },
        {
            fieldName: "num_rows",
            doubleValue: 5,
        },
        {
            fieldName: "pii_type",
            enumValue: "EMAIL",
        },
    ],
    column: "address",
});
const second_tag = new gcp.datacatalog.Tag("second-tag", {
    parent: entry.id,
    template: tagTemplate.id,
    fields: [
        {
            fieldName: "source",
            stringValue: "my-string",
        },
        {
            fieldName: "pii_type",
            enumValue: "NONE",
        },
    ],
    column: "first_name",
});
import pulumi
import pulumi_gcp as gcp

entry_group = gcp.datacatalog.EntryGroup("entry_group", entry_group_id="my_entry_group")
entry = gcp.datacatalog.Entry("entry",
    entry_group=entry_group.id,
    entry_id="my_entry",
    user_specified_type="my_custom_type",
    user_specified_system="SomethingExternal",
    schema="""{
  \"columns\": [
    {
      \"column\": \"first_name\",
      \"description\": \"First name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"last_name\",
      \"description\": \"Last name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"address\",
      \"description\": \"Address\",
      \"mode\": \"REPEATED\",
      \"subcolumns\": [
        {
          \"column\": \"city\",
          \"description\": \"City\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        },
        {
          \"column\": \"state\",
          \"description\": \"State\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        }
      ],
      \"type\": \"RECORD\"
    }
  ]
}
""")
tag_template = gcp.datacatalog.TagTemplate("tag_template",
    tag_template_id="my_template",
    region="us-central1",
    display_name="Demo Tag Template",
    fields=[
        {
            "field_id": "source",
            "display_name": "Source of data asset",
            "type": {
                "primitive_type": "STRING",
            },
            "is_required": True,
        },
        {
            "field_id": "num_rows",
            "display_name": "Number of rows in the data asset",
            "type": {
                "primitive_type": "DOUBLE",
            },
        },
        {
            "field_id": "pii_type",
            "display_name": "PII type",
            "type": {
                "enum_type": {
                    "allowed_values": [
                        {
                            "display_name": "EMAIL",
                        },
                        {
                            "display_name": "SOCIAL SECURITY NUMBER",
                        },
                        {
                            "display_name": "NONE",
                        },
                    ],
                },
            },
        },
    ],
    force_delete=False)
basic_tag = gcp.datacatalog.Tag("basic_tag",
    parent=entry.id,
    template=tag_template.id,
    fields=[
        {
            "field_name": "source",
            "string_value": "my-string",
        },
        {
            "field_name": "num_rows",
            "double_value": 5,
        },
        {
            "field_name": "pii_type",
            "enum_value": "EMAIL",
        },
    ],
    column="address")
second_tag = gcp.datacatalog.Tag("second-tag",
    parent=entry.id,
    template=tag_template.id,
    fields=[
        {
            "field_name": "source",
            "string_value": "my-string",
        },
        {
            "field_name": "pii_type",
            "enum_value": "NONE",
        },
    ],
    column="first_name")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/datacatalog"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		entryGroup, err := datacatalog.NewEntryGroup(ctx, "entry_group", &datacatalog.EntryGroupArgs{
			EntryGroupId: pulumi.String("my_entry_group"),
		})
		if err != nil {
			return err
		}
		entry, err := datacatalog.NewEntry(ctx, "entry", &datacatalog.EntryArgs{
			EntryGroup:          entryGroup.ID(),
			EntryId:             pulumi.String("my_entry"),
			UserSpecifiedType:   pulumi.String("my_custom_type"),
			UserSpecifiedSystem: pulumi.String("SomethingExternal"),
			Schema: pulumi.String(`{
  \"columns\": [
    {
      \"column\": \"first_name\",
      \"description\": \"First name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"last_name\",
      \"description\": \"Last name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"address\",
      \"description\": \"Address\",
      \"mode\": \"REPEATED\",
      \"subcolumns\": [
        {
          \"column\": \"city\",
          \"description\": \"City\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        },
        {
          \"column\": \"state\",
          \"description\": \"State\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        }
      ],
      \"type\": \"RECORD\"
    }
  ]
}
`),
		})
		if err != nil {
			return err
		}
		tagTemplate, err := datacatalog.NewTagTemplate(ctx, "tag_template", &datacatalog.TagTemplateArgs{
			TagTemplateId: pulumi.String("my_template"),
			Region:        pulumi.String("us-central1"),
			DisplayName:   pulumi.String("Demo Tag Template"),
			Fields: datacatalog.TagTemplateFieldArray{
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("source"),
					DisplayName: pulumi.String("Source of data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("STRING"),
					},
					IsRequired: pulumi.Bool(true),
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("num_rows"),
					DisplayName: pulumi.String("Number of rows in the data asset"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						PrimitiveType: pulumi.String("DOUBLE"),
					},
				},
				&datacatalog.TagTemplateFieldArgs{
					FieldId:     pulumi.String("pii_type"),
					DisplayName: pulumi.String("PII type"),
					Type: &datacatalog.TagTemplateFieldTypeArgs{
						EnumType: &datacatalog.TagTemplateFieldTypeEnumTypeArgs{
							AllowedValues: datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArray{
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("EMAIL"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("SOCIAL SECURITY NUMBER"),
								},
								&datacatalog.TagTemplateFieldTypeEnumTypeAllowedValueArgs{
									DisplayName: pulumi.String("NONE"),
								},
							},
						},
					},
				},
			},
			ForceDelete: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewTag(ctx, "basic_tag", &datacatalog.TagArgs{
			Parent:   entry.ID(),
			Template: tagTemplate.ID(),
			Fields: datacatalog.TagFieldArray{
				&datacatalog.TagFieldArgs{
					FieldName:   pulumi.String("source"),
					StringValue: pulumi.String("my-string"),
				},
				&datacatalog.TagFieldArgs{
					FieldName:   pulumi.String("num_rows"),
					DoubleValue: pulumi.Float64(5),
				},
				&datacatalog.TagFieldArgs{
					FieldName: pulumi.String("pii_type"),
					EnumValue: pulumi.String("EMAIL"),
				},
			},
			Column: pulumi.String("address"),
		})
		if err != nil {
			return err
		}
		_, err = datacatalog.NewTag(ctx, "second-tag", &datacatalog.TagArgs{
			Parent:   entry.ID(),
			Template: tagTemplate.ID(),
			Fields: datacatalog.TagFieldArray{
				&datacatalog.TagFieldArgs{
					FieldName:   pulumi.String("source"),
					StringValue: pulumi.String("my-string"),
				},
				&datacatalog.TagFieldArgs{
					FieldName: pulumi.String("pii_type"),
					EnumValue: pulumi.String("NONE"),
				},
			},
			Column: pulumi.String("first_name"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var entryGroup = new Gcp.DataCatalog.EntryGroup("entry_group", new()
    {
        EntryGroupId = "my_entry_group",
    });

    var entry = new Gcp.DataCatalog.Entry("entry", new()
    {
        EntryGroup = entryGroup.Id,
        EntryId = "my_entry",
        UserSpecifiedType = "my_custom_type",
        UserSpecifiedSystem = "SomethingExternal",
        Schema = @"{
  \""columns\"": [
    {
      \""column\"": \""first_name\"",
      \""description\"": \""First name\"",
      \""mode\"": \""REQUIRED\"",
      \""type\"": \""STRING\""
    },
    {
      \""column\"": \""last_name\"",
      \""description\"": \""Last name\"",
      \""mode\"": \""REQUIRED\"",
      \""type\"": \""STRING\""
    },
    {
      \""column\"": \""address\"",
      \""description\"": \""Address\"",
      \""mode\"": \""REPEATED\"",
      \""subcolumns\"": [
        {
          \""column\"": \""city\"",
          \""description\"": \""City\"",
          \""mode\"": \""NULLABLE\"",
          \""type\"": \""STRING\""
        },
        {
          \""column\"": \""state\"",
          \""description\"": \""State\"",
          \""mode\"": \""NULLABLE\"",
          \""type\"": \""STRING\""
        }
      ],
      \""type\"": \""RECORD\""
    }
  ]
}
",
    });

    var tagTemplate = new Gcp.DataCatalog.TagTemplate("tag_template", new()
    {
        TagTemplateId = "my_template",
        Region = "us-central1",
        DisplayName = "Demo Tag Template",
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "source",
                DisplayName = "Source of data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "STRING",
                },
                IsRequired = true,
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "num_rows",
                DisplayName = "Number of rows in the data asset",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    PrimitiveType = "DOUBLE",
                },
            },
            new Gcp.DataCatalog.Inputs.TagTemplateFieldArgs
            {
                FieldId = "pii_type",
                DisplayName = "PII type",
                Type = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeArgs
                {
                    EnumType = new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeArgs
                    {
                        AllowedValues = new[]
                        {
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "EMAIL",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "SOCIAL SECURITY NUMBER",
                            },
                            new Gcp.DataCatalog.Inputs.TagTemplateFieldTypeEnumTypeAllowedValueArgs
                            {
                                DisplayName = "NONE",
                            },
                        },
                    },
                },
            },
        },
        ForceDelete = false,
    });

    var basicTag = new Gcp.DataCatalog.Tag("basic_tag", new()
    {
        Parent = entry.Id,
        Template = tagTemplate.Id,
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "source",
                StringValue = "my-string",
            },
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "num_rows",
                DoubleValue = 5,
            },
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "pii_type",
                EnumValue = "EMAIL",
            },
        },
        Column = "address",
    });

    var second_tag = new Gcp.DataCatalog.Tag("second-tag", new()
    {
        Parent = entry.Id,
        Template = tagTemplate.Id,
        Fields = new[]
        {
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "source",
                StringValue = "my-string",
            },
            new Gcp.DataCatalog.Inputs.TagFieldArgs
            {
                FieldName = "pii_type",
                EnumValue = "NONE",
            },
        },
        Column = "first_name",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.datacatalog.EntryGroup;
import com.pulumi.gcp.datacatalog.EntryGroupArgs;
import com.pulumi.gcp.datacatalog.Entry;
import com.pulumi.gcp.datacatalog.EntryArgs;
import com.pulumi.gcp.datacatalog.TagTemplate;
import com.pulumi.gcp.datacatalog.TagTemplateArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeArgs;
import com.pulumi.gcp.datacatalog.inputs.TagTemplateFieldTypeEnumTypeArgs;
import com.pulumi.gcp.datacatalog.Tag;
import com.pulumi.gcp.datacatalog.TagArgs;
import com.pulumi.gcp.datacatalog.inputs.TagFieldArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var entryGroup = new EntryGroup("entryGroup", EntryGroupArgs.builder()
            .entryGroupId("my_entry_group")
            .build());

        var entry = new Entry("entry", EntryArgs.builder()
            .entryGroup(entryGroup.id())
            .entryId("my_entry")
            .userSpecifiedType("my_custom_type")
            .userSpecifiedSystem("SomethingExternal")
            .schema("""
{
  \"columns\": [
    {
      \"column\": \"first_name\",
      \"description\": \"First name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"last_name\",
      \"description\": \"Last name\",
      \"mode\": \"REQUIRED\",
      \"type\": \"STRING\"
    },
    {
      \"column\": \"address\",
      \"description\": \"Address\",
      \"mode\": \"REPEATED\",
      \"subcolumns\": [
        {
          \"column\": \"city\",
          \"description\": \"City\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        },
        {
          \"column\": \"state\",
          \"description\": \"State\",
          \"mode\": \"NULLABLE\",
          \"type\": \"STRING\"
        }
      ],
      \"type\": \"RECORD\"
    }
  ]
}
            """)
            .build());

        var tagTemplate = new TagTemplate("tagTemplate", TagTemplateArgs.builder()
            .tagTemplateId("my_template")
            .region("us-central1")
            .displayName("Demo Tag Template")
            .fields(            
                TagTemplateFieldArgs.builder()
                    .fieldId("source")
                    .displayName("Source of data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("STRING")
                        .build())
                    .isRequired(true)
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("num_rows")
                    .displayName("Number of rows in the data asset")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .primitiveType("DOUBLE")
                        .build())
                    .build(),
                TagTemplateFieldArgs.builder()
                    .fieldId("pii_type")
                    .displayName("PII type")
                    .type(TagTemplateFieldTypeArgs.builder()
                        .enumType(TagTemplateFieldTypeEnumTypeArgs.builder()
                            .allowedValues(                            
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("EMAIL")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("SOCIAL SECURITY NUMBER")
                                    .build(),
                                TagTemplateFieldTypeEnumTypeAllowedValueArgs.builder()
                                    .displayName("NONE")
                                    .build())
                            .build())
                        .build())
                    .build())
            .forceDelete(false)
            .build());

        var basicTag = new Tag("basicTag", TagArgs.builder()
            .parent(entry.id())
            .template(tagTemplate.id())
            .fields(            
                TagFieldArgs.builder()
                    .fieldName("source")
                    .stringValue("my-string")
                    .build(),
                TagFieldArgs.builder()
                    .fieldName("num_rows")
                    .doubleValue(5.0)
                    .build(),
                TagFieldArgs.builder()
                    .fieldName("pii_type")
                    .enumValue("EMAIL")
                    .build())
            .column("address")
            .build());

        var second_tag = new Tag("second-tag", TagArgs.builder()
            .parent(entry.id())
            .template(tagTemplate.id())
            .fields(            
                TagFieldArgs.builder()
                    .fieldName("source")
                    .stringValue("my-string")
                    .build(),
                TagFieldArgs.builder()
                    .fieldName("pii_type")
                    .enumValue("NONE")
                    .build())
            .column("first_name")
            .build());

    }
}
resources:
  entry:
    type: gcp:datacatalog:Entry
    properties:
      entryGroup: ${entryGroup.id}
      entryId: my_entry
      userSpecifiedType: my_custom_type
      userSpecifiedSystem: SomethingExternal
      schema: |
        {
          \"columns\": [
            {
              \"column\": \"first_name\",
              \"description\": \"First name\",
              \"mode\": \"REQUIRED\",
              \"type\": \"STRING\"
            },
            {
              \"column\": \"last_name\",
              \"description\": \"Last name\",
              \"mode\": \"REQUIRED\",
              \"type\": \"STRING\"
            },
            {
              \"column\": \"address\",
              \"description\": \"Address\",
              \"mode\": \"REPEATED\",
              \"subcolumns\": [
                {
                  \"column\": \"city\",
                  \"description\": \"City\",
                  \"mode\": \"NULLABLE\",
                  \"type\": \"STRING\"
                },
                {
                  \"column\": \"state\",
                  \"description\": \"State\",
                  \"mode\": \"NULLABLE\",
                  \"type\": \"STRING\"
                }
              ],
              \"type\": \"RECORD\"
            }
          ]
        }        
  entryGroup:
    type: gcp:datacatalog:EntryGroup
    name: entry_group
    properties:
      entryGroupId: my_entry_group
  tagTemplate:
    type: gcp:datacatalog:TagTemplate
    name: tag_template
    properties:
      tagTemplateId: my_template
      region: us-central1
      displayName: Demo Tag Template
      fields:
        - fieldId: source
          displayName: Source of data asset
          type:
            primitiveType: STRING
          isRequired: true
        - fieldId: num_rows
          displayName: Number of rows in the data asset
          type:
            primitiveType: DOUBLE
        - fieldId: pii_type
          displayName: PII type
          type:
            enumType:
              allowedValues:
                - displayName: EMAIL
                - displayName: SOCIAL SECURITY NUMBER
                - displayName: NONE
      forceDelete: 'false'
  basicTag:
    type: gcp:datacatalog:Tag
    name: basic_tag
    properties:
      parent: ${entry.id}
      template: ${tagTemplate.id}
      fields:
        - fieldName: source
          stringValue: my-string
        - fieldName: num_rows
          doubleValue: 5
        - fieldName: pii_type
          enumValue: EMAIL
      column: address
  second-tag:
    type: gcp:datacatalog:Tag
    properties:
      parent: ${entry.id}
      template: ${tagTemplate.id}
      fields:
        - fieldName: source
          stringValue: my-string
        - fieldName: pii_type
          enumValue: NONE
      column: first_name

The column property targets a specific schema column using dot notation for nested fields (e.g., “address.city”). The fields array demonstrates multiple value types: stringValue for text, doubleValue for numeric data, and enumValue for predefined choices from the template. Multiple tags can target different columns within the same entry.

Beyond these examples

These snippets focus on specific tag-level features: entry and entry group tagging, column-level metadata attachment, and multiple field types. They’re intentionally minimal rather than full data governance solutions.

The examples rely on pre-existing infrastructure such as Data Catalog entries and entry groups, and tag templates with defined field schemas. They focus on attaching tags rather than provisioning the catalog structure.

To keep things focused, common tag patterns are omitted, including:

  • Tag template creation and field type definitions
  • IAM permissions for tag creation and viewing
  • Tag deletion and forceDelete behavior
  • Timestamp and boolean field types

These omissions are intentional: the goal is to illustrate how tag attachment is wired, not provide drop-in governance modules. See the Data Catalog Tag resource reference for all available configuration options.

Let's create GCP Data Catalog Tags

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Deprecation & Migration
Is the Data Catalog Tag resource deprecated?
Yes, gcp.datacatalog.Tag is deprecated and will be removed in a future major release. You should transition to Dataplex Catalog using the migration guide at https://cloud.google.com/dataplex/docs/transition-to-dataplex-catalog.
Immutability & Limitations
What properties can't I change after creating a tag?
Both template and parent are immutable after creation. Choose the correct tag template and parent (entry or entry group) before creating the tag.
How many fields can a tag have?
A tag must have at least 1 field and can have at most 500 fields.
Tag Configuration & Scope
What's the difference between attaching a tag to an entry vs an entry group?
When you attach a tag to an entry, it applies only to that entry. When you attach it to an entry group (by setting parent to the entry group ID), the tag automatically applies to all entries in that group.
How do I attach a tag to a specific column in my data?
Use the column property with the column name. For nested columns, use dot notation like outer_column.inner_column.
What field types are supported in tags?
Tags support three field types as defined by your tag template: STRING (use stringValue), DOUBLE (use doubleValue), and ENUM (use enumValue).
Do I need to specify all fields from my tag template?
No, you only need to provide values for required fields (marked with isRequired: true in the template). Optional fields can be omitted.
What permissions do I need to create or view tags?
See the Data Catalog IAM documentation at https://cloud.google.com/data-catalog/docs/concepts/iam for information on required permissions.

Using a different cloud?

Explore analytics guides for other cloud providers: