Ansible when condition always evaluates as false - ansible

I have been trying to get this conditional to work for a few hours now.
The solution is eluding me.
The "when" is always evaluating as false.
This is confusing as template/src works perfectly.
- name: Copy PHP Pool Config
template:
src: "{{ src_conf }}"
dest: /etc/php/{{ php_version }}/fpm/pool.d/{{ user.name }}.conf
mode: u=rw,g=r,o=r
with_flattened:
- "{{ users|default([]) }}"
notify: reload PhpFpm
vars:
user: "{{ item }}"
src_conf: "../files/etc/php/fpm/pool.d/{{ group_names | first }}/{{ user.name }}.conf"
tags:
- php
when: src_conf is exists
This works as expected if I remove the "when".
The issue is not all "{{ user.name }}.conf" files exist.
Does "when: src_conf is exists" search in different place?
Update:
I also tried it with location_action, but it still resulted in false.
- name: Copy PHP Pool Config files
local_action: stat path="../../files/etc/php/fpm/pool.d/{{ group_names | first }}/{{ user.name }}.conf"
register: phpPools
with_flattened:
- "{{ users|default([]) }}"
become: no
vars:
user: "{{ item }}"
tags:
- php
- name: Copy PHP Pool Config
template:
src: item.invocation.module_args.path
dest: /etc/php/{{ php_version }}/fpm/pool.d/{{ user.name }}.conf
mode: u=rw,g=r,o=r
with_flattened:
- "{{ phpPools.results }}"
notify: reload PhpFpm
vars:
user: "{{ item.item }}"
tags:
- php
when: item.stat.exists == true

Related

ansible playbook inline to add multiple lines

i got following pb to add multiple lines to chrony.conf
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: "{{ file_path }}"
insertafter: "{{ line.replace_with }}"
line: "{{ line.line_to_add }}"
with_items:
- { search: "{{ line.replace_with }}", add: "{{ line.line_to_add }}" }
in my vars files I got it like this
line:
line_to_add:
- "server ntp1.domain.com iburst"
- "server ntp2.domain.com iburst"
- "server ntp3.domain.com iburst"
but the change put all 3 ntp servers in one line instead of 3.
any idea?
when i change my yml to
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: "{{ file_path }}"
#regexp: '^(\s*)[#]?{{ item.search }}(: )*'
insertafter: "{{ line.replace_with }}"
line: "{{ item }}"
create: true
loop: "{{ line.line_to_add }}"
with_items:
- { search: "{{ line.replace_with }}", add: "{{ line.line_to_add }}" }
I get suplicate loop in task: items
You can use loop for this to iterate each line in the line.line_to_add variable. I also assumed that you have another line.replace_with variable.
- name: Example of multiple lines
hosts: localhost
gather_facts: no
vars:
line:
line_to_add:
- "server ntp1.domain.com iburst"
- "server ntp2.domain.com iburst"
- "server ntp3.domain.com iburst"
replace_with:
- test_line
tasks:
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: test_file
insertafter: "{{ line.replace_with }}"
line: "{{ item }}"
create: true
loop: "{{ line.line_to_add }}"
Gives:
server ntp1.domain.com iburst
server ntp2.domain.com iburst
server ntp3.domain.com iburst

ansible.utils.unsafe_proxy.AnsibleUnsafeT ext object' has no attribute

