blog

12022-04-23

SEAN K.H. LIAO

unified config

If you've written any amount of deployment config for a moderately complex app, you might be familiar with the pattern of: the deployment config being structured, the app config being structured, but embedded as a string within the deployment config. This is unfortunate, since you lose syntax checking etc.

Example, yaml in yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: map1
data:
  config.yaml: |
    foo: bar
    structured:
      config:
        - in
        - a
        - string

Example: json in hcl

resource "aws_iam_policy" "policy" {
  name = "foo"
  policy = <<EOF
    {
      "Version": "1"
      "Statement": [{
        "Action": [
          "ec2:Describe*"
        ]
      }]
    }
  EOF
}

breakout into a file

One solution would be to break things out into their own files, and include the result, each one gets its own filetype, but that doesn't compose well, and if you need templating within the nested config, you now have an incomplete config with invalid syntax. Also, this is very much tied to the tool you're using

Example: helm

apiVersion: v1
kind: ConfigMap
metadata:
  name: map1
data:
  config.yaml: {{ $.Files.Get "config.yaml" }}

Example: terraform

resource "aws_iam_policy" "policy" {
  name = "foo"
  policy = file("policy.json")
}

config conversion

So, if your config language supports it, you can do the conversions inline:

resource "aws_iam_policy" "policy" {
  name = "foo"
  policy = jsonencode({
    Version = "1"
    Statement = [{
      Action = [
        "ec2:Describe*",
      ]
    }]
  })
}

cue

So what do you do? Thankfully, most config tools accept json as input, so instead of writing the You add a level of indirection with cue.

resource: aws_iam_policy: policy: {
  name: "foo"
  policy: json.Marshal({
    Version: "1"
    Action: [
      "ec2:Describe*",
    ]
  })
}
apiVersion: v1
kind: ConfigMap
metadata: name: foo
data: config.yaml: yaml.Marshal({
  foo: bar
  structured: config: [
    "in",
    "a",
    "string",
  ]
})