Data from vault with with_items groups - ansible

I have a task that generates my configuration from jinja2 to conf.
- name: check password
set_fact:
my_secrets: "{{ lookup('hashi_vault', 'secret=kv/{{ stage }}.d/{{ app }}/{{ item }}/secrets token={{ token }} url={{ url }} validate_certs={{ validate_certs }}')}}"
with_items: "{{ groups['ns'] }}"
- name: copy config powerdns_auth pdns.local.gmysql.conf
template:
src: ../../../update/ns/templates/etc/powerdns/pdns.d/pdns.local.gmysql.conf.j2
dest: ../../../config/{{ stage }}/{{ item }}/etc/powerdns/pdns.d/pdns.local.gmysql.conf
mode: '0644'
with_items: "{{ groups['ns'] }}"
in pdns.local.gmysql.conf.j2
gmysql-password={{ my_secrets.user_password_mysql }}
I have a problem because it saves me the from vault password from the last host to a file.
Is it possible to set the fact depending on the host?

Don't loop over groups, use the "natural" play loop on hosts and delegate the needed tasks to localhost.
Note: I kept your relative paths in the template tasks but it looks ugly and will break one day or an other.
Note2: "moustaches don't stack" => I fixed your code (there are other ways to fix it...) where it was incorrect when fetching from hashicorp vault.
- name: Create config files per hosts
hosts: ns
gather_facts: false
vars:
# All your needed vars that I will not define here for this example
tasks:
- name: check password
vars:
secret: "kv/{{ stage }}.d/{{ app }}/{{ inventory_hostname }}/secrets"
hashi_string: "secret={{ secret }} token={{ token }} url={{ url }} validate_certs={{ validate_certs }}"
set_fact:
my_secrets: "{{ lookup('hashi_vault', hashi_string) }}"
- name: copy config powerdns_auth pdns.local.gmysql.conf
template:
src: ../../../update/ns/templates/etc/powerdns/pdns.d/pdns.local.gmysql.conf.j2
dest: ../../../config/{{ stage }}/{{ inventory_hostname }}/etc/powerdns/pdns.d/pdns.local.gmysql.conf
mode: '0644'
delegate_to: localhost

Related

Ansbile issue replacing variables

I am new to ansible and I am using variables to use awx polls, the case is that when I want to use these variables in the get_url task
- name: Download Artifact
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"
When I launch an ansible-playbook from my local I get this error
The offending line appears to be:
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Does anyone know what can be due?
I think the problem is with the missing url key (docs)
Try the following
- name: Download Artifact
get_url:
url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"

Ansible: Delete interfaces that are not in my host_vars

I've an ansible playbook that creates l3_subinterfaces on a Palo Alto firewall, the creating is based on the host_vars of the firewall.
- l3_subinterfaces:
- tag: "9"
vr_name: "vr_production"
ip: "10.0.9.2/24"
comment: "VLAN9 Subinterface"
parent_if: "ethernet1/1"
zone: "Infrastructuur"
- tag: "13"
vr_name: "vr_production"
ip: "10.0.13.2/24"
comment: "VLAN13 Subinterface"
parent_if: "ethernet1/2"
zone: "Infrastructuur"
And the playbook task which create the interfaces:
- name: Configure l3_subinterfaces
panos_l3_subinterface:
provider: "{{ panos_provider }}"
name: "{{ item.parent_if }}.{{ item.tag }}"
tag: "{{ item.tag }}"
ip: ["{{ item.ip }}"]
vr_name: "{{ item.vr_name }}"
zone_name: "{{ item.zone }}"
comment: "{{ item.comment }}"
enable_dhcp: false
with_items:
- "{{ l3_subinterfaces }}"
when: l3_subinterfaces is defined
So at this point everything is working fine. However the thing I'm trying to achieve is holding the state of the firewall in the Ansible inventory.
So for example I'm now delete the l3_subinterface with tag 13 and run the task again, it still have the l3_subinterface with tag 13 configured on the Palo Alto firewall.
I'm trying to figure out how I can delete the l3_subinterfaces which exists on the firewall, but doesn't exists in my host_vars. I think I need to compare something like te facts with the host_vars, but really have no clue how to do it.
Actually I've already found my own answer. The solution is to compare the list l3_subinterfaces against the palo alto interfaces:
- name: Get interfaces facts
panos_facts:
provider: '{{ panos_provider }}'
gather_subset: ['interfaces']
- name: Delete unused l3_subinterfaces
panos_l3_subinterface:
provider: "{{ panos_provider }}"
name: "{{ item }}"
tag: "{{ item|regex_search('\\d+$') }}"
state: "absent"
with_items:
- "{{ ansible_net_interfaces|selectattr('tag', 'defined')|map(attribute='name')|list | difference(l3_subinterfaces|map(attribute='name')|list) }}"

