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 major 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 depend on existing Data Catalog entries or entry groups and tag templates that define field schemas. The examples are intentionally small. Combine them with your own catalog resources and IAM policies.

Attach metadata to a catalog entry

Data governance teams use tags to classify catalog entries, enabling discovery and compliance tracking. Tags conform to a template that defines required fields and allowed value types.

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 references the entry receiving the tag. The template property points to the tag template that defines the schema. The fields array maps field IDs from the template to actual values; here, the required “source” field receives a string value.

Tag an entire entry group

When multiple entries share common metadata, tagging their parent entry group applies 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

Setting parent to the entry group ID attaches the tag to all entries within that group. This avoids creating duplicate tags for each entry when they share the same metadata.

Tag specific columns with multiple field types

Schemas with nested columns often require column-level tagging to mark sensitive data or document field-specific metadata.

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” or “outer_column.inner_column”). The fields array demonstrates all three field types: stringValue for text, doubleValue for numbers, and enumValue for predefined choices from the template. Multiple tags can target different columns in the same entry.

Beyond these examples

These snippets focus on specific tag features: entry and entry group tagging, column-level metadata attachment, and multiple field types (string, double, enum). 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 resources themselves.

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

  • Tag template creation and field definitions
  • IAM permissions for tag creation and viewing
  • Tag updates and lifecycle management
  • Bulk tagging operations

These omissions are intentional: the goal is to illustrate how tags are attached to catalog resources, 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 still supported?
No, gcp.datacatalog.Tag is deprecated and will be removed in a future major release. You should transition to Dataplex Catalog.
How do I migrate from Data Catalog tags to Dataplex Catalog?
Follow the transition guide at https://cloud.google.com/dataplex/docs/transition-to-dataplex-catalog for steps to migrate your users, workloads, and content.
Tag Configuration & Limits
How many fields can a tag have?
A tag must have at least 1 field and at most 500 fields.
What field types are supported in tags?
Tags support STRING (using stringValue), DOUBLE (using doubleValue), and ENUM (using enumValue) field types, as shown in the examples.
What happens when I attach a tag to an entry group instead of an entry?
The tag will be attached to all entries in that group.
Immutability & Constraints
Can I change the template after creating a tag?
No, the template field cannot be modified after creation. You’ll need to recreate the tag with a different template.
Can I move a tag to a different parent after creation?
No, the parent field is immutable. To attach a tag to a different entry or entry group, you must recreate the tag.
Column Targeting
How do I attach a tag to a specific column in an entry's schema?
Use the column property with the column name. For nested columns, separate names with . (e.g., outer_column.inner_column).
Can I tag multiple columns with the same tag?
No, each tag targets a single column (or no column for entry-level tags). Create separate tag resources to tag multiple columns.

Using a different cloud?

Explore analytics guides for other cloud providers: