Issues with Terraform JSON

Hello folks! I have been dealing with this problem for quite some time now and am hoping to be missing something really simple at this point!

Basically, when I use the JSON syntax of building the terraform files,I cannot get the disk portition to function correctly and the error given is quite odd. When I use the HLC2 format, it works like a charm!

I am not using one of the known providers but the libvirt one for creating VMs with KVM:

{
  "data": [
    {
      "template_file": [
        {
          "user_data": [
            {
              "template": "$file(\"/home/terraform/config/cloud_init.cfg\")"
            }
          ]
        }
      ]
    },
    {
      "template_file": [
        {
          "meta_data": [
            {
              "template": "file(\"/home/terraform/config/network_config.cfg\")"
            }
          ]
        }
      ]
    }
  ],
  "resource": [
    {
      "libvirt_volume": [
        {
          "vm-001": [
            {
              "format": "qcow2",
              "name": "vm-001.qcow2",
              "pool": "vm-storage",
              "source": "/home/terraform/images/CentOS-7.qcow2"
            }
          ]
        }
      ]
    },
    {
      "libvirt_cloudinit_disk": [
        {
          "cloudinit": [
            {
              "meta_data": "${data.template_file.meta_data.rendered}",
              "name": "cloudinit.iso",
              "pool": "vm-storage",
              "user_data": "${data.template_file.user_data.rendered}"
            }
          ]
        }
      ]
    },
    {
      "libvirt_domain": [
        {
          "vm-001": [
            {
              "autostart": "true",
              "cloudinit": "${libvirt_cloudinit_disk.cloudinit.id}",
              "memory": "2048",
              "name": "vm-001",
              "network_interface": [
                {
                   "bridge": "br0"
                }
              ],
              "disk": {
              [
                {
                 "volume_id": "${libvirt_volume.vm-001.id}"
                }
              ]
              },
              "running": "true",
              "vcpu": "2"
            }
          ]
        }
      ]
    }
  ]
}

This is my .tf.json file and the error given is:

Error: Incorrect attribute value type

  on vm.tf.json line 69, in resource[2].libvirt_domain[0].vm-001[0]:
  69:               "disk": [
  70:                 {
  71:                  "volume_id": "${libvirt_volume.vm-001.id}"
  72:                 }
  73:               ],

Inappropriate value for attribute "disk": element 0: attributes
"block_device", "file", "scsi", "url", and "wwn" are required.

If someone would give me a hand with this it would be greatly appreciated!

Hi @Unfairz,

It looks like (as of GitHub issue #665 being closed) the provider is using the special attributes as blocks processing mode for this particular argument, which causes it to behave in some unusual ways as described on that documentation page. In particular, you’re running into the quirk described under the In JSON Syntax heading:

Due to the ambiguity of the JSON syntax, there is no way to distinguish based on the input alone between argument and nested block usage, so the JSON syntax cannot support the nested block processing mode for these arguments. This is, unfortunately, one necessary concession on the equivalence between native syntax and JSON syntax made pragmatically for compatibility with existing provider design patterns. Providers may phase out such patterns in future major releases.

To make it work, you’ll need to write the object representing this block as if it were a normal object construction expression, rather than using the JSON conventions for nested blocks. That means the object value must have all of the attributes that the object type of the argument expects, with the ones you don’t need set to null. (The block syntax normally sets these to null automatically for you in the background, but the provider has disabled that processing mode here).

              "disk": {
              [
                {
                 "volume_id": "${libvirt_volume.vm-001.id}",
                 "block_device": null,
                 "file": null,
                 "scsi": null,
                 "url": null,
                 "wwm": null
                }
              ]
              },

This unusual requirement could be fixed at the provider level by disabling the special processing mode, but from reading the issue linked above it looks like opting into it was intentional in order to restore some behavior that was possible under Terraform 0.11 (I didn’t follow exactly what), and so it’s perhaps unlikely that it would be reverted back to the standard processing mode at this point.

Hello! @apparentlymart

Thank you so much for explaining this so well and showing me where the problem is! You have truly helped me a lot!

Hope you have a wonderful day and once again, thank you!!

i just stumbled upon this in the vault_auth_backend.tune, but setting the fields as null doesn’t seem to do it. It fails type checking. Terraform fails with

│ Error: expected 'tune.0.max_lease_ttl' to be a valid duration string