How to get the list of remote files under a Dir and iterate over to list out the contents via ansible - ansible-2.x

Does anyone knows how to get the list of remote files under a particular Dir and to iterate over them and list out the contents of each file via ansible?
For example , i have a location /var/spool/cron and it has many files which i need to cat <file> by iterate over each of them.
fileglob and lookup works locally.
Below is the play but not working as expected.
---
- name: Playbook to quick check the cron jobs for user
hosts: all
remote_user: root
gather_facts: False
tasks:
- name: cron state
shell: |
ls /var/spool/cron/
register: cron_status
- debug: var=item
with_items:
- "{{ cron_status.stdout_lines }}"

Try this as an example
---
- name: Playbook
hosts: all
become: root
gather_facts: False
tasks:
- name: run ls-
shell: |
ls -d1 /etc/cron.d/*
register: cron_status
- name: cat files
shell: cat {{ item }}
register: files_cat
with_items:
- "{{ cron_status.stdout_lines }}"
- debug: var=item
with_items:
- "{{ files_cat.results| map(attribute='stdout_lines')|list }}"

Just for the sake you someones Intrest..
Below Play will give you more cleaner stdout
---
- name: hostname
hosts: all
become: root
gather_facts: False
tasks:
- name: checking cron entries
shell: more /var/spool/cron/*
register: cron_status
- debug: var=cron_status.stdout_lines

Related

Ansible find only files which have changed

I'm trying to look for a pattern in Postgres configuration files, and
only wants to find changed files that match the search pattern.
---
- name: Query postgres pattern matched files
hosts: pghosts
gather_facts: false
tasks:
- name: "Find postgres conf files"
find:
paths: "/srv/postgresql/config/conf.d"
patterns: "*.conf"
file_type: "file"
register: search_files
- name: "grep postgres conf files with searchpattern"
shell: "grep -i 'pg_show_plans' {{ item.path | basename }}"
args:
chdir: "/srv/postgresql/config/conf.d"
loop: "{{ search_files.files }}"
loop_control:
label: "{{ item.path | basename }}"
ignore_errors: true
- name: "find changed files"
debug:
msg: "{{ search_files.files |map(attribute='path') }}"
These are the changed files:
changed: [pgsql14.techlab.local] => (item=00_global_default.conf)
...ignoring
changed: [pgsql13.techlab.local] => (item=00_global_default.conf)
...ignoring
How do I get only those filenames, which realy have changed, and passed the pattern test.
Thanks a lot for your help
I do now have simplified the code which works for me:
- name: read the postgres conf file
shell: cat /srv/postgresql/config/conf.d/00_global_default.conf
register: user_accts1
- name: a task that only happens if the string exists
when: user_accts1.stdout.find('pg_show_plans') != -1
ansible.builtin.copy:
content: "{{ user_accts1.stdout }}"
dest: 'fileresults/{{ inventory_hostname }}.00_global_default.out'
delegate_to: localhost
- name: read the postgres conf file
shell: cat /srv/postgresql/config/conf.d/01_sizing_specific.conf
register: user_accts2
- name: a task that only happens if the string exists
when: user_accts2.stdout.find('pg_show_plans') != -1
ansible.builtin.copy:
content: "{{ user_accts2.stdout }}"
dest: 'fileresults/{{ inventory_hostname }}.01_sizing_specific.out'
delegate_to: localhost
- name: read the postgres conf file
shell: cat /srv/postgresql/config/conf.d/02_local_overrides.conf
register: user_accts3
- name: a task that only happens if the string exists
when: user_accts3.stdout.find('pg_show_plans') != -1
ansible.builtin.copy:
content: "{{ user_accts3.stdout }}"
dest: 'fileresults/{{ inventory_hostname }}.02_local_overrides.out'
delegate_to: localhost

ANSIBLE: Loop on environment variables

I want to play a shell module in Ansible with multiple environment variable.
I want so to loop on a list registered in my vars. The playbook looks like this :
vars:
tcd_environment_variable:
- { abc_variable: "MSG" , abc_value: "HelloWorld" }
- { abc_variable: "REP_USER" , abc_value: "/home/user" }
tasks:
- name: "Test command with environment variables registered"
shell: "echo $MSG >> $REP_USER/test_env.log"
environment:
"{{ item.abc_variable }}": "{{ item.abc_value }}"
loop: "{{ abc_environment_variable }}"
become: yes
become_user: user
I can't make it work, only this works :
tasks:
- name: "Test command with environment variables registered"
shell: "echo $MSG >> $REP_USER/test_env.log"
environment:
REP_USER: /home/user
MSG: "HelloWorld"
become: yes
become_user: user
But I want to loop on Ansible variable.
Thank's for your help
Use items2dict to transform the list to a dictionary, e.g.
- hosts: localhost
vars:
abc_environment_variable:
- {abc_variable: "MSG", abc_value: "HelloWorld"}
- {abc_variable: "REP_USER", abc_value: "/tmp"}
tasks:
- name: "Test command with environment variables registered"
shell: "echo $MSG >> $REP_USER/test_env.log"
environment: "{{ abc_environment_variable|
items2dict(key_name='abc_variable',
value_name='abc_value') }}"
gives
shell> cat /tmp/test_env.log
HelloWorld
See "Setting the remote environment". Fit the parameters and escalation to your needs.

How do i loop over hosts identified by wildcards in Ansible

Below is my playbook that works fine.
---
- hosts: "PROD_SERVERS"
user: "{{USER}}"
tasks:
- name: Check if all hosts are reachable
fail:
msg: "Server is UNREACHABLE."
when: "hostvars[item].ansible_facts|list|length == 0"
with_items: "{{ groups.PROD_SERVERS }}"
However, can you help me with the syntax when the host is presented as wildcard i.e {{ENV}}_*?
---
- hosts: "{{ENV}}_*"
user: "{{USER}}"
tasks:
- name: Check if all hosts are reachable
fail:
msg: "Server is UNREACHABLE."
when: "hostvars[item].ansible_facts|list|length == 0"
with_items: "{{ groups.{{ENV}}_* }}" <------- Need help with this part of the code
There are special variables also called as "magic variables" to identify the hosts in the current play. They are:
ansible_play_hosts
ansible_play_batch
You can use one of these variables to loop with instead of the inventory group name.
Example with ansible_play_hosts:
- fail:
msg: "Server is UNREACHABLE."
when: hostvars[item].ansible_facts|list|length == 0
with_items: "{{ ansible_play_hosts }}"
Update:
Changed the example for Ansible version "2.4.x", the loop should be performed with with_items rather than loop. Quoting from official documentation
We added loop in Ansible 2.5. It is not yet a full replacement for with_<lookup>, but we recommend it for most use cases.
Note: For Ansible "2.9.16" and "2.10.2" loop works as well.

How to pass a register value into a include_role loop

I have an ansible playbook that is reading in a list of files, and setting a register for those values. I want to then pass the list of files into an include_role task. Below is my current code.
- name: Get list of files
command: "sh -c 'find playbooks/vars/files/*.yml'"
register: find_files
- include_vars:
file: "{{ item }}"
loop: "{{ find_files.stdout_lines }}"
register: result
- name: call role
include_role:
name: myRole
loop: "{{ result.results }}"
When the playbook runs, its finds two files in the directory; file1.yml and file2.yml. But when it runs through the include_role loop, its passes file1.yml twice and never passes file2.yml. Trying to determine how I can ensure file2.yml gets passed to the role as well.
I was able to find the correct my issue by constructing an array and then feeding it into include_role and using the find module instead of shell.
- name: Recursively find yml files
find:
paths: ~/vars
recurse: yes
register: find_files
- name: Construct file array
set_fact:
file_arr: "{{ file_arr|default([]) + [file.path] }}"
with_items: "{{ find_files.files }}"
loop_control:
loop_var: file
- name: Topic Management
include_role:
name: kafkaTopicManagement
vars:
kafkaFiles: "{{ item }}"
with_items: "{{ file_arr }}"
This now feeds the the files into include_role.

Error with Ansible include_tasks while adding dynamic hosts in nested loop

Below is the playbook with import_tasks get_hosts.yml for building dynamic hosts in a nested loop. However, I get syntax error running the playbook.
{{ item.split('\t')[0] }} will have ip addresses separated by commas , and then a string seperated by /t
---
- name: "Play 1"
hosts: localhost
tasks:
- name: "Search database"
command: > mysql --user=root --password=p#ssword deployment
--host=localhost -Ns -e "SELECT dest_ip,file_dets FROM deploy_dets"
register: command_result
- name: Add hosts
include_tasks: "{{ playbook_dir }}/gethosts.yml"
dest_ip: "{{ item.split('\t')[0] }}"
groups: dest_nodes
file_dets: "{{ item.split('\t')[1] }}"
ansible_host: localhost
ansible_connection: local
with_items: "{{ command_result.stdout_lines }}"
And below is my get_hosts.yml file
add_host:
name: "{{ item }}"
with_items: "{{ dest_ip.split(',') }}"
Output:
$ ansible-playbook testinclude.yml
ERROR! Syntax Error while loading YAML. did not find expected key
The error appears to be in '/app/deployment/testinclude.yml': line 23, column 8, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
include_tasks: "{{ playbook_dir }}/gethosts.yml"
dest_ip: "{{ item.split('\t')[0] }}"
^ 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 }}"
Can you please suggest
Perhaps you forgot vars parameter, so:
include_tasks: "{{ playbook_dir }}/gethosts.yml"
vars: # <------------------------------------------- HERE
dest_ip: "{{ item.split('\t')[0] }}"
groups: dest_nodes

Resources