Issue
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
variableThe 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.
Solution
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
Answered By - mdaniel