Issues with state management of nested resource

I’m implementing a provider for the APM tool Instana. The provider is already used in production. Currently I’m working on support for maintaining user groups via the provider. Thereby I want to configure the permission set of the given group as a nested resource. The permission set contains several string sets which define certain assets for which the user group will get access granted.

I currently face the issue that after the first terraform apply empty sets are set to null instead of and empty set/slice in the state. The next terraform plan will then show the message

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # instana_rbac_group.example has been changed
  ~ resource "instana_rbac_group" "example" {
        id        = "t6iLKc3sRMmJwpnBg-W4oQ"
        name      = "test"
        # (1 unchanged attribute hidden)

      ~ permission_set {
          + kubernetes_cluster_uuids    = []
          + kubernetes_namespaces_uuids = []
          + mobile_app_ids              = []
          + website_ids                 = []
            # (2 unchanged attributes hidden)
        }
    }

After the second apply the state is fine and the message about changes outside of terraform is not shown any longer. The state file was never changed outside of terraform. The

What can cause this issue? How can I fix it?

The full resource definition including state update functions can be found on the active feature branch on github: terraform-provider-instana/resource-group.go at feature/93_groups · gessnerfl/terraform-provider-instana · GitHub. An extract of the relevant schema is listed below.

map[string]*schema.Schema{
	"name": {
		...
	},
	"full_name": {
		...
	},
	"members": {
		Type:        schema.TypeSet,
		Optional:    true,
		Description: "The members of the group",
		MaxItems:    1024,
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"user_id": {
					Type:        schema.TypeString,
					Required:    true,
					Description: "The user id of the group member",
				},
				"email": {
					Type:        schema.TypeString,
					Optional:    true,
					Description: "The email address of the group member",
				},
			},
		},
	},
	"permission_set": {
		Type:        schema.TypeList,
		Optional:    true,
		MaxItems:    1,
		Description: "The permission set of the group",
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"application_ids": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The scope bindings to restrict access to applications",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type: schema.TypeString,
					},
				},
				"infra_dfq_filter": {
					Type:        schema.TypeString,
					Optional:    true,
					Description: "The scope binding for the dynamic filter query to restrict access to infrastructure assets",
				},
				"kubernetes_cluster_ uuids": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The scope bindings to restrict access to Kubernetes Clusters",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type: schema.TypeString,
					},
				},
				"kubernetes_namespace_uids": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The scope bindings to restrict access to Kubernetes namespaces",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type: schema.TypeString,
					},
				},
				"mobile_app_ids": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The scope bindings to restrict access to mobile apps",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type: schema.TypeString,
					},
				},
				"website_ids": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The scope bindings to restrict access to websites",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type: schema.TypeString,
					},
				},
				"permissions": {
					Type:        schema.TypeSet,
					Optional:    true,
					Description: "The permissions assigned which should be assigned to the users of the group",
					MaxItems:    groupMaxNumberOfSetElements,
					Elem: &schema.Schema{
						Type:         schema.TypeString,
						ValidateFunc: validation.StringInSlice(restapi.SupportedInstanaPermissions.ToStringSlice(), false),
					},
				},
			},
		},
	},
}