Skip to content

ResourceData.Set() doesn't set empty List/Set of String when Create/Update resource #766

@jeremmfr

Description

@jeremmfr

SDK version

github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1

Relevant provider source code

provider.go

package example

import (
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func Provider() *schema.Provider {
	return &schema.Provider{
		Schema: map[string]*schema.Schema{},
		ResourcesMap: map[string]*schema.Resource{
			"example_list": resourceList(),
		},
	}
}

resource_list.go

package example

import (
	"context"
	"log"

	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceList() *schema.Resource {
	return &schema.Resource{
		CreateContext: resourceListCreate,
		ReadContext:   resourceListRead,
		UpdateContext: resourceListUpdate,
		DeleteContext: resourceListDelete,
		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"list": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"set": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"list2": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"set2": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

func resourceListCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Printf("Create")
	d.SetId(d.Get("name").(string))

	return resourceListRead(ctx, d, m)
}

func resourceListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Printf("Read")
	v := make([]string, 0)
	if err := d.Set("list", v); err != nil {
		panic(err)
	}
	if err := d.Set("set", v); err != nil {
		panic(err)
	}

	return nil
}

func resourceListUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Printf("Update")
	v := make([]string, 0)
	if err := d.Set("list2", v); err != nil {
		panic(err)
	}
	if err := d.Set("set2", v); err != nil {
		panic(err)
	}

	return resourceListRead(ctx, d, m)
}

func resourceListDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Printf("Delete")

	return nil
}

Terraform Configuration Files

terraform {
  required_providers {
    example = {
      source = "sdk/example"
    }
  }
}

resource "example_list" "list" {
  name = "test"
}

Debug Output

First apply: https://gist.github.com/jeremmfr/8fdf0aef9a9dba35aa7c2a429013a466
Second apply: https://gist.github.com/jeremmfr/ce7fc52349967f60dbb11845b5839e7a

Especially in second apply :

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # example_list.list has been changed
  ~ resource "example_list" "list" {
        id   = "test2"
      + list = []
        name = "test2"
      + set  = []
    }

Expected Behavior

list and set arguments set in state to an empty list on first apply (create).

Actual Behavior

list and set arguments set in state to an empty list only when refresh resource.
With new Terraform version (0.15.4), the note Note: Objects have changed outside of Terraform appears for the wrong reason.

Steps to Reproduce

  1. terraform init
  2. terraform apply -auto-approve
  3. terraform apply -auto-approve

Others errors

If I update name argument, list2 and set2 not set to an empty list in state when apply (update)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions