One-to-Many Resource Association Even Possible?!

I’ve been trying to figure this one out for a few days and I can’t seem to wrap my head around a solution. I have two resources: snowflake_view and snowflake_view_grant. As seen here:

resource “snowflake_view” “this” {
for_each = local.view_map
database = each.value.database
schema = each.value.schema
name = each.value.name
comment = each.value.comment
statement = each.value.statement
}

resource “snowflake_view_grant” “grant” {
for_each = local.acl_map
database_name = snowflake_view.this[each.key].database
schema_name = snowflake_view.this[each.key].schema
view_name = snowflake_view.this[each.key].name
privilege = try(each.value.privilege, null)
roles = try(each.value.roles, null)

lifecycle {
replace_triggered_by = [snowflake_view.this[each.key].id]
}
}

For a single snowflake_view, I can have zero to many snowflake_view_grant resources. I also have added a lifecycle argument to snowflake_view_grant because I want each grant basically tied to the hip of its view. If the view gets destroyed/recreated I want the associated grants to also follow suit.

In my locals I have the following defined:

locals {
view_map = {
test_view_1 = {
database = “DL_TEST”
schema = “TEST”
name = “TEST_VIEW_1”
comment = null
statement = “SELECT 1 as HELLO;”
privilege = “SELECT”
roles = [“ROLE_A”]
},
test_view_2 = {
database = “DL_TEST”
schema = “TEST”
name = “TEST_VIEW_2”
comment = null
statement = “SELECT 1 as HELLO;”
privilege = “SELECT”
roles = [“ROLE_B”]
}
}

acl_map = {
    test_view_1 = {
        privilege = "SELECT"
        roles = ["ROLE_A"]
        },
    test_view_1 = {
        privilege = "REFERENCES"
        roles = ["ROLE_B"]
        }
    test_view_2 = {
        privilege = "SELECT"
        roles = ["ROLE_B"]
        }
    }

}

The problem I am running into is terraform doesn’t seem to like duplicate values in maps, so one of the “test_view_1” grants gets ignored. Is there a different way to structure this so that I can still implicitly tell Terraform there is a relationship between specific views and grants and so my lifecycle argument functions how I want it to?

Hi @akhelvig,

It’s part of the typical definition of a “map” (or “associative array”) in computer science that the keys must be unique. Therefore I think this is not the correct data structure to use for this situation.

There are some other data structures you might consider:

  1. A map of sets of objects, so that each of your views can have zero or more acls.

    This would allow you to preserve the fact that the top-level structure is a map while making room for each element to have multiple objects. You can look up the full set of acls for a particular view name using just a normal map index operation.

  2. A flat set of objects where the view name is one of the attributes of the objects.

    This would be the closest to what you seem to have intended in the example you shared because there would be no requirement to group the acls by view name; each acl just specifies the view name it belongs to without any regard to what other acls might exist for the same view name.

    It would be inconvenient to look up all of the acls for a single given view name in this case, but that doesn’t seem to be required based on what you’ve shown… you just need to be able to find the view name for each acl to look up in the view resource.