Inability to Distinguish Between Unset and Empty TypeMap Attributes in Terraform SDK v2

In Terraform SDK v2, there is a challenge in differentiating between TypeMap attributes that are explicitly set to an empty map by the user and those that are left unset. This issue arises because both scenarios result in the attribute being represented as an empty map[string]interface{} in the resource data, making it impossible to ascertain whether the user specified the attribute or not.

Demonstration:

Consider the following Terraform configuration:

resource "example_resource" "test" {
  // Case 1: Attribute not specified
  // my_map = {}

  // Case 2: Attribute explicitly set to an empty map
  my_map = {}
}

In the resource schema:

"my_map": {
  Type:     schema.TypeMap,
  Optional: true,
},

Within the resource’s CRUD functions, attempting to retrieve the value of my_map using d.Get("my_map") yields an empty map[string]interface{} in both cases. This behavior prevents the provider from determining whether the user omitted the attribute or explicitly set it to an empty map.

Workaround Attempt:

A similar issue exists with TypeList attributes, where distinguishing between unset and empty lists is problematic. A common workaround involves using a sentinel value to represent an unset state. For instance, setting a default value that is unlikely to be used by the user allows the provider to identify when the attribute is unset.

However, applying this sentinel approach to TypeMap attributes is not straightforward, as it requires defining a default value that can unambiguously represent an unset state without conflicting with valid user inputs.

Request for Guidance:

We seek guidance on the following:

  1. Recommended Approach: What is the best practice for distinguishing between unset and explicitly empty TypeMap attributes in Terraform SDK v2?
  2. Sentinel Value Implementation: Is there an effective method to implement a sentinel value for TypeMap attributes, similar to the approach used for TypeList?
  3. SDK Enhancements: Are there any planned enhancements to the SDK that will address this issue, or existing features that we may not be aware of?

We appreciate any insights or recommendations to effectively handle this scenario within the current capabilities of Terraform SDK v2.

Hi @MajidAbuRmila,

The legacy SDK was written at a time before Terraform had null values, so much of the code uses a type system incapable of differentiating between unset and zero values. Some GetRaw* methods were layered on top of the SDK (in the ResourceData and ResourceDiff types IIRC) which can return more accurate values and help workaround difficult situations, but you are still going to be fighting the builtin behaviors which can’t use those types.

New providers are written using the Terraform Plugin Framework, which offers access to the full API and type system used by Terraform.