How do I skip empty item in list if I use with_together?
see the code below:
- name: get data_files list
shell: ls -l data_files | awk -F " " {'print $9'}
register: csv_file_list
- debug: var=csv_file_list
- name: get table name list
shell: ls -l data_files/ | awk -F " " {'print $9'} | sed -e "s/.csv//g" | sed -e "s/-/./g"
register: table_list
- debug: var=table_list
- name: copy table from csv to demo db
shell: psql -U postgres -d demo -c "\copy {{ item.1 }} from /home/ubuntu/data_files/{{ item.0 }} DELIMITER ',' CSV HEADER"
with_together:
- csv_file_list.stdout_lines
- table_list.stdout_lines
when: {{ item.1 }} != ''
Test if item.1 is not none.
when: item.1 != None
Related
When I run this command:
# hammer --csv --no-headers scap-content list | sort -n | awk -F "," '{printf("\"%s\",\"%s\"\n",$1,$2)}'
"1","Red Hat firefox default content"
"2","Red Hat jre default content"
"3","Red Hat rhel6 default content"
"4","Red Hat rhel7 default content"
I get two CSV separated columns ID & Name and I want to read these into Ansible. I can read the contents as one online list e.g.
- name: SCAP | List scap-content
shell: |
hammer --csv --no-headers --username "{{ hammer.username|default('NotSet') }}" --password "{{ hammer.password|default('NotSet') }}" \
scap-content list | sort -n | \
awk -F "," '{printf("\"%s\",\"%s\"\n",$1,$2)}'
register: scap_content
tags: scap
- debug: |
var=scap_content.stdout.split(",")[0]
tags: scap
- debug: var=scap_content.stdout.split(",")[1]
tags: scap
But I want a list with item.id and item.name so I can process the list one row at a time.
Any ideas?
I have a requirement in ansible to compare the mount counts before and after the maintenance, for this i am using the below tasks. We need to compare the premounts and postmounts and if there is difference in the value, it should throw a message to check the host. Please advise.
- name: Take premount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: premounts
- name: Take postmount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: postmounts
I think you are looking for the assert module. You can use this to print a message or fail as per condition.
Example:
- name: Take premount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: premounts
- name: Take postmount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: postmounts
- assert:
that:
- premounts == postmounts
fail_msg: "Premounts: {{ premounts }} and postmounts: {{ postmounts }} do not match!"
success_msg: "Mounts match."
Instead of running the df command and getting number of mounts, you can use the Ansible fact ansible_mounts to get this count also.
Example:
- set_fact:
premounts: "{{ ansible_mounts|count }}"
# some tasks in between
# Gather facts again
- setup:
- set_fact:
postmounts: "{{ ansible_mounts|count }}"
- assert:
that:
- premounts == postmounts
fail_msg: "Premounts: {{ premounts }} and postmounts: {{ postmounts }} do not match!"
success_msg: "Mounts match."
Try as below:
- name: Take premount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: premounts
- name: Take postmount counts
shell: df -h |awk ' NR>1{print $1}'|grep -v "tmpfs"|wc -l
register: postmounts
- debug:
msg: 'There are difference in the mount count, check it'
when: premounts.stdout_lines[0] | int != postmounts.stdout_lines[0] | int
Thanks for your time reading this (probably dumb question)...
I have the following playbook:
- hosts: all
gather_facts: true
vars:
ansible_python_interpreter: /usr/bin/python
tasks:
- name: Get shard status.
shell:
cmd: |
mongo node1:27020 --eval "sh.status()" | grep shards -A 4 | awk -F ':|,|/' '{ print $2 " ", " ", $5,$7,$9}' | sed -e '1 i Shard Nodes' | column -t
when: ansible_fqdn == 'node1'
register: shards_status
- name: Get replica status from SHARD1.
shell:
cmd: |
mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
when: ansible_fqdn == 'node1'
register: shard1
- name: Get replica status from SHARD2.
shell:
cmd: |
mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
when: ansible_fqdn == 'node2'
register: shard2
- name: Get replica status from SHARD3.
shell:
cmd: |
mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
when: ansible_fqdn == 'node3'
register: shard3
- name: Get replica status from SHARD4.
shell:
cmd: |
mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
when: ansible_fqdn == 'node4'
register: shard4
- name: Append logs.
lineinfile:
dest: /tmp/status.txt
line: "{{ item }}"
insertafter: EOF
with_items:
- "{{ shards_status.stdout }}"
- "{{ shard1.stdout }}"
- "{{ shard2.stdout }}"
- "{{ shard3.stdout }}"
- "{{ shard4.stdout }}"
delegate_to: localhost
I want to have in one file (/tmp/status.txt) the result of the above vars (shard1,2,3,4). The issue is, if I run the playbook, I got the following message:
TASK [Append logs.] ****************************************************************************************************************************************************************************************
fatal: [node1]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node2]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node3]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node4]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
Any idea of how I can achieve this?
I have tried accessing into the dic, running only that task from one node and multiple workarounds.. but no luck
I believe this failure is because each time you are guarding your tasks with when: ansible_fqdn == 'node1'.
So when ansible is executing this playbook in node1, its executing all node1 tasks and then when it reaches the Append logs. task it tries to dump the stdout from node2. But since we are running in node1, node2 dictionary is empty, hence 'dict object' has no attribute 'stdout'.
One solution would be to give it a default value, for example
with_items:
- "{{ shards_status.stdout | default("") }}"
- "{{ shard1.stdout | default("") }}"
- "{{ shard2.stdout | default("") }}"
- "{{ shard3.stdout | default("") }}"
- "{{ shard4.stdout | default("") }}"
default value for dictionary in jinja2 (ansible)
But the proper ansible solution would be to change your playbook and way of thinking.
With an inventory like this
[mongo]
shard1 get_shard_status=true
shard2
shard3
shard4
your playbook could look something like this
- hosts: mongo
vars:
get_shard_status: false
tasks:
- name: get shard status
shell: mongo node1:27020 --eval "sh.status()" | grep shards -A 4 | awk -F ':|,|/' '{ print $2 " ", " ", $5,$7,$9}' | sed -e '1 i Shard Nodes' | column -t
register: shard_status
when: get_shard_status
- name: get the replica status
shell: mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
register: replicas
- name: dump status to localhost
lineinfile:
line: "{{ shard_status + '\n' | default('') }}{{ replicas.stdout }}"
state: present
become: false
dest: "/tmp/foobar"
delegate_to: localhost
With this way, if you had another mongo node, you would only modify your inventory and not your playbook and you also dont have to guard the replicas.stdout with a | default("") as you are always executing that in your nodes.
i have some ansible task below :
- name: counting object from json
shell: >
jq '.results[].stdout_lines | length' backup/{{ inventory_hostname }}_rsl.json | wc -l
register: jsondata
- name: counting object converting
shell: >
seq 0 {{ jsondata.stdout|int - 1 }} | tr '\n' ' ' | xargs | sed 's/[[:space:]]/,/g'
register: seq
- name: get interface
shell: >
cat backup/{{ inventory_hostname }}_{{ item }}_rsl_result_nows.json | cut -d, -f1
register: interface
with_items:
- "{{ seq.stdout.split(',') | list }}"
- name: get rsl value
shell: >
cat backup/{{ inventory_hostname }}_{{ item }}_rsl_result_nows.json | cut -d, -f2-
register: rslvalue
with_items:
- "{{ seq.stdout.split(',') | list }}"
- name: post to DB via curl
shell: >
curl -d "ip_address={{ inventory_hostname }}&hostname={{ varhostname.stdout }}&interface={{ interface }}&rslvalue={{ rslvalue }}" -X POST http://dev.trm.net:8088/ip_planning/rsl/postrsl -v
i want to post data with the same hostname but different interface and some other attributes.
This my curl command that i want :
curl -d "ip_address=IP_A&hostname=HOST_A&interface=IFACE_1&rslvalue=1,2,3,4,5" -X POST http://dev.trm.net:8088/ip_planning/rsl/postrsl -v
curl -d "ip_address=IP_A&hostname=HOST_A&interface=IFACE_2&rslvalue=5,4,3,2,1" -X POST http://dev.trm.net:8088/ip_planning/rsl/postrsl -v
curl -d "ip_address=IP_B&hostname=HOST_B&interface=IFACE_1&rslvalue=11,21,31,41,51" -X POST http://dev.trm.net:8088/ip_planning/rsl/postrsl -v
i'm tired a full-day, please help me. i've tried from my ansible script above but error
"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined
You have {{ item.interface.stdout }} in the last task, but with_items is not present.
Also when you use item in the shell command, use as "{{item}}"
a little improvement make me small fun...
- name: post to DB via curl
shell: >
curl -d "ip_address={{ inventory_hostname }}&hostname={{ varhostname.stdout }}&interface={{ item }}&rslvalue={{ item }}" -X POST http://dev.tr$
with_items:
- "{{ rslvalue.results | map(attribute='stdout') | list }}"
- "{{ interface.results | map(attribute='stdout') | list }}"
but "item" variable always print "rslvalue" result. how to declare "item" with multiple with_items ??
Here is my code:
- name: Check last usage history
shell: |
mysql -N --host={{ host }} \
--user={{ user }} \
--password={{ pass }} \
-D db \
-e "SELECT LEFT(CreationTime,LOCATE(' ',CreationTime) - 1) from table;"
register: last_usage
when: products != "1" and products != "2" and products != "3"
- name: Check last modified
shell: |
mysql -N --host={{ host }} \
--user={{ user }} \
--password={{ password }} \
-D db \
-e "SELECT LEFT(ModificationTime,LOCATE(' ',ModificationTime) - 1) FROM table2"
register: last_modi
when: products == "1 or products == "3" or products == "2"
- name: insert data in csv
shell: |
echo "{{ name }}{{ last_usage.stdout }} {{ last_modi.stdout }}" >> /home/test/test.csv
I want to print output in csv file NULL for a variable if task is skipped.
For now, it is showing
One or more undefined variables: 'dict object' has no attribute 'stdout'
- name: insert data in csv
shell: |
echo "{{ name }}{{ last_usage.stdout | default('NULL') }} {{ last_modi.stdout | default('NULL') }}" >> /home/test/test.csv