I am trying to modify and use this httpd ansible role https://github.com/CentOS/ansible-role-httpd
I'm facing an issue with pki-tls.yml
This piece of code will reproduce the issue I am facing.
---
- name: Copy certificates
hosts: myhost.domain.com
remote_user: user
become: yes
vars:
httpd_vhost_shared_list:
- name: emacs
fqdn: domain.com
path: /var/www/emacs
acl:
- 10.10.40.0/24
pkistore: /home/user/certificates
tasks:
- name: Debug
debug:
var: httpd_vhost_shared_list
- name: TLS certs
copy:
src: "{{ pkistore }}/{{ item.name }}"
dest: "/etc/pki/tls/certs/{{ item.name }}"
with_items:
- "{{ httpd_vhost_shared_list }}.crt"
- "{{ httpd_vhost_shared_list }}-CAChain.crt"
- name: TLS key
copy:
src: "{{ pkistore }}/{{ item.name }}"
dest: "/etc/pki/tls/private/{{ item.name }}"
with_items:
- "{{ httpd_vhost_shared_list }}.key"
When I run my playbook, I get the following error:
The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeT
ext object' has no attribute 'name'
However the variable is defined. How would one do to access name in variable httpd_vhost_shared_list?
Any feedback is welcome.
In the meantime, I figured out it is simple to split the play "TLS certs" in 2 plays. One for the server certificate and another one for chain certificate.
- name: TLS certificate
copy:
src: "{{ pkistore }}/{{ item.name }}.crt"
dest: "/etc/pki/tls/certs/{{ item.name }}.crt"
with_items:
- "{{ httpd_vhost_shared_list }}"
- name: TLS chain
copy:
src: "{{ pkistore }}/{{ item.name }}-CAChain.crt"
dest: "/etc/pki/tls/certs/{{ item.name }}-CAChain.crt"
with_items:
- "{{ httpd_vhost_shared_list }}"
- name: TLS key
copy:
src: "{{ pkistore }}/{{ item.name }}.key"
dest: "/etc/pki/tls/private/{{ item.name }}.key"
with_items:
- "{{ httpd_vhost_shared_list }}"

In Ansible loop, test existence of files from registered results

I have several files that I need to backup in different directories. I have tried the code below and not working for me.
vars:
file_vars:
- {name: /file1}
- {name: /etc/file2}
- {name: /etc/file/file3}
tasks:
- name: "Checking if config files exists"
stat:
path: "{{ item.name }}"
with_items: "{{ file_vars }}"
register: stat_result
- name: Backup Files
copy: src={{ item.name }} dest={{ item.name }}{{ ansible_date_time.date }}.bak
with_items: "{{ file_vars }}"
remote_src: yes
when: stat_result.stat.exists == True
The problem is the condition
when: stat_result.stat.exists == True
There is no attribute stat_result.stat. Instead, the attribute stat_result.results is a list of the results from the loop. It's possible to create a dictionary of files and their statuses. For example
- set_fact:
files_stats: "{{ dict(my_files|zip(my_stats)) }}"
vars:
my_files: "{{ stat_result.results|json_query('[].item.name') }}"
my_stats: "{{ stat_result.results|json_query('[].stat.exists') }}"
Then simply use this dictionary in the condition
when: files_stats[item.name]
Below is a shorter version which creates the dictionary more efficiently
- set_fact:
files_stats: "{{ dict(stat_result.results|
json_query('[].[item.name, stat.exists]')) }}"
Please try using below worked for me:
---
- name: Copy files
hosts: localhost
become: yes
become_user: root
vars_files:
- files.yml
tasks:
- name: "Checking if config files exists"
stat:
path: "{{ item }}"
with_items: "{{ files }}"
register: stat_result
- name: Ansible
debug:
msg: "{{ stat_result }}"
- name: Backup Files
copy:
src: "{{ item }}"
dest: "{{ item.bak }}"
with_items: "{{ files }}"
when: stat_result == "True"
and files.yml will look like:
---
files:
- /tmp/file1
- /tmp/file2
you can check you playbook syntax using below command:
ansible-playbook copy.yml --syntax-check
Also you do dry run your playbook before actual execution.
ansible-playbook -i localhost copy.yml --check

Ansible write result command to local file with loop

