ossentoo
ossentoo

Reputation: 2019

Azure Container Instance with Terraform - multiple secrets volumes

I've got the following Terraform code to deploy Azure Container Instances from some json variable:

resource "azurerm_container_group" "aci" {
  count               = length(var.ContainerInstances)
  name                = var.ContainerInstances[count.index].Name
  resource_group_name = var.ContainerInstances[count.index].ResourceGroup
  location            = var.ContainerInstances[count.index].Location
  dns_name_label      = var.ContainerInstances[count.index].DnsNameLabel
  os_type             = var.ContainerInstances[count.index].OsType
  tags                = merge(var.workspace_tags, var.ContainerInstances[count.index].Tags)
  ip_address_type     = var.ContainerInstances[count.index].IpAddressType

  dynamic "container" {

    for_each = [for k, v in var.ContainerInstances[count.index].Containers :
      {
        name     = lookup(v, "Name", "")
        image    = lookup(v, "Image", "")
        cpu      = lookup(v, "Cpu", "")
        memory   = lookup(v, "Memory", "")
        port     = lookup(v, "Port", "")
        protocol = lookup(v, "Protocol", "")

        environmentvariables         = lookup(v, "EnvironmentVariables", "")
        secure_environment_variables = lookup(v, "SecureEnvironmentVariables", "")
        volumes                      = lookup(v, "Volumes", {})
      }
    ]

    content {
      name   = container.value.name
      image  = container.value.image
      cpu    = container.value.cpu
      memory = container.value.memory

      ports {
        port     = container.value.port
        protocol = container.value.protocol
      }

      environment_variables        = container.value.environmentvariables
      secure_environment_variables = container.value.secure_environment_variables

      dynamic "volume" {

          for_each = [for x in container.value.volumes :
            {
              name      = lookup(x, "Name", "")
              mountpath = lookup(x, "MountPath", "")
              readonly  = lookup(x, "ReadOnly", "")
              secrets   = { for key, value in lookup(x, "Secrets", {}) : value => base64encode(value) }
            }
          ]

          content {
            name       = volume.value.name
            mount_path = volume.value.mountpath
            read_only  = volume.value.readonly

            secret = volume.value.secrets
          }
      }
    }
  }
}

Basically, i need to add multiple volumes with secrets into each ACI. Each volumes secrets and mount point with be slightly different, so i don't think i can have all the values in one volume.

Here's a full example: https://github.com/ossentoo/terraform-aci-volumes/blob/main/aci.tf

The problem is, when i run this example code with terraform apply, it runs endlessly and doesn't complete. If i go to the Azure portal after around 5 mins of run time, i see that the ACI has been created, but it is unhealthy. Therefore, it seems like there's something wrong with my config. Can you see any problem with it?

When i try and run this example by first commenting out the dynamic volume section of config, the aci does get created. So i'm pretty sure the issue is with the dynamic code.

Upvotes: 0

Views: 1493

Answers (1)

Ansuman Bal
Ansuman Bal

Reputation: 11421

I tried the same in my environment , using the variables , I also faced the same issue but hardcoding it succeeds.

The issue was in the For_each secrets argument that you are using in dynamic volume :

secrets = { for key, value in lookup(x, "Secrets", {}) : value => base64encode(value) }

Instead of the value in secrets in the above you have to use key as below :

secrets = { for key, value in lookup(x, "Secrets", {}) : key => base64encode(value).

Test code (from the GitHub Example you have shared) after editing:

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "aci-rg" {
  name     = var.ContainerInstances.ResourceGroup
  location = var.ContainerInstances.Location
}

resource "azurerm_container_group" "aci" {
  name                = var.ContainerInstances.Name
  resource_group_name = var.ContainerInstances.ResourceGroup
  location            = var.ContainerInstances.Location
  dns_name_label      = var.ContainerInstances.DnsNameLabel
  os_type             = var.ContainerInstances.OsType
  ip_address_type     = var.ContainerInstances.IpAddressType

  container {

    name   = var.ContainerInstances.Container.Name
    image  = var.ContainerInstances.Container.Image
    cpu    = var.ContainerInstances.Container.Cpu
    memory = var.ContainerInstances.Container.Memory

    environment_variables        = var.ContainerInstances.Container.EnvironmentVariables
    secure_environment_variables = var.ContainerInstances.Container.SecureEnvironmentVariables

    ports {
      port     = var.ContainerInstances.Container.Port
      protocol = var.ContainerInstances.Container.Protocol
    }

    dynamic "volume" {

      for_each = [for x in var.ContainerInstances.Container.Volumes :
        {
          name      = lookup(x, "Name", "")
          mountpath = lookup(x, "MountPath", "")
          readonly  = lookup(x, "ReadOnly", "")
          secrets   = { for key, value in lookup(x, "Secrets", {}) : key => base64encode(value) }
        }
      ]

      content {
        name       = volume.value.name
        mount_path = volume.value.mountpath
        read_only  = volume.value.readonly
        secret = volume.value.secrets
      }
    }
  }
  depends_on = [
    azurerm_resource_group.aci-rg
  ]
}

Output:

enter image description here

enter image description here

enter image description here

Upvotes: 1

Related Questions