Hello,
I managed to create a folder structure on a GCP organization. But i’m not really satisfied with the code behind it.
First off, i simply converted a map a to flattened list in order to to be able to pass it to a for_each.
The structure looks like something :
rf1
|_sf11
|_sf12
rf2
|_sf21
|_sf211
|_sf22
|_sf221
and the map :
variable "folders" {
type = map
default = {
"rf1" = {
"subs" = {
"sf11" = {}
"sf12" = {}
}
}
"rf2" = {
"subs" = {
"sf21" = {
"subs" = {
"sf221" = {}
}
}
"sf22" = {
"subs" = {
"sf221" = {}
}
}
}
}
}
}
Like you may know, The folder structure on google cloud is managed with the google_folder resource.
To create a folder, you need to provide the display name and the parent id.
For a root folder, you’ll need to provide the parent “organization/0123456789”
For a sub folder, you’ll need to provide the parent folder id “folder/9876543210”
These id’s are only known once the resources are created.
Today i’m managing this creating three flattened variables, each one of them representing a level of “sub foldering”.
rf_flat = flatten([
for rf, subs in var.folders : {
folder = rf
parent = format("%s/%s", "organizations", var.organization_id)
}
])
sf_flat = flatten([
for rf, subs in var.folders : [
for sf in subs : {
parent_id = format("%s/%s", "organizations", var.organization_id)
parent_name = rf
folder = sf
parent = data.google_active_folder.lookup_folder[format("%s.%s", "organization", rf)].name
}
]
])
ssf_flat = flatten([
for rf, subs in var.folders : [
for sf, subs in subs : [
for ssf, subs in subs : {
parent_id = format("%s/%s", "folders", var.organization_id)
parent_name = sf
folder = ssf
parent = data.google_active_folder.lookup_folder[format("%s.%s", "folder", sf)].name
}
]
]
])
The data query is to get the correct id of the folder to create the child folders.
The problem here, is that i have two create 3 google_folder resource blocks with depends_on.
… But ok, i then tried to flatten all the information into one local. And tried to manage this with only one resource block.
The obvious problem is that i have some resources that needs the id’s provided by the same resource block.
folder_flat = concat(
flatten([
for f, p in var.folders : [
for fo in p.sa_owner : {
f = f
o = fo
id = f
p = format("%s/%s", "organizations", var.organization_id)
}
]
]),
flatten([
for f, p in var.folder_structure_iam : [
for ff, fp in p.subs : [
for fo in fp.sa_owner : {
f = ff
o = fo
id = format("%s/%s", f, ff)
p = google_folder.folder_hierarchy[f].name
#p = data.google_active_folder.lookup_folder[format("%s/%s", "folders", f)].name
#p = data.google_active_folder.lookup_folder[format("%s/%s", f, ff)].name
}
]
]
]),
flatten([
for f, p in var.folder_structure_iam : [
for ff, fp in p.subs : [
for fff, ffp in fp.subs : [
for ffo in ffp.sa_owner : {
f = fff
o = ffo
id = format("%s/%s/%s", f, ff, fff)
#p = data.google_active_folder.lookup_folder[format("%s/%s", "folders", ff)].name
#p = data.google_active_folder.lookup_folder[format("%s/%s/%s", f, ff, fff)].name
p = google_folder.folder_hierarchy[format("%s/%s", f, ff)].name
}
]
]
]
])
)
it gives me a map with all the information i need, except i cant get the folder id’s that i create.
resource "google_folder" "folder_hierarchy" {
for_each = { for fold in local.folder_flat : "${fold.id}" => fold }
parent = each.value.p
display_name = each.value.f
}
data "google_active_folder" "lookup_folder" {
for_each = { for fold in local.folder_flat : "${fold.id}" => fold }
parent = each.value.p
display_name = each.value.f
# depends_on = [
# google_folder.folder_hierarchy
# ]
}
And to be honest, i’m looping here because i cant find how to work this local with only one resource block.
And it looks like to me that i’m forced to create one resource block per subfolder level. Is that right ?
$ terraform plan
Error: Cycle: module.folder_structure.local.folder_flat (expand), module.folder_structure.google_folder.folder_hierarchy