I've write ansible-playbook to collect the result from many network devices. Below playbook is working fine. But if I have to collect result with lot of commands. Let say 20 commands, I've to create the many task to write the results into file in my playbook.
For now, I manually create the tasks to write to logs into file. Below is example with 3 commands.
- name: run multiple commands and evaluate the output
hosts: <<network-host>>
gather_facts: no
connection: local
vars:
datetime: "{{ lookup('pipe', 'date +%Y%m%d%H') }}"
backup_dir: "/backup/"
cli:
host: "{{ ansible_host }}"
username: <<username>>
password: <<password>>
tasks:
- sros_command:
commands:
- show version
- show system information
- show port
provider: "{{ cli }}"
register: result
- name: Writing output
local_action:
module: lineinfile
dest: "{{ backup_dir }}/{{ inventory_hostname }}-{{ datetime }}.txt"
line: "{{ inventory_hostname }}:# show version\n{{ result.stdout[0] }}"
create: yes
changed_when: False
- name: Writing output
local_action:
module: lineinfile
dest: "{{ backup_dir }}/{{ inventory_hostname }}-{{ datetime }}.txt"
line: "{{ inventory_hostname }}:# show system information\n{{ result.stdout[1] }}"
create: yes
changed_when: False
- name: Writing output
local_action:
module: lineinfile
dest: "{{ backup_dir }}/{{ inventory_hostname }}-{{ datetime }}.txt"
line: "{{ inventory_hostname }}:# show port\n{{ cmd_result.stdout[2] }}"
create: yes
changed_when: False
Is it possible to loop commands and result within one task?
Please kindly advice.
Thanks
try this one task alone in place above three tasks..
- name: Writing output
local_action:
module: lineinfile
dest: "{{ backup_dir }}/{{ inventory_hostname }}-{{ datetime }}.txt"
line: "{{ inventory_hostname }}:# show {{ item.command }}\n{{ cmd_result.stdout{{ item.outnum }} }}"
create: yes
changed_when: False
with_items:
- { command: version, outnum: [0] }
- { command: system information, outnum: [1] }
- { command: port, outnum: [2] }
Below playbook is worked for me
- name: Writing output
local_action:
module: lineinfile
dest: "{{ backup_dir }}/{{ inventory_hostname }}-{{ datetime }}.txt"
line: "{{ inventory_hostname }}:# show {{ item.command }}\n{{ item.cmdoutput}}"
create: yes
changed_when: False
with_items:
- { command: "version", cmdoutput: "{{ cmd_result.stdout[0] }}" }
- { command: "system information", cmdoutput: "{{ cmd_result.stdout[1] }}" }
- { command: "port", cmdoutput: "{{ cmd_result.stdout[2] }}" }

Ansible: when condition with_items

I have such a part of a playbook, which works fine:
- name: "Copy solrconfig.xml"
copy:
src: "{{role_path}}/files/{{item.path}}"
dest: "{{solr_jmx_config}}/solrconfig.xml"
with_items:
- path: solrconfig_master.xml
when: inventory_hostname == "{{ solr_master }}"
become: yes
become_user: solr
- name: "Copy solrconfig.xml"
copy:
src: "{{role_path}}/files/{{item.path}}"
dest: "{{solr_jmx_config}}/solrconfig.xml"
with_items:
- path: solrconfig_slave.xml
when: inventory_hostname != "{{ solr_master }}"
become: yes
become_user: solr
However, I would like it to look nicer and do something like that:
- name: "Copy solrconfig.xml"
copy:
src: "{{role_path}}/files/{{item.path}}"
dest: "{{solr_jmx_config}}/solrconfig.xml"
with_items:
- path: solrconfig_master.xml -> when: inventory_hostname == "{{ solr_master }}"
- path: solrconfig_slave.xml -> when: inventory_hostname != "{{ solr_master }}"
become: yes
become_user: solr
How to apply "when" condition for each particular item?
Best regards,
Marek
Why do you need with_items and role_path here? Try this:
- name: "Copy solrconfig.xml"
copy:
src: "{{ 'solrconfig_master.xml' if inventory_hostname == solr_master else 'solrconfig_slave.xml' }}"
dest: "{{solr_jmx_config}}/solrconfig.xml"
become: yes
become_user: solr
with_ is generally used for loops, you don't need it for single element.
When you call tasks inside roles, search path for file modules include <role_path>/files/....

Resources