hashicorp / terraform-plugin-sdk

Terraform Plugin SDK enables building plugins (providers) to manage any service providers or custom in-house solutions
https://developer.hashicorp.com/terraform/plugin
Mozilla Public License 2.0
441 stars 232 forks source link

Default TypeList / TypeSet #142

Open iwarapter opened 5 years ago

iwarapter commented 5 years ago

Terraform provides a test example for using a default for TypeList: https://github.com/hashicorp/terraform/blob/master/helper/schema/schema_test.go#L3624

However if I define one in a provider I get: foo: Default is not valid for lists or sets

I have also tried using a DefaultFunc:

"foo": &schema.Schema{
      Type:     schema.TypeSet,
      Optional: true,
      DefaultFunc: func() (interface{}, error) {
        return []interface{}{"bar", "thing"}, nil
      },
      Elem: &schema.Schema{
        Type: schema.TypeString,
      },
    },

Which compiles but doesn't provide a default, how would you go about achieving this?

Thanks!

chkp-idoma commented 4 years ago

Hi, I ran into this problem also.

Do someone have some workaround to this problem?

Thanks.

Tensho commented 4 years ago

Hi, I'm still confused about Default option behavior for Set type. I'd expect if I specify Default option in schema it means the value should be returned by Get()/GetOk() call no matter is it specified in configuration or not.

resource example_box robin {
  bundle = "b-x"
  // "size" attribute of Set type is not specified here
}
func resourceExampleBox() *schema.Resource {
    return &schema.Resource{
        Create: resourceExampleBoxCreate,
...
    "size": {
        Type:     schema.TypeSet,
        Optional: true,
        Elem: &schema.Resource{
            Schema: map[string]*schema.Schema{
                "width": {
                    Type:     schema.TypeInt,
                    Optional: true,
                    Default:  100,
                },
                "height": {
                    Type:     schema.TypeInt,
                    Optional: true,
                    Default:  50,
                },
            },
        },
    },
...
func resourceExampleBoxCreate(d *schema.ResourceData, m interface{}) error {
...
    size := d.Get("size").(*schema.Set).List() // len: 0 here !!! why??? is it a bug or feature?

Here is my discussion with @slapula regarding the subject, but it didn't help me to understand is it a bug or feature. I've also created an example provider to play around and check the unexpected behavior of the defaults.

EliiseS commented 4 years ago

I'd also love some clarity on this issue

stikkireddy commented 4 years ago

From my understanding the way that defaults applied to "blocks" such as lists and sets require the block to be declared for it to work.

As you can see in the below example the fields have default env variables and the field is a type list with a max item of one. For the default values to be propagated to the values in the Set/List field it requires you to declare that block.

provider databricks {
host =....
basic_auth {}
}

Without declaring the empty block terraform does not seem to populate default values.

AFAIK you cannot set defaults on the set/list object itself but only the values it contains.

What I cannot confirm is if this is the intended behavior of the sdk/terraform.

Concrete example below:

Provider field definition: https://github.com/databrickslabs/terraform-provider-databricks/blob/c343db6a0c03b98d0f038b8a6c628d3ce2962db9/databricks/provider.go#L69-L89

Usage: https://github.com/databrickslabs/terraform-provider-databricks/blob/c343db6a0c03b98d0f038b8a6c628d3ce2962db9/databricks/resource_databricks_mws_credentials_mws_test.go#L126-L138

G-Rath commented 3 years ago

This also seems to be contrary to what the current documentation for Default says:

Value: any value of an elements Type for primitive types, or the type defined by Elem for complex types. Restrictions:

  • Cannot be used if Required is true
  • Cannot be used with DefaultFunc

If Default is specified, that value that is used when this item is not set in the configuration.

Currently based on this the documentation is just plain wrong 😕