Summary
Removal of O/C single nested attributes don’t trigger a plan change. However when unrelated attributes are changed, a plan change is triggered and the nested attribute is passed as unknown in the plan.
Full example
For example, we start with this definition where read_only_specs is an Optional / Computed SingleNestedAttribute and all its attributes are also Optional / Computed:
resource "mongodbatlas_advanced_cluster" "test" {
project_id = "<PROJECT_ID>"
name = "test"
cluster_type = "SHARDED"
replication_specs = [
{
region_configs = [
{
provider_name = "AWS"
region_name = "US_EAST_1"
priority = 7
electable_specs = {
node_count = 3
instance_size = "M10"
}
read_only_specs = {
node_count = 1
instance_size = "M10"
}
}
]
}
]
}
- We do terraform apply to create the resource.
- We remove the read_only_specs attribute from the config.
- We do terraform plan (or apply) and no plan changes are shown. Debugging the provider with breakpoints, I can see in Read operation that read_only_specs state is known, in ModifyPlan operation both state and plan for read_only_specs are known, config is null as it has been deleted from the definition. This behavior is expected, as read_only_specs is O/C and it’s not anymore in the definition, it behaves as Optional, Read returns the same state, so the plan matches the state and no plan changes are shown.
- We change an unrelated attribute, e.g. region_name from US_EAST_1 to US_WEST_2.
- We do terraform plan (or apply) and it shows this plan change:
...
~ read_only_specs = {
~ disk_iops = 3000 -> (known after apply)
~ disk_size_gb = 10 -> (known after apply)
~ ebs_volume_type = "STANDARD" -> (known after apply)
~ instance_size = "M10" -> (known after apply)
~ node_count = 1 -> (known after apply)
} -> (known after apply)
~ region_name = "US_EAST_1" -> "US_WEST_2"
...
Read operation sets the response with a known value for read_only_specs, however ModifyPlan and Update receive a plan that is unknown, presumably because it behaves as Optional as it’s not in the config anymore.
IMPORTANT: Our Update API assumes that you want to delete / set to default when a block is not passed in the update request payload. We don’t pass unknown values in the payload. So in this case, we’ll end up deleting the read-only nodes when the read_only_specs block is removed from the config.
Questions
- Is there a way to detect a plan change when an O/C single nested attribute is deleted from the config?
- How can we differentiate the case where the attribute was never present in the config vs it was deleted, as the
plan
isunknown
in both cases? - What is the recommended behavior when an O/C single nested attribute is deleted from the config?
A. Behave like if it was never there and reset to default values (e.g. remove read-only nodes).
B. Keep theplan
with thestate
info (e.g. keep read-only nodes), even if they are not in theconfig
anymore, similar to SDKv2 behavior. - Right now we’re using B as it’s safer for the customer. For example if they’re importing an existing resource with read-only nodes and forget read_only_specs in the config, it’s confusing to show “read_only_specs will be known after apply” and then delete the nodes. In order to do this we’re implementing ModifyPlan to copy attributes from read_only_specs state to plan when plan is unknown. Is this a good approach or there is a better way?
- In case A is recommended, we came with the idea to implement ModifyPlan to set read_only_specs to
null
(so plan is shown, and it’s correctly showing that it will be deleted / set to null) when it is in thestate
but not in theconfig
but this sounds like complex logic. Also not sure if this goes against a TF best practice to show no plan changes if an O/C attribute is deleted. Is this a good approach or there is a better way? - Right now we’re more concerned with O/C single nested attributes, but this also happens with regular attributes so same questions apply. E.g., if
node_count
is deleted fromread_only_specs
, keepingread_only_specs
in the config, is the recommended behavior to keep the nodes (keep 1 node) or deleting them (0 nodes)?
Thanks.