Working with OCI Tag Defaults In Terraform

James George
Oracle Developers
Published in
3 min readDec 15, 2022

Tagging of resources is a handy thing to do for your OCI deployments. Tag Defaults provide a way to automate resource tagging, but care should be taken when working with Terraform.

Tagging in general can assist with everything from cost management to locating associated resources for a deployment. There are a number of ways you can apply tags to resources in OCI manually and programmatically, but using automatic Tag Defaults with Compartments is a good way to apply a tagging strategy that aligns to a hierarchical structure without actually having to add the tags explicitly; any resource created in a given compartment will automatically have any Tag Defaults for that compartment and any parent compartment automatically applied (note: for Tag Defaults where no default value has been defined, you still have to explicitly supply the tag and value). You may already be using this feature and not realize it — Oracle provides the Oracle-Tags tag namespace that provides the CreatedBy and CreatedOn tags that are configured as Tag Defaults in the root compartment and are likely applied to all the resources you have already created.

Utilizing Tag Defaults works especially well when manually creating resources and can be easily adapted to Infrastructure as Code scenarios; i.e. only supplying tag and tag values that are not defaulted. Issues arise, however, with Terraform if your Terraform project will have a life beyond a single apply. The issue is that Terraform maintains a state file with the details of the resources it created, and this includes resource arguments, including tags. For an initial Terraform resource creation, things are fine — resources are created and Tag Defaults are applied. Terraform knows which resources it created and what the arguments were when it created those resources, but when a Terraform plan is subsequently run, Terraform identifies the defaulted tags as arguments that it did not supply and thus will likely want to remove them. In this case, if apply is run, the tags are removed. This is not a great outcome if you are defaulting cost tracking tags!

Fix It With Code

The Resource Specific Approach

One obvious solution is to not rely on Tag Defaults when you are working with Terraform and define all the required tags explicitly.

Programmatically setting all the required tags is more acceptable and can be codified into the coding and testing cycles to ensure they are created. Trouble is, this does not work well for the Oracle-Tags tags where they are typically set using Tag Variables; the variable does not equal the eventual value applied, and thus Terraform is not happy on subsequent runs and will reapply the tag using the Tag Variable which will certainly change CreatedOn and maybe change CreatedBy. A better approach is to allow OCI to set the Oracle-Tags automatically and then just ignore them in Terraform. The example code below is creating a Virtual Cloud Network but also indicates that Terraform should not worry about the CreatedBy and CreatedOn tags. With this bit in place any subsequent Terraform runs will not change those tags. This can be extended to include other automatically defaulted tags as necessary:

resource "oci_core_vcn" "vcn" {
display_name = var.vcn_name
compartment_id = var.compartment_id
cidr_blocks = var.vcn_cidr_blocks
dns_label = var.dns_label
is_ipv6enabled = false
defined_tags = var.defined_tags

lifecycle {
ignore_changes = [
defined_tags["Oracle-Tags.CreatedBy"],
defined_tags["Oracle-Tags.CreatedOn"],
defined_tags["My-Tags.AwesomeTag"]
]
}
}

Note that this approach does mean that any resource that might have Tag Defaults applied will need to have a lifecycle block that masks the Tag Defaults being applied.

The Provider Approach

Another, possibly superior, approach is to utilize a feature of the OCI Terraform provider, the ignore_defined_tags argument. This would then apply to any resource being managed by the provider instance. Your provider configuration might then look something like this:

provider "oci" {
tenancy_ocid = var.tenancy_ocid
region = var.region
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key = var.private_key

ignore_defined_tags = [
"Oracle-Tags.CreatedBy",
"Oracle-Tags.CreatedOn",
"My-Tags.AwesomeTag"
]
}

Either of these approaches, or even a combination of the two, can be extended to cover other Tag Defaults defined in your environment.

Obviously tags have enormous potential, so it’s important to know some of these potential pitfalls when working with tools like Terraform. Want to know more? Drop into our developer Slack to chat with others who are using the same tools!

--

--