Variable declaration that allows dynamic list of aws EBS Volumes & Network Interfaces. (Newbie questions on correct approach)

Good Afternoon Everyone!

I hope everyone is doing well, excited to be making my first post :slight_smile: So I have recently been tasked with learning and rejiggering our environments half integration of Terraform. After some consultation with the Change Management Board (CMB), they would like us to “simplify” how we document what systems are deploying to make the change management process easier for the non-technical staff on the board.

Ok so my idea is as follows: We have 3 environments (dev, test, prod) and we have a separate repo for each application. In that repo, we have 3 seperate folders, one for each environment where we have a single vars file where we define all our systems, and I am trying to make it as inclusive of all the properties associated with the AMI as possible, but that is giving me some troubles and I am unsure how exactly to proceed, if at all. I want to allow dynamic declaration of “ebs_block_devices” and “network_interfaces” and attach them dynamically.

My thoughts…

  • I feel that it might be best to create a pre-calculated object with key/value that collects all of the say network_interfaces, but after the last 2 days I can’t quite get a working object that is able to build the necessary object because the resulting object is searching across multiple layers. (i.e. grabbing the region/availability zone from the “system” object, but also iterating through the say EBS or network interface objects.
  • second problem I see is while you can have a for_each in the aws ami resource group, I don’t see how to dynamically attach all of these calculated objects (granted, I haven’t researched this much yet because I am struggling with the first task)

Thank you for everyone taking a moment to read my post and more so to anyone able/willing to give me some direction!

Working Configuration

variable "all_systems" {
  description = ""

  type = list(
    object({
      /* Required Parameters */
      region                 = string
      hostname               = string
      availability_zone      = string
      private_ip           = string
      vpc_security_group_ids = list(string)

      /* Optional Parameters */
      ami                    = optional(string)
      instance_type          = optional(string, "m6i.large")
      get_password_data      = optional(bool, true)

      root_block_device = optional(
        object({
          volume_type           = optional(string, "gp3") 
          volume_size           = optional(string, "100")
          delete_on_termination = optional(bool, true)
          iops                  = optional(string)
          throughput            = optional(string)
          tags                  = optional(object)
        })
      )

      tags = optional(
        object({
          OS                      = optional(string, "Red Hat Enterprise Linux 8")
          #Name                   = Calculated automatically from parent object
          Backup                  = optional(bool, false)
          Function                = optional(string, "AMI Builder")
          Terraform               = optional(bool, True)
          #Environment            = Calculated automatically from parent object
        })
      )
    })
  )
}

Desired “Dynamic” configuration.

variable "all_systems" {
  description = ""

  type = list(
    object({
      /* Required Parameters */
      region                 = string
      hostname               = string
      availability_zone      = string
      vpc_security_group_ids = list(string)

      /* Optional Parameters */
      ami                    = optional(string)
      instance_type          = optional(string, "m6i.large")
      get_password_data      = optional(bool, true)

      root_block_device = optional(
        object({
          volume_type           = optional(string, "gp3") 
          volume_size           = optional(string, "100")
          delete_on_termination = optional(bool, true)
          iops                  = optional(string)
          throughput            = optional(string)
          tags                  = optional(object)
        })
      )

      ebs_block_device = optional(
        list(
          object({
            volume_type           = optional(string, "gp3") 
            volume_size           = optional(string, "100")
            delete_on_termination = optional(bool, false)
            device_name           = optional(string, "/dev/xvdf")
            tags                  = optional(object)
          })
        )
      )

      network_interfaces = list(
        object({
          #subnet_ip              = Calculated automatically from parent object
          #region                 = Calculated automatically from parent object
          description             = optional(string)
          interface_type          = optional(string)
          private_ips             = list(string)
          security_groups         = optional(list(string))
          tags                    = optional(object)
        })
      )

      tags = optional(
        object({
          OS                      = optional(string, "Red Hat Enterprise Linux 8")
          #Name                   = Calculated automatically from parent object
          Backup                  = optional(bool, false)
          Function                = optional(string, "AMI Builder")
          Terraform               = optional(bool, True)
          #Environment            = Calculated automatically from parent object
        })
      )
    })
  )
}