Alex Cohen
Alex Cohen

Reputation: 6206

How to allow an ordered list in a custom terraform provider resource?

I have a custom terraform provider with a resource that takes a list as one of its inputs.

Here is the list in question: https://github.com/volterraedge/terraform-provider-volterra/blob/main/volterra/resource_auto_volterra_http_loadbalancer.go#L3501

When I declare the list, it needs to be set as multiple blocks like the following:

  active_service_policies {
    policies {
      name      = "foobar"
      namespace = "shared"
    }
    policies {
      name      = "batz"
      namespace = "shared"
    }
  }

Instead, I want to be able to declare it like the following:

  active_service_policies {
    policies = [
    {
      name      = "foobar"
      namespace = "shared"
    },
    {
      name      = "batz"
      namespace = "shared"
    }
    ]
  }

This causes the following error:

Error: Unsupported argument
  on main.tf line 79, in resource "volterra_http_loadbalancer" "sp":
  79:     policies = [
An argument named "policies" is not expected here. Did you mean to define a block
of type "policies"?

Why cant I use an ordered list and how can I allow its use?

Is this issue becaue the policies is a Type: schema.TypeList, should this be a TypeSet or some other object instead?

Upvotes: 1

Views: 763

Answers (1)

Martin Atkins
Martin Atkins

Reputation: 74299

The Terraform SDK you are using was originally designed for Terraform v0.11 and earlier and so it doesn't support configuration constructs that those older Terraform versions didn't support, and Terraform v0.11 and earlier didn't support lists of objects in the way you are intending here.

To use the full capabilities of the modern Terraform language you can instead build your provider with the newer Plugin Framework, which is designed around the modern Terraform language type system, although it is also currently less mature than the older SDK due to their difference in age.

In the new framework you can declare a tfsdk.Attribute which has an Attributes field set to a tfsdk.ListNestedAttributes result:

tfsdk.Attribute{
    Attributes: tfsdk.ListNestedAttributes(
        map[string]tfsdk.Attribute{
            "name": tfsdk.Attribute{
                // ...
            },
            "namespace": tfsdk.Attribute{
                // ...
            },
        },
        tfsdk.ListNestedAttributesOptions{},
    ),

    // ...
}

The above (partial) example declares an attribute that expects a list of objects where each object can have name and namespace attributes itself.

The closest you can get to this in the older SDK is the sequence of blocks you showed in your example. In older providers built with that SDK, the common pattern here would be to give the block the singular name policy, rather than the plural name policies, so that it's clearer in the configuration that each block is declaring just one policy in the sequence.

Upvotes: 2

Related Questions