TL;DR: I’d like to build a hierarchy of resources from details in a locals.map_variable
that are stitched together via id’s that are generated at “apply-time” and I think I’m asking for the impossible.
I’d like to assemble a set of GitLab groups/subgroups using the GitLab provider’s gitlab_group resource.
Subgroups are linked to their parent via the parent’s id, parent_id
.
It’s straightforward to bang these out with an explicit set of resources, simply referring to the parent group and grabbing its ID in the subgroup.
I’m using a module to create the groups with appropriate defaults, it’s a riff and extension of ideas from Lotte-Sara Laan’s Module Parameter Defaults with the Terraform Object Type post. I can just add a separate invocation of my module for each resource, but I end up needing to call terraform init
every time I add a new one, which seems unintuitive.
I’d rather just define the set of groups in a map variable and invoke the module once using a for_each
loop.
The module is invoked something like this:
module "groups" {
source = "./modules/defaulted_gitlab_group"
for_each = local.our_groups
name = each.value["name"]
path = each.value["path"]
description = each.value["description"]
parent_id = each.value["parent_id"]
group_settings = each.value["group_settings"]
}
Ideally our_groups
would be something like this:
locals {
# various things elided...
our_groups = {
"foo" : {
name = "Foo"
path = "foo"
description = "Foo"
group_settings = local.group_defaults
members = {
"george-hartzell" = "owner",
}
}
"foo-bar" : {
name = "Foo Bar"
path = "bar"
description = "Foo Bar"
group_settings = local.group_defaults
parent_id = module.groups["foo"].gitlab_group.id
}
}
}
BUT, I end up with an error message like this (edited from a real example to match the sanitized input above):
╷
│ Error: Unsupported attribute
│
│ on foo_groups.tf line 35, in locals:
│ 35: parent_id = module.groups["foo"].gitlab_group.id
│ ├────────────────
│ │ module.groups["foo"] is a object, known only after apply
│
│ This object does not have an attribute named "gitlab_group".
╵
I’ve also tried a second approach, where the local map contains the name of the parent group and I look it up in the module call/definition:
module "groups" {
source = "./modules/defaulted_gitlab_group"
for_each = local.our_groups
name = each.value["name"]
path = each.value["path"]
description = each.value["description"]
group_settings = each.value["group_settings"]
parent_id = module.groups[each.value["parent_group_name"]].group.id
}
Somewhat predictably, this leads to a cycle:
╷
│ Error: Cycle: module.groups (close), module.groups.var.parent_id (expand), module.groups.gitlab_group.group, module.groups.output.group (expand)
│
The only other resource I found that supported a hierarchy is a Google folder but I was unable to find any examples of people generating them from a map like I’m trying to do.
I’d love suggestions for getting out of the corner I’ve painted myself into.
Thanks!