terraform-plugin-sdk
terraform-plugin-sdk copied to clipboard
Terraform apply always shows a change for unset optional boolean with default of false
SDK version
github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.0
Relevant provider source code
func guacamoleUser() *schema.Resource {
return &schema.Resource{
CreateContext: resourceUserCreate,
ReadContext: resourceUserRead,
UpdateContext: resourceUserUpdate,
DeleteContext: resourceUserDelete,
Schema: map[string]*schema.Schema{
"username": {
Type: schema.TypeString,
Description: "Username of guacamole user",
Required: true,
ForceNew: true,
},
"last_active": {
Type: schema.TypeString,
Description: "Epoch time string of last user activity",
Computed: true,
},
"attributes": {
Type: schema.TypeList,
Description: "Attributes of guacamole user",
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organizational_role": {
Type: schema.TypeString,
Description: "Organizational role of user",
Optional: true,
Default: "",
},
"full_name": {
Type: schema.TypeString,
Description: "Full name of user",
Optional: true,
Default: "",
},
"email": {
Type: schema.TypeString,
Description: "Email of user",
Optional: true,
Default: "",
},
"expired": {
Type: schema.TypeBool,
Description: "Whether the user is expired",
Optional: true,
Default: false,
},
"timezone": {
Type: schema.TypeString,
Description: "Timezone of user",
Optional: true,
Default: "",
},
"access_window_start": {
Type: schema.TypeString,
Description: "Access window start time for user",
Optional: true,
Default: "",
},
"access_window_end": {
Type: schema.TypeString,
Description: "Access window end time for user",
Optional: true,
Default: "",
},
"disabled": {
Type: schema.TypeBool,
Description: "Whether account is disabled",
Optional: true,
Default: false,
},
"valid_from": {
Type: schema.TypeString,
Description: "Start date for when user is valid",
Optional: true,
Default: "",
},
"valid_until": {
Type: schema.TypeString,
Description: "End date for when user is valid",
Optional: true,
Default: "",
},
},
},
},
"group_membership": {
Type: schema.TypeSet,
Description: "Groups this user is a member of",
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"system_permissions": {
Type: schema.TypeSet,
Description: "System permissions assigned to user",
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}
Terraform Configuration Files
...
Debug Output
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
2021/01/06 08:53:23 [DEBUG] command: asking for input: "Do you want to perform these actions?"
# guacamole_user.test_user will be updated in-place
~ resource "guacamole_user" "test_user" {
id = "testUser"
# (4 unchanged attributes hidden)
- attributes {
- disabled = false -> null
- expired = false -> null
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
Config snippets
main.tf
resource "guacamole_user" "test_user" {
username = "testUser"
}
terraform.tfstate
{
"version": 4,
"terraform_version": "0.14.3",
"serial": 234,
"lineage": "06621170-99a5-4601-6744-02b6e5831bb1",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "guacamole_user",
"name": "test_user",
"provider": "provider[\"techbeck03.com/techbeck03/guacamole\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"attributes": [
{
"access_window_end": "",
"access_window_start": "",
"disabled": false,
"email": "",
"expired": false,
"full_name": "",
"organizational_role": "",
"timezone": "",
"valid_from": "",
"valid_until": ""
}
],
"group_membership": [],
"id": "testUser",
"last_active": "0",
"system_permissions": [],
"username": "testUser"
},
"sensitive_attributes": [],
"private": "bnVsbA=="
}
]
}
]
}
Expected Behavior
On the first terraform apply the resource should be created and the state file should reflect the one shown above. Subsequent calls to terraform apply without any changes to resource definition should show no pending changes.
Actual Behavior
On the first terraform apply everything works as expected and the above state file is created (and looks as expected). Subsequent calls to terraform apply always show the following pending changes:
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
2021/01/06 08:53:23 [DEBUG] command: asking for input: "Do you want to perform these actions?"
# guacamole_user.test_user will be updated in-place
~ resource "guacamole_user" "test_user" {
id = "testUser"
# (4 unchanged attributes hidden)
- attributes {
- disabled = false -> null
- expired = false -> null
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
This happens every time i do a terraform apply even though nothing has changed within the resource definition.
Steps to Reproduce
terraform initterraform apply
References
Working with a custom provider and this is happening to me too. I only have issues when I use _ = d.Set("project", project). As long as I don't actually set anything other than the id, it works. Sort of. If I don't set anything then I can't actually update the state from the API I'm calling.
EDIT: This fixed me up https://github.com/hashicorp/terraform-provider-aws/issues/17161#issuecomment-762942937