Torsten N.
Torsten N.

Reputation: 2141

Translating complex YAML into .tf

I have the following, relatively complicated piece of YAML:

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: ${aws_iam_role.tf-eks-node.arn}
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes

I now want to translate this into a Terraform-Kubernetes compatible resource, which consists exclusively of String, Lists and Maps. How do I do this? I found an example of how a LimitRange would look here using hyphens to signify a list:

resource "kubernetes_limit_range" "example" {
    metadata {
        name = "terraform-example"
    }
    spec {
        limit {
            type = "Pod"
            max {
                cpu = "200m"
                memory = "1024M"
            }
        }
        limit {
            type = "PersistentVolumeClaim"
            min {
                storage = "24M"
            }
        }
        limit {
            type = "Container"
            default {
                cpu = "50m"
                memory = "24M"
            }
        }
    }
}

My current try for the mapRoles block is as follows:

mapRole { rolearn = "${aws_iam_role.tf-eks-node.arn}"
      username = "system:node:{{EC2PrivateDNSName}}"
      groups = ["system:bootstrappers","system:nodes"]}

This is not correct because mapRoles is a list (because its singular element is a list element as demonstrated by the hyphen); but if it is a list, and everything after the hyphen is the list element, what is the list title?

using the idea mentioned in an answer, I tried to put the metadata block in a data-block beforehand:

data "template_file" "map_roles" {
  template = <<EOF
- rolearn: ${var.arn}
  username: system:node:{{EC2PrivateDNSName}}
  groups:
    - system:bootstrappers
    - system:nodes
EOF

  vars {
    arn = "${var.kube-arn}"
  }
}

resource "kubernetes_config_map" "aws_auth" {
  metadata {
    name = "aws-auth"
    namespace = "kube-system"
  }
  data {
    mapRoles = "${data.template_file.map_roles.template}"
  } 
}

Upvotes: 1

Views: 2325

Answers (4)

ted-k42
ted-k42

Reputation: 446

As a reference for anyone looking to loop through variables (with the new for syntax), I had success with setting up the aws-auth configmap object below:

resource "kubernetes_config_map" "aws-auth" {
  metadata {
    name = "aws-auth"
    namespace = "kube-system"
  }

  data = {
    mapRoles = local.config_map_aws_auth
  }
}

locals {
  config_map_aws_auth = yamlencode(
  concat([
    {
      "rolearn": aws_iam_role.nodes-assume-role.arn,
      "username": "system:node:{{EC2PrivateDNSName}}",
      "groups": [
        "system:bootstrappers",
        "system:nodes"
      ]
    }
  ],
  [
    for team in var.teams :
    {
      "rolearn": "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${team}-readonly",
      "username": "${team}_readonly",
      "groups": [
        "view"
      ]
    }
  ])
  )
}

Upvotes: 0

Torsten N.
Torsten N.

Reputation: 2141

Managed to make it work with some changes to David Maze's answer:

resource "kubernetes_config_map" "aws_auth" {
  metadata {
    name = "aws-auth"
    namespace = "kube-system"
  }
  data {
    mapRoles = <<EOF
- rolearn: ${var.kube-arn}
  username: system:node:{{EC2PrivateDNSName}}
  groups:
    - system:bootstrappers
    - system:nodes
EOF
  } 
}

The idea of putting the |-input into an EOF-block is what I was missing. Terraform can resolve variable input directly in that block, so I didn't even need a data block to set the template up first.

Upvotes: 1

David Maze
David Maze

Reputation: 159865

The first step is to find a Terraform resource type that matches what you're looking for. The Terraform Kubernetes provider has historically been a little sparse but now does include basic objects like Deployments and ConfigMaps. (Not DaemonSets, though.)

As @Rico notes in their answer, the data: of a ConfigMap is just a map from string name to string value, and your example uses a YAML multi-line string syntax. HCL has a different syntax that looks like shell here-documents. To do the interpolation you also need to feed it through a template. So you should be able to translate this to:

data "template_file" "map_roles" {
  template = <<EOF
- rolearn: ${arn}
  username: system:node:{{EC2PrivateDNSName}}
  groups:
    - system:bootstrappers
    - system:nodes
EOF

  vars {
    arn = ${aws_iam_role.tf-eks-node.arn}
  }
}

resource "kubernetes_config_map" "aws_auth" {
  metadata {
    name = "aws-auth"
    namespace = "kube-system"
  }
  data {
    mapRoles = ${data.template_file.map_roles}
  } 
}

Upvotes: 1

Rico
Rico

Reputation: 61689

So when you have this in YAML:

data:
  mapRoles: |

it means that everything after the | is a string that is the value of mapRoles. I'm not really sure that's what you want. If you want lists of lists you would want something like this:

data:
  mapRoles:
  - rolearn: ${aws_iam_role.tf-eks-node.arn}
  - username: system:node:{{EC2PrivateDNSName}}
  - groups:
    - system:bootstrappers
    - system:nodes

This would translate into HCL to this:

"data" = {
  "mapRoles" = {
    "rolearn" = "${aws_iam_role.tf-eks-node.arn}"
  }

  "mapRoles" = {
    "username" = "system:node:{{EC2PrivateDNSName}}"
  }

  "mapRoles" = {
    "groups" = ["system:bootstrappers", "system:nodes"]
  }
}

Upvotes: 1

Related Questions