PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, December 21, 2022

[FIXED] How to use locals in terraform to repeat and merge blocks?

 December 21, 2022     syntax, terraform     No comments   

Issue

I have multiple docker_container resources:

resource "docker_container" "headerdebug" {
  name  = "headerdebug"
  image = "${docker_image.headerdebug.latest}"

  labels {
    "traefik.frontend.rule" = "Host:debug.in.bb8.fun"
    "traefik.port" = 8080
    "traefik.enable" = "true"
    "traefik.frontend.passHostHeader" = "true"
    "traefik.frontend.headers.SSLTemporaryRedirect" = "true"
    "traefik.frontend.headers.STSSeconds" = "2592000"
    "traefik.frontend.headers.STSIncludeSubdomains" = "false"
    "traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
    "traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
  }
}

And another one:

resource "docker_container" "cadvisor" {
  name  = "cadvisor"
  image = "${docker_image.cadvisor.latest}"

  labels {
    "traefik.frontend.rule" = "Host:cadvisor.bb8.fun"
    "traefik.port" = 8080
    "traefik.enable" = "true"
    "traefik.frontend.headers.SSLTemporaryRedirect" = "true"
    "traefik.frontend.headers.STSSeconds" = "2592000"
    "traefik.frontend.headers.STSIncludeSubdomains" = "false"
    "traefik.frontend.headers.contentTypeNosniff" = "true"
    "traefik.frontend.headers.browserXSSFilter" = "true"
    "traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
    "traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
  }
}

I'm trying to use locals to re-use the common labels between both the containers. I have the following local defined:

locals {
  traefik_common_labels {
    "traefik.frontend.passHostHeader" = "true"
    "traefik.frontend.headers.SSLTemporaryRedirect" = "true"
    "traefik.frontend.headers.STSSeconds" = "2592000"
    "traefik.frontend.headers.STSIncludeSubdomains" = "false"
    "traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
    "traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
  }
}

But the documentation doesn't mention how to use locals for merging entire blocks, only maps.

I've tried the following:

labels "${merge(
    local.traefik_common_labels,
    map(
      "traefik.frontend.rule", "Host:debug.in.bb8.fun",
      "traefik.port", 8080,
      "traefik.enable", "true",
    )
  )}"

which gives the following error:

tf11 plan

Error: Failed to load root config module: Error loading modules: module docker: Error parsing .terraform/modules/2f3785083ce0d0ac2dd3346cf129e795/main.tf: key 'labels "${merge(
    local.traefik_common_labels,
    map(
      "traefik.frontend.rule", "Host:debug.in.bb8.fun",
      "traefik.port", 8080,
      "traefik.enable", "true",
    )
  )}"' expected start of object ('{') or assignment ('=')

There is a pretty diff of my attempts at this PR: https://git.captnemo.in/nemo/nebula/pulls/4/files


Solution

In Terraform 1.x+ you can use a dynamic block to achieve this

variable "xpoweredby" { default = "" }
variable "xfo_allow" { default = "" }

locals {
  traefik_common_labels = {
    "traefik.frontend.passHostHeader"                  = "true"
    "traefik.frontend.headers.SSLTemporaryRedirect"    = "true"
    "traefik.frontend.headers.STSSeconds"              = "2592000"
    "traefik.frontend.headers.STSIncludeSubdomains"    = "false"
    "traefik.frontend.headers.customResponseHeaders"   = var.xpoweredby
    "traefik.frontend.headers.customFrameOptionsValue" = var.xfo_allow
  }
}

resource "docker_image" "cadvisor" {
  name = "google/cadvisor:latest"
}

resource "docker_container" "cadvisor" {
  name  = "cadvisor"
  image = docker_image.cadvisor.latest

  dynamic "labels" {
    for_each = merge(local.traefik_common_labels,
      {
        "traefik.frontend.rule" = "Host:debug.in.bb8.fun",
        "traefik.port"          = 8080,
        "traefik.enable"        = "true",
      }
    )

    content {
      label = labels.key
      value = labels.value
    }
  }
}

In Terraform 0.11 etc, this could be accomplised with the following:

You need to assign the value to labels like so

locals {
  traefik_common_labels {
    "traefik.frontend.passHostHeader"                  = "true"
    "traefik.frontend.headers.SSLTemporaryRedirect"    = "true"
    "traefik.frontend.headers.STSSeconds"              = "2592000"
    "traefik.frontend.headers.STSIncludeSubdomains"    = "false"
    "traefik.frontend.headers.customResponseHeaders"   = "${var.xpoweredby}"
    "traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
  }
}

resource "docker_container" "cadvisor" {
  name  = "cadvisor"
  image = "${docker_image.cadvisor.latest}"

  labels = "${merge(
    local.traefik_common_labels,
    map(
      "traefik.frontend.rule", "Host:debug.in.bb8.fun",
      "traefik.port", 8080,
      "traefik.enable", "true",
    ))}"
}


Answered By - Conor Mongey
Answer Checked By - Robin (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing