How can I concatenate a contents of several files into a variable?
Here's the problem: I'm trying to set public keys for a user on a remote machine. The example from the authorized_key documentation that almost works:
- name: Set up authorized_keys for the deploy user
authorized_key: user=deploy
key="{{ item }}"
with_file:
- public_keys/doe-jane
- public_keys/doe-john
But in fact I need to use exclusive=yes
, so after the update all non-provided public keys are removed.
If the exclusive=yes
is provided then only the last public key listed remains in the .ssh/authorized_keys
file (also reported as a bug).
My current approach:
- name: create empty temporary keys file
local_action: "shell > /tmp/auth_keys"
- name: concat keys to temporary file
local_action: "shell echo {{ item }} >> /tmp/auth_keys"
with_file:
- public_keys/doe-jane
- public_keys/doe-john
- name: set up authorized_keys
authorized_key: user=deploy
key="{{ lookup('file', '/tmp/auth_keys') }}"
exclusive=yes
This works but the first two commands always produce "changed". Also I feel there must be a more elegant solution for this.
So, is there a way how to concatenate contents of several files into a variable? Or is there any better approach in general for this task?
There's nothing overly wrong with your first option and then, as your comment mentions, simply using changed_when: False
to acknowledge that this isn't something that you care about the result of it changing is a valid option.
To answer the actual question title you can, as mentioned in the GitHub "issue" you linked, simply concatenate the lookups directly in the task like so:
- name: set up authorized_keys
authorized_key: user=deploy
key="{{ lookup('file', 'public_keys/doe-jane') + lookup('file', 'public_keys/doe-john')}}"
exclusive=yes
However, a cleaner option may be to use the assemble module to concatenate your keys.
This would then change your current approach into something more like:
- name: create concatenated keys file
local_action: "assemble src=roles/ssh_keys/files/ssh_keys/ dest=/tmp/ssh_keys_file"
- name: set up authorized_keys
authorized_key: user=deploy
key="{{ lookup('file', '/tmp/ssh_keys_file' }}"
exclusive=yes
This will only be marked as changed if the destination file has changed at all so running it over and over leaves a lovely wall of green.
This relies on your ssh keys all being files and in the same folder (assemble is typically used for turning conf.d style directories into a single .conf file for programs that don't use the conf.d style configuration) but this is probably the most sensible way of holding them anyway.
The benefit of this is that you can simply add/remove ssh keys from the folder specified and it will be picked up on the next play without any need to add/remove keys being explicitly defined in the task itself as well.