Update Tags on Existing Resources?

I’m looking to update the tags on an existing resource (an EBS volume, specifically) but am not seeing a way to do that.

Am I missing it somewhere?

May I presume the crickets on this one are telling me there isn’t a way to do this?

You can update tags by changing the TF config of the EBS volume. If the EBS volume isn’t managed by TF you’ll need to write a config and import the resource.

Would the following EBS volume be considered to be “managed” by TF, if it were created within an aws_instance, like so:

resource "aws_instance" "student_linux" {
  count = var.instance_count
  instance_type = var.instance_type

  source_dest_check = false
  subnet_id = aws_subnet.MAW_Students_Linux_Subnet.id

  ebs_block_device {
    delete_on_termination = true
    volume_type = var.instance_storage_type
    device_name = var.linux_ebs_attach_location
    volume_size = var.linux_ebs_size
  }

  volume_tags = {
    Name = "${count.index+1}_Linux_VM_EBS"
  }
}

If so, how would one update the associated volume_tag’s after the fact?

Tagging ebs volumes in an instance resource was added to TF 0.11. You just need to add a tags block inside of the ebs_block_device block.

  ebs_block_device {
    delete_on_termination = true
    volume_type = var.instance_storage_type
    device_name = var.linux_ebs_attach_location
    volume_size = var.linux_ebs_size
      tags = {
         name = "volume foo"
      }
  }

Right, that would be my preferred way to do this all.

However, doing it that way by creating a separate EBS volume resource in turn causes problems upon destroy because Terraform tries to detach it from the Instance before powering down - which hangs indefinitely and the Instance never powers down.

See my previous post here ('depends_on' appears to have no effect. What am I doing wrong?) where I was trying to do it that way and was informed I instead needed to declare the EBS volume inside the aws_instance declaration so that Terraform would know how to handle it upon Instance shutdown.

Hence, I find myself now needing to figure out how to add tags to the EBS block created in an aws_instance resource, but after the fact.

I hope that makes sense. I just can’t figure out how to do so.

Ideally there is some function that allows me to pass an EBS volume ID and can simply add/update existing Tags. I have yet to discover if this exists.

resource "aws_instance" "student_linux" {
  count = var.instance_count
  instance_type = var.instance_type

  source_dest_check = false
  subnet_id = aws_subnet.MAW_Students_Linux_Subnet.id

  ebs_block_device {
    delete_on_termination = true
    volume_type = var.instance_storage_type
    device_name = var.linux_ebs_attach_location
    volume_size = var.linux_ebs_size
     tags = {
       name = "volume foo"
     }
  }

  volume_tags = {
    Name = "${count.index+1}_Linux_VM_EBS"
  }
}

It would be great if it worked that way, but according to the docs the ebs_block_device doesn’t support tags.

$ terraform validate

Error: Unsupported argument

  on main.tf line 312, in resource "aws_instance" "student_linux":
 312:     tags = {

An argument named "tags" is not expected here.

I found the feature request to add the functionality and thought it was merged in. I just looked again and a related bug was merged. There have been multiple feature request since 2015 but no traction. Seems like they don’t care.

Good to hear I’m not just missing something completely obvious. It seems so incredibly basic, but judging by their GitHub issues page (where I first posted this and they sent me over here for more timely/relevant advice) they seem to have A LOT of issues on their plate. I suppose that’s the double-edge sword of TF’s massive increase in popularity and usage over the recent past.

Oh well… I believe I’ll just consider this “solved” in that I believe this “solution” that I discovered a little while back seems to be the only way to bridge gaps like this (and others) for the meantime.

1 Like

Hi all,

A Terraform provider is, in its essense, a wrapper around an API provided by an upstream vendor, and so often the constraints in functionality you see at the provider level are echoes of corresponding constraints in the underlying API.

In the case of EC2 and EBS as you’re all discussing here, the underlying EC2 API offers two different ways to create and attach EBS volumes:

  • You can directly create and EBS volume using CreateVolume and then attach it to an already-running EC2 instance using AttachVolume. In the Terraform provider, those two operations are represented as the aws_ebs_volume and aws_volume_attachment resource types respectively. CreateVolume accepts an individual set of tags for each call, giving full flexibility for tagging on a per-volume basis.

  • You can create a new instance using RunInstances and describe as part of the request one or more EBS volumes to create as a side effect. In the Terraform provider, this is presented via the aws_instance resource type.

    From the perspective of this API, the volumes are treated as being “part of” the instance, rather than separate entities, and tags are set broadly for types of attached object (like volumes), rather than for each child object individually, using TagSpecification objects. The TagSpecification objects are populated from the volume_tags argument you’ve already seen.

    Terraform does not directly interact with these implied child objects like volumes and network interfaces at all. Due to the API design, they are managed by EC2 internally itself, not by the Terraform provider. For example, deleting the root volume associated with an instance when that instance is deleted is done by of EC2 itself, not by the Terraform provider. The same is true for setting the tags on those objects.

I’ve gathered from reading responses by the AWS provider dev team in GitHub issues that they’d like for the provider to manage more directly the child objects associated with instances and have Terraform essentially bypass the built-in mechanisms in the EC2 API to do so, but that sort of thing has to be done with a lot of care to make sure it doesn’t cause conflict with built-in API behaviors.

I expect that the difficulty of robustly designing such a thing is the main reason that this hasn’t happened yet; historically, higher-level abstractions in the AWS provider (rather than exposing the underlying API functions as directly as possible) has had mixed results because the AWS provider team cannot predict how the underlying APIs will evolve in future. Also, where the Terraform provider does something different than other AWS tooling it can lead to surprises and integration challenges for people in environments that are not 100% Terraform-managed.

I hope that goes some way to explain why the provider is designed the way it is today. I understand that these limitations can be frustrating. The AWS provider team tends to be frustrated by them too, but has to make various design and work-prioritization tradeoffs in order to produce a system that works well for as many people as possible.

It looks like there’s a tracking issue #4017 for this enhancement request in the AWS provider repository. Adding :+1: reactions to the opening comment of that issue can help influence how the team prioritizes work.