Include variable in expression - yaml

I'm trying to transfer public keys to linux servers using ansible and it's authorized_key module. I thought I use a lookup to read the content of a file and combine it with items.
- name: ensure deployment keys are in authorized keys
authorized_key: user={{ sshaccess_user }} key="{{ lookup('file', '{{ item }}') }}"
with_items: sshaccess_keys
And sshaccess_keys is defined:
sshaccess_keys:
- ~/.ssh/id_rsa.pub
Obviously, I would like to append more than one. The error I get is
fatal: [testbox] => could not locate file in lookup: {{ item }}
It tries to read a file instead of taking the content of item as the filename?

When using with_items you want to use the item variable. You're using items. Fix that and it looks like this should work.

Related

Ansible read csv that has spaces in column names

I am trying to read csv in ansible and the file they are sending me has spaces in column names. Example:
User name
Password
Home phone number
sampleuser
fksdakfjdk
54545646
I have tried to read it using escape symbols and similar but keep getting error. Since i am new to ansible maybe its something obvious that escapes me.
any help is appreciated.
Edit:
this is something similar to what i need
- name: Read users from CSV file and return a dictionary
read_csv:
path: credentials.csv
register: users
delegate_to: localhost
- name: test
command: mkdir /home/{{ item.['User name'] }}
loop: users.list
I see two problems with your playbook.
The first is that you have:
loop: user.list
This is trying to iterate over the literal string value user.list, which is going to fail. You should have:
loop: "{{ user.list }}"
Secondly, you have written:
{{ item.['User name'] }}
This looks like an attempt to combine the dot-style notation (item.key) with the bracket style notation (item[key]). You should write:
{{ item['User name'] }}
To read a dict with ansible, 2 possibility
variable.key
variable['key']
Use the second
- ansible.builtin.debug:
var: variable['Home phone number']

How to substitute values to a conf file using Ansible

