Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default tags for all resources #2283

Closed
serialseb opened this issue Jun 9, 2015 · 16 comments
Closed

Default tags for all resources #2283

serialseb opened this issue Jun 9, 2015 · 16 comments

Comments

@serialseb
Copy link

This is a feature request, something Ive not managed to find any smart way to do. Happy to try and contribute a pull request for it if it's not deemed useful.

My client tends to want to tag every resource with some additional data like team ownership and a few other things. This makes our tf files very large, mostly due to the enormous amount of copy and paste in each of the resources of exactly the same stuff.

It would be great if we had default tags that could be applied to any resource supporting tagging, overridable.

I'd suggest extending the template provider to set defaults, something like

resource "template_tags" "default" {
  Owner = "[email protected]"
}

Would that go in the right direction? Or is there another way of achieving that?

@radeksimko
Copy link
Member

@serialseb 👍 I agree that such feature would be useful, it just won't be easy to do (ain't saying it's impossible).

Tagging in AWS itself is quite complicated on the API level already, see #1296

@jrnt30
Copy link
Contributor

jrnt30 commented Sep 21, 2015

@radeksimko In relation to this and #1296 would it be reasonable to customize the AWS provider to accept the additional "Default Tags" parameter to apply to all resources. The individual AWS resources would then need to consult the provider and merge in the default tags, if the resource itself were "taggable"

This would be somewhat similar to what CloudFormation achieves when deploying a stack when customizing the "tags" attribute.

Ex. with the tags attribute of hte cli @ http://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html

@paultyng
Copy link
Contributor

There is the global Tag Editor in the AWS Console, I don't believe its supported in any of the SDK's though, I'm not sure. But that may be a pathway to a consistent interface for tag application for all resources, to emulate the way it interacts with resources for tagging.

http://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/tagging-resources.html

@leepa
Copy link

leepa commented Aug 23, 2016

Although #5435 was closed I find a work around is to use something like:

variable "default_tags" {
  type = "map"
  default = {}
}
default_tags = {
  foo = "bar"
}
...
  tags = "${merge(var.default_tags, map("Name", "my resource"))}"
...

It's a bit messy but it allows me to get around most of my issue around default tagging. Default tags would by far more preferable however as it would make the syntax in the actual resources cleaner. This is especially try when the parser doesn't support multi-line interpolation (or doesn't seem to).

@stack72
Copy link
Contributor

stack72 commented Mar 29, 2017

Hi @serialseb

Thanks so much for the request!

Sorry we took so long to get back to you. While we'd love to see something like this, we don't currently have any plans to implement this ourselves. Until then, this issue is unlikely to see any movement and remain stale. We're trying to prune the stale issues (that aren't going to be addressed anytime soon) by closing them. Note that we only do this for enhancement requests and not bugs.

If you are still interested in this feature being part of Terraform, then we would gladly review a Pull Request.

Thanks

@stack72

@stack72 stack72 closed this as completed Mar 29, 2017
@awilkins
Copy link

@leepa thanks for your solution... it seems multi-line interpolation works now.

e.g.

resource "aws_internet_gateway" "management" {
  vpc_id = "${aws_vpc.management.id}"
  tags = "${merge(var.default_tags, map(
    "Name", "management-gateway",
    "flavour", "lemon"
  ))}"
}

It would be a far more natural syntax IMHO if multiple assignments to tags merged the maps together, but this is close.

e.g.

resource "aws_internet_gateway" "management" {
  vpc_id = "${aws_vpc.management.id}"
  tags = "${var.default_tags}"
  tags {
    Name = "management-gateway"
  }
}

@ngocketit
Copy link

Latest version of Terraform has locals that makes this easier, especially if you want to use interpolations.

@dwmkerr
Copy link

dwmkerr commented Mar 15, 2018

For anyone who is still struggling with the best way to do this, and waiting for the map interpolation to be supported, here's the way I'm doing it now. This is about as clean as I've been able to get it, and is specifically for dealing with the kubernetes.io/cluster/<clustername> challenge. Will also share on the related issues:

  1. Define the 'common tags':
locals {
  common_tags = "${map(
    "Project", "openshift",
    "KubernetesCluster", "${var.cluster_id}",
    "kubernetes.io/cluster/${var.cluster_name}", "${var.cluster_id}"
  )}"
}
  1. Apply the common tags, adding any specific ones for your resource.
resource "aws_instance" "master" {
  //  Use our common tags and add a specific name.
  tags = "${merge(
    local.common_tags,
    map(
      "Name", "OpenShift Master"
    )
  )}"
}

Reference:

  1. Common tags: https://github.com/dwmkerr/terraform-aws-openshift/blob/feature/openshift-3.7/modules/openshift/01-tags.tf
  2. Applying tags: https://github.com/dwmkerr/terraform-aws-openshift/blob/feature/openshift-3.7/modules/openshift/06-nodes.tf

@ghost
Copy link

ghost commented Aug 29, 2018

I am new to Terraform, ran across this thread, and was hoping to get some clarification.

My goal is to define what i would call global tags that can be used across all aws resources and then add any specific tags to any individual resource that requires it.

