Terraform: YAML file rendering issue in storage section of container linux config of flatcar OS

453 Views Asked by At

I am trying to generate a file by template rendering to pass to the user data of the ec2 instance. I am using the third party terraform provider to generate an ignition file from the YAML.

data "ct_config" "worker" {
  content      = data.template_file.file.rendered
  strict       = true
  pretty_print = true
}
data "template_file" "file" {
  ...
  ...
  template = file("${path.module}/example.yml")
  vars = {
    script = file("${path.module}/script.sh")
  }
}

example.yml

storage:
  files:
    - path: "/opt/bin/script"
      mode: 0755
      contents: 
        inline: |
          ${script}

Error:

Error: Error unmarshaling yaml: yaml: line 187: could not find expected ':'

  on ../../modules/launch_template/launch_template.tf line 22, in data "ct_config" "worker":
  22: data "ct_config" "worker" {

If I change ${script} to sample data then it works. Also, No matter what I put in the script.sh I am getting the same error.

2

There are 2 best solutions below

3
Alain O'Dea On BEST ANSWER

You want this outcome (pseudocode):

storage:
  files:
    - path: "/opt/bin/script"
      mode: 0755
      contents: 
        inline: |
          {{content of script file}}

In your current implementation, all lines after the first loaded from script.sh will not be indented and will not be interpreted as desired (the entire script.sh content) by a YAML decoder.

Using indent you can correct the indentation and using the newer templatefile functuin you can use a slightly cleaner setup for the template:

data "ct_config" "worker" {
  content      = local.ct_config_content
  strict       = true
  pretty_print = true
}

locals {
  ct_config_content = templatefile("${path.module}/example.yml", {
    script = indent(10, file("${path.module}/script.sh"))
  })
}

For clarity, here is the example.yml template file (from the original question) to use with the code above:

storage:
  files:
    - path: "/opt/bin/script"
      mode: 0755
      contents: 
        inline: |
          ${script}
0
admdrew On

I had this exact issue with ct_config, and figured it out today. You need to base64encode your script to ensure it's written correctly without newlines - without that, newlines in your script will make it to CT, which attempts to build an Ignition file, which cannot have newlines, causing the error you ran into originally.

Once encoded, you then just need to tell CT to !!binary the file to ensure Ignition correctly base64 decodes it on deploy:

data "template_file" "file" {
  ...
  ...
  template = file("${path.module}/example.yml")
  vars = {
    script = base64encode(file("${path.module}/script.sh"))
  }
}
storage:
  files:
    - path: "/opt/bin/script"
      mode: 0755
      contents: 
        inline: !!binary |
          ${script}