0

In other words, I want the content from an Ansible variable to be written to a particular "column" in a config file, and I don't want that content to be wrapped.

The task:

- name: build cloud-init file
  local_action:
    module: ansible.builtin.template
    src: cloud_config.j2
    dest: ./cloud_config.yml
    mode: 0640
  tags: ['containers', 'containers:configuration']

The variable, which lives in a vault file:

machineuser_key: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
    ...

The template:

write_files:
{# ssh config to allow our deployment user to fetch the Ansible repo #}
{# See https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users #}
- path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
  permissions: 600
  owner: {{ gcp_deploy_user }}
  content: |
    {{ machineuser_key }} 

The output of that template task:

write_files:
- path: /home/omegasphinx/.ssh/omegasphinx_github_rsa
  permissions: 600
  owner: omegasphinx
  content: |
    -----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
...

I know that blockinfile is a recommended module when one wants to write a config file, and that I should use the "Block Indication Indicator" to do this. But when I do these things, it still wraps the content of the ssh key. That blockinfile task looks like this:

- name: add ssh private key to cloud-init file
  local_action:
    module: ansible.builtin.blockinfile
    path: cloud_config.yml
    mode: 0440
    insertafter: "# machineuser_ssh_block"
    block: |2
      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: |
          {{ machineuser_key }}
  tags: ['containers', 'containers:configuration']

And the .j2 template looks like this:

write_files:
# machineuser_ssh_block

The output then looks like this (exactly the same):

write_files:
 - path: /home/omegasphinx/.ssh/omegasphinx_github_rsa
  permissions: 600
  owner: omegasphinx
  content: |
    -----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
...

Other things I've tried:

  • I disable tabs-to-spaces in my editor and then added tabs before each line of the ssh key in the machineuser_key variable

  • The docs say "You can manually disable the lstrip_blocks behavior by putting a plus sign (+) at the start of a block"; so I added a block and then indented the variable inside the block:

  {%+ if machineuser_key is defined %}
    {{ machineuser_key }} 
  {% endif %}

My understanding of whitespace in Jinja2:

To give you some context on what I'm expecting to happen. The "Whitespace Control" section of the Jinja docs states that "a single trailing newline is stripped if present" but "other whitespace (spaces, tabs, newlines etc.) is returned unchanged." In my case, I have "other whitespace": spaces to the left of each line of the variable machineuser_key. But obviously I'm missing something.

Brian Dant
  • 4,029
  • 6
  • 33
  • 47

1 Answers1

2

As far as I can tell from your question, it's not jinja whitespace control that's jamming up your outcome, it's the fact that machineuser_key itself has embedded newlines; a lot of helm charts have the same problem, which allows you to take advantage of the same work-arounds:

  • take advantage of the fact that YAML is a superset of JSON
  • use the indent filter to get you and the YAML block on the same page

JSON as YAML approach

      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: {{ machineuser_key | to_json }}

resulting in

        owner: gcpawesomeuser
        content: "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nETC ETC ETC\n"

Using the indent filter

      - path: /home/{{ gcp_deploy_user }}/.ssh/{{ gcp_deploy_user}}_github_rsa
        permissions: 600
        owner: {{ gcp_deploy_user }}
        content: |
          {{ machineuser_key | indent(2) }}
# with the (2) matching the number of spaces under "content" where the mustaches start

producing:

        owner: gcpawesomeuser
        content: |
          -----BEGIN OPENSSH PRIVATE KEY-----
          b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
          ETC ETC ETC
mdaniel
  • 31,240
  • 5
  • 55
  • 58