Can someone tell me if locals and common tags are specific to each module? Or can the locals be defined at a higher level and used across all modules? I reviewed the documentation here: https://www.terraform.io/docs/configuration/locals.html
But did not come up with the best practices for defining these common tags.

If there is a url that provides the best practices for using tags within Terraform, or more specifically defining global tags, please share.

Thank You,

@awilkins
Copy link

awilkins commented Sep 4, 2018

locals and variables are scoped to the module they're declared in / passed into.

If you want a single source of default tags, your best shot is to create a locals block with the default tags in it in a single file, and either softlink that to every folder it's used in, or declare it in your root level config and pass that map as a variable to any modules you're using.

There's an exception : tag definitions on autoscaling groups. I'm keenly anticipating version 0.12 because it will finally provide a way to make this easy (instead of the current situation where you have to maintain another copy of the tags as a list-of-maps rather than a map).

@ghost
Copy link

ghost commented Sep 5, 2018

awilkins, thank you for the response. I have a few more questions. see below

"Create a locals block within the default tags in a single file:
* softlink that to every folder it is used in. "

QUESTIONS: 
* Is this what you are referring to? (see below)
* Where would this file be saved?
* How would I softlink it in a folder I want to use it in?


		# Define the common tags for all resources
		locals {
		  common_tags = {
			tag1  = "tag1_value"
			tag2  = "tag2_value"
			tag3  = "tag3_value"
			tag4  = "tag4_value"
		  }
		}
"* declare it in my root level config and pass the map as a variable to individual modules."
QUESTIONS:
* What do you mean by root level config?  the main.tf file?
	If that is the case I tried this and kept getting errors running terraform init.  It was saying that locals was a bad argument.
* I also read that I could not pass things between modules unless it was via outputs.  Can you tell me if the method below looks correct?

MY ATTEMPT WAS TO DO SOMETHING VERY SIMILAR TO THE FOLLOWING BUT I RAN INTO AN ERROR STATING "TAGS WAS NOT A VALID ARGUMENT" WHEN RUNNING TERRAFORM INIT. I was trying this within a module used to create a vpc.

The module pointed to another module that had these variables defined in the variables.tf file without defaults. I did not create the structure in the upstream module so I am not entirely familiar with everything in it.

		# Define the common tags for all resources
		locals {
		  common_tags = {
			Component   = "awesome-app"
			Environment = "production"
		  }
		}
		
		# Create a resource that blends the common tags with instance-specific tags.
		resource "aws_instance" "server" {
		  ami           = "ami-123456"
		  instance_type = "t2.micro"

		  tags = "${merge(
			local.common_tags,
			map(
			  "Name", "awesome-app-server",
			  "Role", "server"
			)
		  )}"
		}

Sorry if some of this is common knowledge but I am new to terraform and git. I will do some additional research while I await your response.

Again Thank You for the assistance!

@ghost
Copy link

ghost commented Sep 7, 2018

the content below is located in main.tf and is taken from the terraform aws vpc module.
Can someone tell me why this is not creating more than 2 tags?

Terraform init and plan run w/o errors, but plan does not indicate any more than 2 tags. Please let me know if you have any ideas. NOTE: I added tag1 to the variables.tf file and still no luck.

Thank You,

Common Tags

locals {
common_tags = "${map(
tag1 = "tag1_value"
tag2 = "tag2_value"
tag3 = "tag3_value"
tag4 = "tag4_value"
)}"
}

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "${var.vpc_name}"
cidr = "${var.vpc_cidr}"
tag1 = "${var.tag1}"

public_subnets = "${var.vpc_public_subnets}"
private_subnets = "${var.vpc_private_subnets}"

enable_nat_gateway = true

#instance_tenancy = true
default_vpc_enable_dns_hostnames = true
default_vpc_enable_dns_support = true
enable_dns_hostnames = true
enable_dns_support = true
enable_dynamodb_endpoint = true
enable_s3_endpoint = true
enable_dhcp_options = true
dhcp_options_domain_name = "ec2.internal"

azs = "${var.vpc_azs}"

tags = "${merge(
local.common_tags,
map(
Terraform = "true"
Name = "${var.vpc_name}"
tag1 = "${var.tag1}"
)
)}"
}

@ghost
Copy link

ghost commented Sep 7, 2018

so it turns out the changes I attempted to make during testing may not have been seen properly within my config even though they were checked in and visible in my repo. We tested from a different source and things worked.

Thank you,

@chipfranzen
Copy link

Any new plans for adding tags to all resources? New year's resolution, perhaps?

@apparentlymart
Copy link
Contributor

Since the model for tags is not consistent across all providers, Terraform Core can't really provide such a feature, but individual providers could potentially offer such a thing if the tagging model is consistent enough across all resource types in the provider:

provider "example" {
  default_tags = {
    environment = "production"
  }
}

Providers are not developed in this repository any longer, so I'd suggest opening feature requests in the separate provider repositories to discuss how it might work for each provider in particular.

In the absence of such a feature in a provider, the approach of using a local value for a map of "common tags" is the current best solution in Terraform Core, and we're not planning to introduce any more generalized features for tags in particular since, as I noted above, the tagging model and conventions across different providers is not consistent.

@ghost
Copy link

ghost commented Mar 30, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Mar 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests