hashicorp / hashicorp/terraform-plugin-sdk

TypeSet is not modified during Update

Open
#792 5 comments 5 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
485
Forks
244
Avg merge
19h 57m
Merged PRs (30d)
4

Description

# SDK Version
`
2.7.0
`

# Relevant provider source code
Resource:
```golang
func resourceTestComponent() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"the_test": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"to_change": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
CreateContext: tCreate,
CustomizeDiff: tDiff,
ReadContext: tRead,
UpdateContext: tUpdate,
DeleteContext: tDelete,
}
}

func tRead(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
log.Println("================> In Read <================")
var diags diag.Diagnostics
err := rd.Set("the_test", generateMap([]map[string]string{
{
"id": "1",
"to_change": "noRead",
},
{
"id": "2",
"to_change": "NoRead",
},
}))
if err != nil {
return diag.FromErr(err)
}

log.Println("================> End of Read <================")
return diags
}

func generateMap(mapper []map[string]string) []interface{} {
var result []interface{}
for _, elt := range mapper {
result = append(result, elt)
}

return result
}

func tCreate(c context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Println("================> In create <================")
var diags diag.Diagnostics
data.SetId("un")

err := data.Set("the_test", generateMap([]map[string]string{
{
"id": "1",
"to_change": "no",
},
{
"id": "2",
"to_change": "no",
},
}))
if err != nil {
return diag.FromErr(err)
}

log.Println("================> End of create <================")
log.Println(err)
return diags
}

func tDiff(c context.Context, rd *schema.ResourceDiff, i interface{}) error {
log.Println("================> In Custom diff <================")

resourceName, _ := rd.GetChange("name")
if resourceName == "" {
return nil
}

err := rd.SetNew("the_test", generateMap([]map[string]string{
{
"id": "1",
"to_change": "yes",
},
{
"id": "2",
"to_change": "yes",
},
}))
if err != nil {
return err
}

log.Println("================> End of custom diff <================")
return nil
}

func tUpdate(c context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Println("================> In Update <================")
var diags diag.Diagnostics
setter := data.Get("the_test").(*schema.Set)

log.Println("-> Before sata set")
log.Println(setter.List())

for _, elt := range setter.List() {
m := elt.(map[string]interface{})
m["to_change"] = "no2"
}

log.Println("-> After manual loop")
log.Println(setter.List())

err := data.Set("the_test", setter)
if err != nil {
return diag.FromErr(err)
}

log.Println("-> After sata set")
setter2 := data.Get("the_test").(*schema.Set)
log.Println(setter2.List())

log.Println("================> End of Update <================")
return diags
}

```
State First plan/apply
```
resource "test_comp" "base-config" {
id = "un"
name = "new"
the_test = [
{
id = "1"
to_change = "no"
},
{
id = "2"
to_change = "no"
},
]
}

```
State after the second plan/apply
```
resource "test_comp" "base-config" {
id = "un"
name = "new"
the_test = [
{
id = "1"
to_change = "yes"
},
{
id = "2"
to_change = "yes"
},
]
}

```
The value of the customDiff is persisted, not the Update.

# Issue
I am developping a TF provider.
I have a resource with a Computed TypeSet.

When calling the Create function at first apply, the TypeSet is created with the rights values.
Then the second plan shows the diff from the values in the CustomizeDiff.

But once applied, it is the values of the CustomeDiff that are stored in the state and not the value of the the Update function.

I pasted a representation of the code. In the logs I can see that in the update function the change happened, but is not persisted at the end.
Here are the logs of the provider
```bash
2021/08/12 09:46:46 ================> In Update <================: timestamp=2021-08-12T09:46:46.659Z
2021/08/12 09:46:46 -> Before sata set: timestamp=2021-08-12T09:46:46.659Z
2021/08/12 09:46:46 [map[id:1 to_change:yes] map[id:2 to_change:yes]]: timestamp=2021-08-12T09:46:46.659Z
2021/08/12 09:46:46 -> After manual loop: timestamp=2021-08-12T09:46:46.660Z
2021/08/12 09:46:46 [map[id:1 to_change:no2] map[id:2 to_change:no2]]: timestamp=2021-08-12T09:46:46.660Z
2021/08/12 09:46:46 -> After sata set: timestamp=2021-08-12T09:46:46.660Z
2021/08/12 09:46:46 [map[id:2 to_change:no2] map[id:1 to_change:no2]]: timestamp=2021-08-12T09:46:46.660Z
2021/08/12 09:46:46 ================> End of Update <================: timestamp=2021-08-12T09:46:46.660Z
```

# Expected Behavior
The value stored in the state file shoud be the one set in the function Update.

Am I missing something about how TypeSet works ?

The same behavior is working perfectly with TypeList.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.