3
votes

I'm using Terraform to deploy some dev and prod VMs on our VMware vCenter infrastructure and use vsphere tags to define responsibilities of VMs. I therefore added the following to the (sub)module:

  resource "vsphere_tag" "tag" {
    name        = "SYS-Team"
    category_id = "Responsibility"
    description = "Systems group"
  }

  ...

  resource "vsphere_virtual_machine" "web" {
    tags             = [vsphere_tag.tag.id]
    ...
  }

Now, when I destroy e.g. the dev infra, it also deletes the prod vsphere tag and leave the VMs without the tag.

I tried to skip the deletion with the lifecycle, but then I would need to separately delete each resource which I don't like.

lifecycle {
  prevent_destroy = true
}

Is there a way to add an existing tag without having the resource managed by Terraform? Something hardcoded without having the tag included as a resource like:

  resource "vsphere_virtual_machine" "web" {
    tags             = [{
      name        = "SYS-Team"
      category_id = "Responsibility"
      description = "Systems group"
      }
    ]
    ...
  }
2

2 Answers

2
votes

You can use Terraform's data sources to refer to things that are either not managed by Terraform or are managed in a different Terraform context when you need to retrieve some output from the resource such as an automatically generated ID.

In this case you could use the vsphere_tag data source to look up the id of the tag:

data "vsphere_tag_category" "responsibility" {
  name = "Responsibility"
}

data "vsphere_tag" "sys_team" {
  name        = "SYS-Team"
  category_id = data.vsphere_tag_category.responsibility.id
}

...

resource "vsphere_virtual_machine" "web" {
  tags             = [data.vsphere_tag.sys_team.id]
  ...
}

This will use a vSphere tag that has either been created externally or managed by Terraform in another place, allowing you to easily run terraform destroy to destroy the VM but keep the tag.

1
votes

If I understood correctly the real problem is on:
when I destroy e.g. the dev infra, it also deletes the prod vsphere tag

That should not be happening!
any cross environment deletions is a red flag

It feels like the problem is in your pipeline, not your terraform code ...
The deployment pipelines I create the dev resources are not mixed with prod,
and IF they are mix, you are just asking for troubles,
your team should make redesigning that a high priority


You do ask:
Is there a way to add an existing tag without having the resource managed by Terraform?

Yes you can use PowerCLI for that:
https://blogs.vmware.com/PowerCLI/2014/03/using-vsphere-tags-powercli.html

the command to add tags is really simple:
New-Tag –Name “jsmith” –Category “Owner”

You could even integrate that into terraform code with a null_resource something like:

resource "null_resource" "create_tag" {
  provisioner "local-exec" {
    when        = "create"
    command     = "New-Tag –Name “jsmith” –Category “Owner”"
    interpreter = ["PowerShell"]
  }
}