terraform-plugin-sdk icon indicating copy to clipboard operation
terraform-plugin-sdk copied to clipboard

How to check a nested attribute’s presence in a configuration?

Open sumanth-lingappa opened this issue 3 years ago • 0 comments

SDK version

github.com/hashicorp/terraform-plugin-sdk/v2 v2.21.0

Relevant provider source code

Schema

package schemata

import (
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func ServiceProfileSchema() map[string]*schema.Schema {
	return map[string]*schema.Schema{
		"name": {
			Type:     schema.TypeString,
			Required: true,
		},
		"lb": {
			Type:     schema.TypeList,
			Optional: true,
			MaxItems: 1,
			Elem: &schema.Resource{
				Schema: map[string]*schema.Schema{
					"name": {
						Type:     schema.TypeString,
						Optional: true,
					},
					"lb_params": {
						Type:     schema.TypeList,
						Optional: true,
						MaxItems: 1,
						Elem: &schema.Resource{
							Schema: map[string]*schema.Schema{
								"algorithm": {
									Type:     schema.TypeString,
									Optional: true,
								},
								"stickiness_type": {
									Type:     schema.TypeString,
									Optional: true,
								},
								"max_server_connections": {
									Type:     schema.TypeInt,
									Optional: true,
								},
							},
						},
					},
				},
			},
		},
	}
}

Terraform Configuration Files

resource "cads_application" "app1" {
  service_profiles {
    name = "a3sp"
    lb {
      name = "lbsp"
      lb_params {
        algorithm       = "ROUND_ROBIN"
        stickiness_type = "SOURCE_IP"
        # max_server_connections = 1
      }
    }
}

Debug Output

Expected Behavior

I am writing a custom terraform provider. I need to read the above configuration.

I have written schema in such a way that lb and lb_params are of TypeList with MaxItems=1.

If I do not pass max_server_connections under lb_params in config (.tf file), the terraform SDK is sending max_server_connections=0 in payload.

I do not need this in my payload if it’s not present in the config.

How can I achieve it?

Even though I tried to use the below if block for max_server_connections, I see the max_server_connections in the payload.

Create function snippet

// service_profiles is just like network_functions
if service_profiles, ok := d.GetOk("service_profiles"); ok {
	serviceProfilesList := make([]interface{}, 0)
	sp := make(map[string]interface{})
	for _, v := range service_profiles.([]interface{}) {
		sp["name"] = v.(map[string]interface{})["name"].(string)
		// lb is of TypeList. take only the first element
		// if lb length is 0, then it is a service profile with no lb params
		if len(v.(map[string]interface{})["lb"].([]interface{})) > 0 {
			lbRaw := v.(map[string]interface{})["lb"].([]interface{})[0].(map[string]interface{})
			lbMap := make(map[string]interface{})
			lbMap["name"] = lbRaw["name"].(string)
			//lb_params is of TypeList. take only the first element
			if len(lbRaw["lb_params"].([]interface{})) > 0 {
				lbParamsRaw := lbRaw["lb_params"].([]interface{})[0].(map[string]interface{})
				lbParamsMap := make(map[string]interface{})
				lbParamsMap["algorithm"] = lbParamsRaw["algorithm"].(string)
				lbParamsMap["stickiness_type"] = lbParamsRaw["stickiness_type"].(string)
				if _, ok := lbParamsRaw["max_server_connections"]; ok {
					lbParamsMap["max_server_connections"] = lbParamsRaw["max_server_connections"].(int)
				}
				lbMap["lb_params"] = lbParamsMap
			}
			sp["lb"] = lbMap
		}
	}
}

Actual Behavior

Steps to Reproduce

References

I have asked the same question on discuss.hashicorp.com https://discuss.hashicorp.com/t/how-to-check-a-nested-attributes-presence-in-a-configuration/44123

sumanth-lingappa avatar Sep 10 '22 12:09 sumanth-lingappa