1

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?

Alex Cohen
  • 5,596
  • 16
  • 54
  • 104
  • We need to see the resource schema in your provider code. – Matthew Schuchard Nov 18 '21 at 12:00
  • https://github.com/volterraedge/terraform-provider-volterra/blob/main/volterra/resource_auto_volterra_http_loadbalancer.go#L3501 – Alex Cohen Nov 18 '21 at 15:33
  • I do not believe the SDK supports nested maps in resource arguments in its schema, so your closest would be a `list` with `elem` of `map` with `string`. However, this would need to be "top-level". – Matthew Schuchard Nov 18 '21 at 15:52

1 Answers1

2

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.

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138