hashicorp / terraform-provider-vsphere

Terraform Provider for VMware vSphere
https://registry.terraform.io/providers/hashicorp/vsphere/
Mozilla Public License 2.0
612 stars 450 forks source link

Improved Syntax for Custom Attributes #370

Closed jcreedon closed 6 years ago

jcreedon commented 6 years ago

I'm very excited to finally have custom attributes for vsphere in terraform. However the syntax is annoying if you want to do more than one custom attribute. Either you have to deal with a very long string or a here doc.

(Sorry if the below formatting isn't right, I wasn't sure the best way to shoe horn a feature request into the issue template.)

Terraform Version

Terraform v0.11.2

vSphere Provider Version

provider.vsphere v1.2.0

Affected Resource(s)

Please list the resources as a list, for example:

Terraform Configuration Files

Per the documentation, this format should be used for specifying custom attrbiutes

resource "vpshere_virtual_machine" "web" {
  ...

  custom_attributes = "${map(vsphere_custom_attribute.attribute.id, "value")}"
}

Desired Behavior

Something reasonable like how tags work with the AWS provider would be fantastic, like:

  custom_attributes {
    app = "appname"
    envname = "${var.envname}"
    role = "web"
    shortenv = "${var.shortenv}"
  }

Important Factoids

I think there also might be a bug in the HCL or HIL parser. What I end up having to use is:

  custom_attributes = <<EOF
${map(
data.vsphere_custom_attribute.attribute-app.id, "appname",
data.vsphere_custom_attribute.attribute-envname.id, "${var.envname}",
data.vsphere_custom_attribute.attribute-role.id, "web",
data.vsphere_custom_attribute.attribute-shortenv.id, "${var.shortenv}"
)}EOF

However idiomatic here docs (as specified by bash) should be written as such:

  custom_attributes = <<EOF
${map(
data.vsphere_custom_attribute.attribute-app.id, "appname",
data.vsphere_custom_attribute.attribute-envname.id, "${var.envname}",
data.vsphere_custom_attribute.attribute-role.id, "web",
data.vsphere_custom_attribute.attribute-shortenv.id, "${var.shortenv}"
)}
EOF

With the termination token on it's own line. However in this situation, terraform throws the following error:

Error: vsphere_virtual_machine.web: 1 error(s) occurred:

* vsphere_virtual_machine.web: At column 1, line 1: output of an HIL expression must be a string, or a single list (argument 1 is TypeMap) in:

${map(
data.vsphere_custom_attribute.attribute-app.id, "appname",
data.vsphere_custom_attribute.attribute-envname.id, "${var.envname}",
data.vsphere_custom_attribute.attribute-role.id, "web",
data.vsphere_custom_attribute.attribute-shortenv.id, "${var.shortenv}"
)}

As a stopgap, if HCL could support the <<- syntax, that would help cleanup some of the mess because then you could at least indent it like this:

  custom_attributes = <<-EOF
    ${map(
    data.vsphere_custom_attribute.attribute-app.id, "appname",
    data.vsphere_custom_attribute.attribute-envname.id, "${var.envname}",
    data.vsphere_custom_attribute.attribute-role.id, "web",
    data.vsphere_custom_attribute.attribute-shortenv.id, "${var.shortenv}"
    )}
    EOF
vancluever commented 6 years ago

@jcreedon the awkward tagging interface here is due to how vSphere works with tags versus AWS. In AWS, tags are simple key/value pairs, in vSphere, they there are more complicated pre-configured data sets that need to be attached to objects via their IDs. We we have a framework in the vSphere provider of allowing as little arbitrary data as possible in downstream resources, you first either have to create the attribute with the vsphere_custom_attribute resource, or fetch its data with the counterpart data source if it exists already, and then reference its id in the appropriate resource.

As for the HIL issues, that could definitely be cleaned up. I'm going to check what the right project to open that issue up against would be. We are currently working on a new version of HCL that is aiming to bring both language structure and interpolation together, so depending on everyone's time and priorities, this might instead be something that gets fixed in HCL2 instead.

Thanks!

vancluever commented 6 years ago

Hey @jcreedon I just confirmed that since we are focusing on HCL2 that this is more than likely where it will be fixed.

With HCL2, we will be implementing a couple of things that pertain to what you are trying to do here:

# NOT YET IMPLEMENTED and may change before final release
  custom_attributes = {
    "${data.vsphere_custom_attribute.attribute-app.id}"      = "appname"
    "${data.vsphere_custom_attribute.attribute-envname.id}"  = var.envname
    "${data.vsphere_custom_attribute.attribute-role.id}"     = "web"
    "${data.vsphere_custom_attribute.attribute-shortenv.id}" = var.shortenv
  }

HCL2 is a priority for the Terraform Core team, and while there is no official release date or specific feed that progress can be tracked on, you can watch the Core project for updates on its incorporation into Terraform itself.

Thanks!

jcreedon commented 6 years ago

HCL2 looks to be the right solution. I look forward to seeing it. Thanks!