Sync files between 2 hosts using ansible

I'm looking for a way to sync files between 2 hosts in ansible. The scenario is as follows. I have a CSV file which contains 3 columns indicating directories which needs to be synced between 2 servers. the first 2 columns indicate the source and target servers and the third column indicates the directory
source, target, directory
src01, tgt02, dir0003
src02, tgt05, dir0004
src10, tgt68, dir1022
I found this answer for syncing files between 2 hosts - How to copy files between two nodes using ansible
Is there any way to parameterize this using a csv config file?
Yes. It's possible. In the first play read the CSV file and create group of targets. Use the new group in the second play and loop the synchronize module. For example the playbook
- hosts: localhost
tasks:
- read_csv:
path: db.csv
register: my_db
- add_host:
hostname: "{{ item.target }}"
groups: my_targets
my_list: "{{ my_db.list }}"
loop: "{{ my_db.list }}"
- hosts: my_targets
tasks:
- debug:
msg: "Copy {{ item.directory }} from {{ item.source }} to {{ inventory_hostname }}"
loop: "{{ my_list|json_query(query) }}"
vars:
query: "[?target == '{{ inventory_hostname }}']"
- name: Copy
synchronize:
src: "{{ item.directory }}"
dest: "{{ item.directory }}"
delegate_to: "{{ item.source }}"
loop: "{{ my_list|json_query(query) }}"
vars:
query: "[?target == '{{ inventory_hostname }}']"
(not tested)
gives
"msg": "Copy dir0004 from src02 to tgt05"
"msg": "Copy dir0003 from src01 to tgt02"
"msg": "Copy dir1022 from src10 to tgt68"

Can we have 2 with_items in ansible in a single task

Below is the condition
- name: Find the image
slurp:
src: "{{ IMAGE }}"
register: slurp_results
- name: Upload image
shell: |
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/TESTIMAGE
with_items: "{{ (slurp_results.content|b64decode).splitlines() }}"
The above code works.
But I would need "TESTIMAGE" also to be replaced as {{ item }} like below.
skopeo copy -docker-archive:{{ item }}.tar docker://{{ URL }}/{{ item }}
How to define 2 with_items in a single shell task with 2 different slurp results
I believe you can by using the subelements module. Here is a link. Try going by this example:
- name: Setup MySQL users, given the mysql hosts and privs subkey lists
mysql_user:
name: "{{ item.0.name }}"
password: "{{ item.0.mysql.password }}"
host: "{{ item.1 }}"
priv: "{{ item.0.mysql.privs | join('/') }}"
with_subelements:
- "{{ users }}"
- mysql.hosts
Users is referred to as item.0 and hosts as item.1 and so on.

printing the host name from group in inventory

I have below inventory file:
[web]
10.0.1.0
[db]
10.0.3.0
[frontend]
10.0.5.0
[X_all:children]
web
db
frontend
Now in my playbook: I'm trying to print the hostname under X_all group in the name line.
- name: "Copying the output of Registry run to local machine from {{ hostvars[item]['inventory_hostname'] }}"
become: true
become_user: "{{ login }}"
fetch:
src: /tmp/DeploymentRegistry.txt
dest: /tmp/DeploymentRegistry-{{ inventory_hostname }}.txt
flat: yes
with_items:
- "{{ groups['X_all'] }}"
Is it even possible to add the hostname in the name line?
I tried replacing {{ hostvars[item]['inventory_hostname'] }} with inventory_hostname but it's also not working.
Regarding your requirement
I'm trying to print the hostname under test group in the name line.
take note that the group has more than one member and therefore more than one hostname, but a list of hostnames.
- name: Show hosts {{ groups['test'] }}
delegate_to: localhost
debug:
msg: "{{ item }}" # will show the group member hostname(s)
with_items:
- "{{ groups['test'] }}"
Is it even possible to add the hostname in the name line? I tried ... with inventory_hostname but it's also not working.
Yes, it is.
- name: Show host {{ inventory_hostname }}
debug:
msg: "{{ item }}"
with_items:
- "{{ groups['test'] }}"
But it will print the first hostname from list only.

Resources