I have an ansible playbook that has created a file (/tmp/values.txt) in each server with the following content
1.1.1.1
2.2.2.2
3.3.3.3
4.4.4.4
5.5.5.5
And I have a conf file named etcd.conf in the /tmp/etcd.conf with the following content
and I need to substitute the value of each line from /tmp/values.txt, so /tmp/etcd.conf will look like this:
SELF_IP=1.1.1.1
NODE_1_IP=2.2.2.2
NODE_2_IP=3.3.3.3
NODE_3_IP=4.4.4.4
NODE_4_IP=5.5.5.5
Is there a way I can do this? I used the following lookup method but it only works in the controll server
- name: Create etcd.conf
template:
src: etcd.conf.j2
dest: /tmp/etcd.conf
vars:
my_values: "{{ lookup('file', '/tmp/values.txt').split('\n') }}"
my_vars: [SELF_IP, NODE_1_IP, NODE_2_IP, NODE_3_IP, NODE_4_IP]
my_dict: "{{ dict(my_vars|zip(my_values)) }}"
You can use the slurp: task to grab the content for each machine, or use command: cat /tmp/values.txt and then examine the stdout_lines of its register:-ed variable to achieve that same .split("\n") behavior (I believe you'll still need to use that .split call after | b64decode if you use the slurp approach)
What will likely require some massaging is that you'll need to identify the group (which may very well include all) of inventory hostnames for which that command will produce content, and then grab the hostvar out of them to get all values
Conceptually, similar to [ hostvars[hv].tmp_values.stdout_lines for hv in groups[the_group] ] | join("\n"), but it'll be tedious to write out, so I'd only want to do that if you aren't able to get it to work on your own

Ansible: Reference variable contents from variable name

I am trying to access the contents of a variable, from a variable name. I've used ansible vault to create some passwords, and I am trying to create database users, like so:
postgresql_user:
name: "{{ item }}"
db: "{{ item }}"
login_user: postgres_admin
login_password: '{{postgres_admin}}'
login_host: localhost
login_port: 5433
password: '{{ "{{item}}" }}'
loop:
- artifactory
- bitbucket
- confluence
- crowd
- jira
In this case, I have a database user, which is the variable in the loop. The password for that user, is stored inside the (vault) variable name of that user. In the password: field like I am trying to do a double reference. It doesn't work.
I've tried a few more things, but this is my first run with Ansible and I don't want to go down the wrong path. (I did not include the reference to the vault but it's at the top of the file, and it has been tested with a simpler tasks)
Thanks!
Use lookup plugin vars. For example
password: "{{ lookup('vars', item) }}"
With the introduction of the collections the documentation of the plugins is not available online anymore. See the documentation from the command-line
shell> ansible-doc -t lookup vars
To make the code both more robust and user-friendly, I'd propose to rename the variables with the passwords. For example "artifactory_passwd" etc. Then, in the lookup, create the name of the variable dynamically
password: "{{ lookup('vars', item ~ '_passwd') }}"

Using variables for file name and file contents in lineinfile module

I am trying to read the contents of a file, store these in a variable and then insert them into another file if they don't already exist.
So, how I'm attempting to go about this is as follows:
# Create a variable that represents the path to the file that you want to read from
ssh_public_key_file: '../../jenkins_master/files/{{ hostvars[inventory_hostname]["environment"] }}/id_rsa.pub'
# Create a variable that represents the contents of this file:
ssh_public_key: "{{ lookup('file', '{{ ssh_public_key_file }}') }}"
I then use these variables in my Ansible playbook as follows:
- name: Install SSH authorized key
lineinfile: create=yes dest=~/.ssh/authorized_keys line=" {{ ssh_public_key }}" mode=0644
However, when I try and run the playbook, I get the following error message:
could not locate file in lookup: {{ ssh_public_key_file }}
Can anyone recommend a solution or suggest what I may have done wrong?
Thanks,
Seán
You have to change the line to:
# Create a variable that represents the contents of this file:
ssh_public_key: "{{ lookup('file', ssh_public_key_file) }}"
If you need to concatenate variables and strings you can do it like this:
# Example with two variables
ssh_public_key: "{{ lookup('file', var_1+var_2) }}"
# Example with string and variable
ssh_public_key: "{{ lookup('file', '~/config/'+var_1) }}"
. .
First I would make sure that your ssh_public_key_file variable is set up properly. If you add a task like the following what does it show?
- name: display variable
debug: var=ssh_public_key_file
If the output looks something like this then the variable isn't defined properly (eg. the "environment" fact doesn't exist for the host):
ok: [localhost] => {
"ssh_public_key_file": "../../jenkins_master/files/{{ hostvars[inventory_hostname][\"environment\"] }}/id_rsa.pub"
}
However if everything is defined properly then your output should show the variables replaced with their correct values:
ok: [localhost] => {
"ssh_public_key_file": "../../jenkins_master/files/foo/id_rsa.pub"
}
Once you've verified that then I would do the same thing with your ssh_public_key variable. Just output its value using the debug module. It should display as the contents of the public key file.
One other thing I would strongly suggest is to avoid using lineinfile altogether. Since you're working with SSH keys I would recommend you use the authorized_key module instead. It's a much cleaner way of managing authorized_keys files.

Ansible: Set variable to file content

I'm using the ec2 module with ansible-playbook I want to set a variable to the contents of a file. Here's how I'm currently doing it.
Var with the filename
shell task to cat the file
use the result of the cat to pass to the ec2 module.
Example contents of my playbook.
vars:
amazon_linux_ami: "ami-fb8e9292"
user_data_file: "base-ami-userdata.sh"
tasks:
- name: user_data_contents
shell: cat {{ user_data_file }}
register: user_data_action
- name: launch ec2-instance
local_action:
...
user_data: "{{ user_data_action.stdout }}"
I assume there's a much easier way to do this, but I couldn't find it while searching Ansible docs.
You can use lookups in Ansible in order to get the contents of a file, e.g.
user_data: "{{ lookup('file', user_data_file) }}"
Caveat: This lookup will work with local files, not remote files.
Here's a complete example from the docs:
- hosts: all
vars:
contents: "{{ lookup('file', '/etc/foo.txt') }}"
tasks:
- debug: msg="the value of foo.txt is {{ contents }}"
You can use the slurp module to fetch a file from the remote host: (Thanks to #mlissner for suggesting it)
vars:
amazon_linux_ami: "ami-fb8e9292"
user_data_file: "base-ami-userdata.sh"
tasks:
- name: Load data
slurp:
src: "{{ user_data_file }}"
register: slurped_user_data
- name: Decode data and store as fact # You can skip this if you want to use the right hand side directly...
set_fact:
user_data: "{{ slurped_user_data.content | b64decode }}"
You can use fetch module to copy files from remote hosts to local, and lookup module to read the content of fetched files.
lookup only works on localhost. If you want to retrieve variables from a variables file you made remotely use include_vars: {{ varfile }} . Contents of {{ varfile }} should be a dictionary of the form {"key":"value"}, you will find ansible gives you trouble if you include a space after the colon.

Resources