hashicorp / hashicorp/terraform-plugin-sdk
Nested data resource optional fields are initialised to golang defaults irrespective of declaration in resource plan.
- Dominant language
- Go
- Stars
- 485
- Forks
- 244
- Avg merge
- 19h 57m
- Merged PRs (30d)
- 4
Description
### Terraform Version
```
Terraform v0.12.26
```
### Terraform Configuration Files
**Terraform plan:**
```terraform
data "avi_tenant" "default_tenant" {
name = "admin"
}
resource "avi_pool" "lb_pool" {
name = "pool1"
lb_algorithm = "LB_ALGORITHM_ROUND_ROBIN"
#min_servers_up
#min_health_monitors_up
servers {
ip {
type = "V4"
addr = "10.10.23.32"
}
#port = 2254
}
tenant_ref = data.avi_tenant.default_tenant.id
}
```
**`lb_pool`** and **`servers`** from the resource plan are mapped to **ResourcePoolSchema()** and **ResourceServerSchema()** respectively.
**Schema Config:**
```go
func ResourcePoolSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"min_health_monitors_up": {
Type: schema.TypeInt,
Optional: true,
},
"min_servers_up": {
Type: schema.TypeInt,
Optional: true,
},
.,
.,
.,
"servers": {
Type: schema.TypeList,
Optional: true,
Elem: ResourceServerSchema(),
},
.,
.,
.,
}
}
func ResourceServerSchema() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"autoscaling_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
.,
.,
.,
"external_uuid": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
.,
.,
.,
"ip": {
Type: schema.TypeSet,
Required: true,
Elem: ResourceIpAddrSchema(),
},
"port": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
}
}
```
### Debug Output
2020-07-10T04:43:15.813Z [DEBUG] plugin.terraform-provider-avi: 2020/07/10 04:43:15 **DEBUG: Found servers with type: []interface {}.**
2020-07-10T04:43:15.813Z [DEBUG] plugin.terraform-provider-avi: 2020/07/10 04:43:15 DATA: map[autoscaling_group_name: availability_zone: description: discovered_networks:[] enabled:true external_orchestration_id: **external_uuid:** hostname: ip:0xc000b03460 location:0xc000b030e0 mac_address: nw_ref: **port:0** **prst_hdr_val:** ratio:1 resolve_server_by_dns:false rewrite_host_header:false server_node: static:false verify_network:false vm_ref:],
2020-07-10T04:43:15.813Z [DEBUG] plugin.terraform-provider-avi: TYPE: **map[string]interface {}**
### Expected Behavior
The nested resource's fields should not be initialised to default values by itself, when not declared in the plan.
### Actual Behavior
In my resource plan I have intentionally commented out three fields in `min_servers_up`, `min_health_monitors_up` and `port` where port is the field resource `servers` which is nested in `lb_pool`. The behaviour to check if the keys in the top level resource (**lb_pool**) were set/not set is fine as methods of `schema.ResourceData` like GetOk()/GetOkExists() are accessible.
But when I try to fetch the nested resource `servers` from `schema.ResourceData`
`servers , _ := d.GetOk("servers")`
the type of `servers` is `[]interface{}` which is correct as the type declared in the `schema.Resource` is `schema.TypeList`. This slice further has the interfaces of type **`map[string]interface{}`** which is the main issue as it should be of type `*schema.ResourceData`. With this behaviour I cannot use methods like GetOk()/GetOkExists() etc. on the `map[string]interface{}` type to determine if a particular key was declared in the resource plan or was set to default by golang-default initialiser and there is always a value set for particular key in the map, though these are default values but they have a serious impact onto the end-point which gets configured with these unintended values.
### Steps to Reproduce
1. `terraform init`
2. `terraform apply`
Contributor guide
Research direction
Start by tracing schema.ResourceData.GetOk("servers") through nested TypeList handling and inspect how Elem: ResourceServerSchema() populates each map[string]interface{} value. Done means optional nested fields remain distinguishable as unset rather than receiving Go zero values, with coverage for min_servers_up, min_health_monitors_up, and port.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100