flatten object made of nested list in terraform
I have the following variable that I try to parse :
variable.tf
variable "rbac_roles" {
type = object(
{
view = list(object({
group_name = string,
group_id = string,
namespaces = list(string)
})),
edit = list(object({
group_name = string,
group_id = string,
namespaces = list(string)
})),
admin = list(object({
group_name = string,
group_id = string,
namespaces = list(string)
}))
}
)
}
variable.tfvars
rbac_roles = {
view = [
{
group_name = "group1",
group_id = "123",
namespaces = ["default", "namespace1"]
},
{
group_name = "group2",
group_id = "456",
namespaces = ["namespace2"]
}
],
edit = [
{
group_name = "group1",
group_id = "123",
namespaces = ["namespace2"]
}
],
admin = [
{
group_name = "group3",
group_id = "789",
namespaces = ["default, namespace1, namespace2"]
},
]
}
I try to create the following resources :
resource "kubernetes_role_binding" "view_cluster_role_binding" {
metadata {
name = ${group}-${namespace}-viewer-binding
namespace = ${namespace}
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = "view"
}
subject {
kind = "Group"
name = ${group}
api_group = "rbac.authorization.k8s.io"
}
}
resource "kubernetes_role_binding" "edit_cluster_role_binding" {
metadata {
name = ${group}-${namespace}-viewer-binding
namespace = ${namespace}
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = "edit"
}
subject {
kind = "Group"
name = ${group}
api_group = "rbac.authorization.k8s.io"
}
}
resource "kubernetes_role_binding" "admin_cluster_role_binding" {
metadata {
name = ${group}-${namespace}-viewer-binding
namespace = ${namespace}
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = "admin"
}
subject {
kind = "Group"
name = ${group}
api_group = "rbac.authorization.k8s.io"
}
}
So far I have tried to flatten()
my list and to loop over it with for
and foreach
but I haven't been successful yet. From what I understand I need to use a locals{}
to reach my goal, but I can't get the right syntax. Any help will be appreciated !
Solution 1:
First this is wrong ["default, namespace1, namespace2"]
. It should be ["default", "namespace1", "namespace2"]
. Once you fix that, you can flatten your data structure as follows:
locals {
flat_rbac_roles = merge([
for role, groups in var.rbac_roles:
merge([
for group_idx, group in groups:
{
for namespace_idx, namespace in group["namespaces"]:
"${role}-${group_idx}-${namespace_idx}" => {
role_name = role
group_name = group["group_name"]
group_id = group["group_id"]
namespace = namespace
}
}
]...)
]...)
}
which gives:
{
"admin-0-0" = {
"group_id" = "789"
"group_name" = "group3"
"namespace" = "default"
"role_name" = "admin"
}
"admin-0-1" = {
"group_id" = "789"
"group_name" = "group3"
"namespace" = "namespace1"
"role_name" = "admin"
}
"admin-0-2" = {
"group_id" = "789"
"group_name" = "group3"
"namespace" = "namespace2"
"role_name" = "admin"
}
"edit-0-0" = {
"group_id" = "123"
"group_name" = "group1"
"namespace" = "namespace2"
"role_name" = "edit"
}
"view-0-0" = {
"group_id" = "123"
"group_name" = "group1"
"namespace" = "default"
"role_name" = "view"
}
"view-0-1" = {
"group_id" = "123"
"group_name" = "group1"
"namespace" = "namespace1"
"role_name" = "view"
}
"view-1-0" = {
"group_id" = "456"
"group_name" = "group2"
"namespace" = "namespace2"
"role_name" = "view"
}
}