hashicorp / hashicorp/terraform-plugin-framework

SetNestedAttributes plan does not like single nested compute null values

Open
#302 5 comments 0 reactions 0 assignees View on GitHub
documentation
Dominant language
Go
Stars
384
Forks
107
Avg merge
3m
Merged PRs (30d)
1

Description

I have very hard times to make SetNestedAttributes properly working when it has optional nested attributes and with optional computed attributes.
It looks like null values are not properly recognised or ignored.
I am not sure if am doing something wrong here, I tried a couple of combinations with UseStateForUnknown modifiers, but it does not really change anything.

### Module version

```
github.com/hashicorp/terraform-plugin-framework v0.6.1
```

### Relevant provider source code

```go

type (
podResourceBug struct{}
podResourceBugType struct{}

podResourceBugData struct {
Mounts []*podResourceBugDataMount `tfsdk:"mounts"`
}

podResourceBugDataMount struct {
Name types.String `tfsdk:"name"`
A *podResourceBugDataNested `tfsdk:"a"`
B *podResourceBugDataNested `tfsdk:"b"`
}

podResourceBugDataNested struct {
Path types.String `tfsdk:"path"`
Optional types.Bool `tfsdk:"optional"`
}
)

func (t podResourceBugType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"mounts": {
Optional: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
Attributes: tfsdk.SetNestedAttributes(
map[string]tfsdk.Attribute{
"name": {
Type: types.StringType,
Required: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
},
"a": {
Computed: true,
Optional: true,
Attributes: tfsdk.SingleNestedAttributes(
map[string]tfsdk.Attribute{
"path": {
Type: types.StringType,
Required: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
},
"optional": {
Type: types.BoolType,
Optional: true,
Computed: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
},
},
),
},
"b": {
Computed: true,
Optional: true,
Attributes: tfsdk.SingleNestedAttributes(
map[string]tfsdk.Attribute{
"path": {
Type: types.StringType,
Required: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
},
"optional": {
Type: types.BoolType,
Optional: true,
Computed: true,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.RequiresReplace(),
},
},
},
),
},
},
tfsdk.SetNestedAttributesOptions{},
),
},
},
}, nil
}

func (t podResourceBugType) NewResource(ctx context.Context, in tfsdk.Provider) (tfsdk.Resource, diag.Diagnostics) {
return podResourceBug{}, nil
}

func (r podResourceBug) Create(ctx context.Context, req tfsdk.CreateResourceRequest, resp *tfsdk.CreateResourceResponse) {
var data podResourceBugData
resp.Diagnostics.Append(
req.Config.Get(ctx, &data)...,
)

if resp.Diagnostics.HasError() {
return
}
// emulate "computed" value
data.Mounts[0].A.Optional.Null = false

// Set state
resp.Diagnostics.Append(
resp.State.Set(ctx, &data)...,
)
}

func (r podResourceBug) Read(ctx context.Context, req tfsdk.ReadResourceRequest, resp *tfsdk.ReadResourceResponse) {
var data podResourceBugData
resp.Diagnostics.Append(
req.State.Get(ctx, &data)...,
)

// Set state
resp.Diagnostics.Append(
resp.State.Set(ctx, &data)...,
)
}

```

### Terraform Configuration Files

```hcl
resource "resource_bug" "test" {
mounts = [
{
name = "test"
// or omit b
b = null

a = {
path = "x"
}
},
]
}

```

### Expected Behavior
No change on update, but it triggers replacement all the time

### Actual Behavior

Replacements, even the resource did not change at all.
I actual face two different problem based on the settings:

When null is explicitly set for `b` :
diff:
```
~ mounts = [
+ { # forces replacement
+ a = {
+ optional = (known after apply)
+ path = "x"
}
+ b = {
+ optional = (known after apply)
+ path = (known after apply)
}
+ name = "test"
},
- { # forces replacement
- a = {
- optional = false -> null
- path = "x" -> null
}
- name = "test" -> null
},
]
```

### References
I think it might be related to #293, but not sure.

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.