1

I am using Terraform. Terraform has a notion templatefile which can be used to take variables that Terraform has access to (locally supplied or retrieved externally) and to apply them to a Jinja2 template. This specific example is very close to the one in the documentation.

People use these templates to generate cloud-init files with Jinja2 templates. Here is a snipped of the template,

ssh_keys:
    ecdsa_private: "${ssh_ecdsa_key_private}"

Then these variables get set in Terraform, like this,

data "template_file" "user_data" {
  template = templatefile(
    "cloud/cloud.cfg",
    {
      ssh_ecdsa_key_private  = file("./ssh/acme-bitbucket-id_ecdsa")
    }
  )

This is however problematic for me presumably because cloud-init is yaml.

  in "<unicode string>", line 22, column 1:
    "
    ^
could not find expected ':'
  in "<unicode string>", line 24, column 8:
          "-----BEGIN OPENSSH PRIVATE KEY-----
           ^"
2022-03-18 00:20:32,611 - util.py[WARNING]: Failed at merging in cloud config part from part-001
2022-03-18 00:20:32,611 - util.py[DEBUG]: Failed at merging in cloud config part from part-001
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/handlers/cloud_config.py", line 140, in handle_part
    self._merge_part(payload, headers)
  File "/usr/lib/python3/dist-packages/cloudinit/handlers/cloud_config.py", line 116, in _merge_part
    (payload_yaml, my_mergers) = self._extract_mergers(payload, headers)
  File "/usr/lib/python3/dist-packages/cloudinit/handlers/cloud_config.py", line 95, in _extract_mergers
    mergers_yaml = mergers.dict_extract_mergers(payload_yaml)
  File "/usr/lib/python3/dist-packages/cloudinit/mergers/__init__.py", line 79, in dict_extract_mergers
    raw_mergers = config.pop('merge_how', None)
AttributeError: 'NoneType' object has no attribute 'pop'
2022-03-18 00:20:32,616 - __init__.py[DEBUG]: Calling handler CloudConfigPartHandler: [['text/cloud-config', 'text/cloud-config-jsonp']] (__end__, None, 3) with frequency once-per-instance

I believe what's happening here is the file isn't being indented properly. Let's say ./ssh/acme-bitbucket-id_ecdsa looked like this,

-----BEGIN OPENSSH PRIVATE KEY-----
FOO
BAR
BAZ
-----END OPENSSH PRIVATE KEY-----

I think that's getting processed into the template like this,

ssh_keys:
    ecdsa_private: -----BEGIN OPENSSH PRIVATE KEY-----
FOO
BAR
BAZ
-----END OPENSSH PRIVATE KEY-----

What is the way to stop properly produce a cloud-init file with Terraform?

1 Answer 1

0

Here is how I got around it, I declared these as HDL object,

data "template_file" "user_data" {
  template = templatefile(
    "cloud/cloud.cfg",
    {
      ssh_keys = {
        ssh_ecdsa_key_private  = file("./ssh/acme-bitbucket-id_ecdsa")
        ssh_ecdsa_key_public   = file("./ssh/acme-bitbucket-id_ecdsa.pub")
      }
    }
  )
}

And then I pulled it into the yaml file using yamlencode.

There is a bit of documentation that covers this, over at "Generating JSON or YAML from a template"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.