Home > other >  Add values to deep nested map in Terraform
Add values to deep nested map in Terraform

Time:04-23

I'm using the AWS EKS module 18.20.5 and I'm trying to add values to a deeply nested map. The map is

variable "eks_managed_node_groups" {
  description = "Map of managed node group definitions to create"
  type        = any
  default     = {
    management_cluster_on_demand = {
      desired_capacity = 3
      max_capacity     = 10
      min_capacity     = 3

      instance_types = ["c5.2xlarge"]
      capacity_type  = "ON_DEMAND"
      k8s_labels = {
        Environment  = "testing"
        GithubRepo   = "infrastructure-modules-kubernetes-cluster"
        GithubSource = "terraform-aws-modules"
      }
      additional_tags = {
        cluster = "management_cluster_new"
      }

      block_device_mappings = {
        xvda = {
          device_name = "/dev/xvda"
          ebs = {
            volume_size           = 50
            volume_type           = "gp2"
            delete_on_termination = true
          }
        }
      }
    }
  }
}

What I am aiming to do is add some extra values into the ebs section, specifically

encrypted = true
kms_key_id = module.kms.arn

This would force any volumes added to a node group, to have their EBS volume encrypted with a KMS key.

I've tried using locals to add the values, but the issue is when I get to the xbda section, it tries to loop through the strings and fails

locals {
  managed_nodes = flatten([
    for group in var.eks_managed_node_groups: [
      for vol in group.block_device_mappings: [
        for settings in vol: [
          for values in settings: values
        ]
      ]
    ]
  ])
}

Which when running Terraform plan, results in the following error

│ Error: Iteration over non-iterable value
│ 
│   on main.tf line 9, in locals:
│    8:         for settings in vol: [
│    9:           for values in settings: values
│   10:         ]
│ 
│ A value of type string cannot be used as the collection in a 'for' expression.

Is this even possible to accomplish? Thanks.

CodePudding user response:

I think the following should do the job:

locals {
    eks_managed_node_groups = {
        for group_name, group in var.eks_managed_node_groups: 
          group_name => merge(group, {block_device_mappings = {
                for device_name, device in group.block_device_mappings: 
                    device_name => merge(device, 
                             {ebs=merge(device.ebs, {
                                    encrypted = true
                                    kms_key_id = "module.kms.arn"
                                })})
                }})

            }
}

resulting in:

{
  "management_cluster_on_demand" = {
    "additional_tags" = {
      "cluster" = "management_cluster_new"
    }
    "block_device_mappings" = {
      "xvda" = {
        "device_name" = "/dev/xvda"
        "ebs" = {
          "delete_on_termination" = true
          "encrypted" = true
          "kms_key_id" = "module.kms.arn"
          "volume_size" = 50
          "volume_type" = "gp2"
        }
      }
    }
    "capacity_type" = "ON_DEMAND"
    "desired_capacity" = 3
    "instance_types" = [
      "c5.2xlarge",
    ]
    "k8s_labels" = {
      "Environment" = "testing"
      "GithubRepo" = "infrastructure-modules-kubernetes-cluster"
      "GithubSource" = "terraform-aws-modules"
    }
    "max_capacity" = 10
    "min_capacity" = 3
  }
}

I don't have your module.kms.arn, so I just use it as string "module.kms.arn". So you have to change it back to module.kms.arn.

  • Related