Ansible give me strange resutlt in a loop - ansible

I am writing a playbook to check if a list of directories exist but Ansible give me some stranges results when I'am using a with_item loop.
Here is working :
- name: test
ansible.builtin.stat:
path: /home/ansible
register: test
- debug: var=test.stat.exists
Give this result :
TASK [debug] ***********************************************************************************************************************************************
ok: [10.99.93.1] => {
"test.stat.exists": true
}
Now, if I do this :
- name: Check if directory exist
ansible.builtin.stat: path= "{{ item }}"
with_items:
- /home/ansible
register: storage
- debug: var=storage.results
I have this result :
{
"storage.results": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": false,
"get_mime": true,
"path": ""
}
},
"item": "/home/ansible",
"stat": {
"exists": false
}
}
]
}
I don't understand why the "exists" is false.

Related

Ansible Stat Module

Bit of an odd one here. Seems I'm not getting the full return values from the Ansible stat module. Any ideas? Here are some snippets of the code I have with the verbose output beneath the plays below.
jboss_deploy_home_dir: /opt/jboss/jboss-eap-7.4
- name: get folder ownership
stat:
path: "{{ jboss_deploy_home_dir }}"
register: jboss_deploy_home_stat
ok: [redacted] => {
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": false,
"get_mime": true,
"path": "/opt/jboss/jboss-eap-7.4"
}
},
"stat": {
"exists": false
}
}
- name: debugging
debug: var=jboss_deploy_home_stat
ok: [redacted] => {
"jboss_deploy_home_stat": {
"changed": false,
"failed": false,
"stat": {
"exists": false < Expected more return values than just this!
}
}
}
What's odd is when I ssh to the target server (centos7.9.2009 server in AWS) I can clearly see that the directory exists!
Other info:
Ansible Version: [ core 2.11.9 ]
Python version: [ 3.6.8 ]

Ansible - Find File with a Specific Path and Copy it to a Specific Pre-Set Destination from a Dictionary

I've got a problem that I've been trying to solve for a few days and I'm starting to think I'm just not going to get it. So, here I am.
I have to write an Ansible playbook that will look for a a bunch of files in a bunch of repos and, if it should happen to find that file in those repos, copy it to a specific destination directory which will be pre-set and specific to that file. A catch is that there might be multiple instances of that file but we only want that file if it's under a specific sub-directory in the path (the location of the sub-directory changes from repo to repo and the directory structure of the repos are all pretty different).
So that I don't put you all through our terrible naming conventions, I've abstracted the problem to this kinda silly example.
Let's say that this is our directory structure:
/tmp/example
└── foods
├── breakfast
│   ├── pancakes
│   └── waffles
├── dinner
│   ├── fish
│   └── pasta
└── lunch
├── burger
└── burrito
And this is our dictionary that states the user, the food they want, and the destination path of the food should we find it:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
Now, let's say that we want to iterate through the list of people in the orders dictionary and find their food item in /tmp/example, BUT it should only match if their food choice is under the foods/lunch directory. If we happen to find their food in the foods/lunch directory, copy it to that user's specified dst directory (notice that not all of the dst directories are the same). Skip the food if it's found under foods/breakfast or foods/dinner or even something like restaurant/lunch; we only care about foods/lunch. For example, Mary wants fish, and fish does exist, but it's in the foods/dinner directory so we're going to consider it as missing and not copy it.
I've gotten to the point where I can find the food but I'm stuck trying to tie that found food file to the dst field that tells us where the food should go. It's frustrating because I feel that all of the data that I need is actually in the find_food_results dictionary. I just don't know how to act on the results of find so as to perform the logical equivalent of "if food matched, and path contains 'foods/lunch', copy it to item.value.dst".
I also can't help but feel that there's a simpler way to do this and I'm just chasing my tail at this point. Anyhow, thanks a bunch in advance. Please let me know if I can clarify anything.
Here's the code:
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "describe find_food_results"
debug:
var: find_food_results
- name: "narrow down our findings to paths that contain 'foods/lunch'"
set_fact:
food_lunch_directory_paths: "{{ food_lunch_directory_paths | default([]) }} + [ '{{ item.path }}' ]"
with_items: "{{ find_food_results.results | map(attribute='files') | list }}"
when: "'foods/lunch' in item.path"
- name: "describe our food/lunch paths"
debug:
var: food_lunch_directory_paths
And here's the output:
PLAY [directory finder] *******************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [127.0.0.1]
TASK [describe orders] ********************************************************************************************************************************************
ok: [127.0.0.1] => {
"orders": {
"Bob": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
},
"Jack": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
},
"Mary": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
}
}
TASK [describe orders | dict2items] *******************************************************************************************************************************
ok: [127.0.0.1] => {
"orders | dict2items": [
{
"key": "Bob",
"value": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
}
},
{
"key": "Jack",
"value": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
}
},
{
"key": "Mary",
"value": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
}
]
}
TASK [find the food] **********************************************************************************************************************************************
ok: [127.0.0.1] => (item={u'key': u'Bob', u'value': {u'food': u'burrito', u'dst': u'/tmp/example-homes/home/bob/plate'}})
ok: [127.0.0.1] => (item={u'key': u'Jack', u'value': {u'food': u'fish', u'dst': u'/tmp/example-homes/home/jack/plate'}})
ok: [127.0.0.1] => (item={u'key': u'Mary', u'value': {u'food': u'fish', u'dst': u'/tmp/example-homes/mary/plate'}})
TASK [describe find_food_results] *********************************************************************************************************************************
ok: [127.0.0.1] => {
"find_food_results": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184466.0584693,
"ctime": 1604184466.0584693,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 58724223,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184466.0584693,
"nlink": 1,
"path": "/tmp/example/foods/lunch/burrito",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"burrito"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Bob",
"value": {
"dst": "/tmp/example-homes/home/bob/plate",
"food": "burrito"
}
},
"matched": 1,
"msg": ""
},
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184480.3713806,
"ctime": 1604184480.3713806,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 62917805,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184480.3713806,
"nlink": 1,
"path": "/tmp/example/foods/dinner/fish",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"fish"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Jack",
"value": {
"dst": "/tmp/example-homes/home/jack/plate",
"food": "fish"
}
},
"matched": 1,
"msg": ""
},
{
"ansible_loop_var": "item",
"changed": false,
"examined": 10,
"failed": false,
"files": [
{
"atime": 1604184480.3713806,
"ctime": 1604184480.3713806,
"dev": 66305,
"gid": 0,
"gr_name": "root",
"inode": 62917805,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1604184480.3713806,
"nlink": 1,
"path": "/tmp/example/foods/dinner/fish",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": null,
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/tmp/example"
],
"patterns": [
"fish"
],
"recurse": true,
"size": null,
"use_regex": false
}
},
"item": {
"key": "Mary",
"value": {
"dst": "/tmp/example-homes/mary/plate",
"food": "fish"
}
},
"matched": 1,
"msg": ""
}
]
}
}
TASK [narrow down our findings to paths that contain 'foods/lunch'] ***********************************************************************************************
ok: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184466.0584693, u'gr_name': u'root', u'path': u'/tmp/example/foods/lunch/burrito', u'xusr': False, u'atime': 1604184466.0584693, u'inode': 58724223, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184466.0584693, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
skipping: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184480.3713806, u'gr_name': u'root', u'path': u'/tmp/example/foods/dinner/fish', u'xusr': False, u'atime': 1604184480.3713806, u'inode': 62917805, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184480.3713806, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
skipping: [127.0.0.1] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1604184480.3713806, u'gr_name': u'root', u'path': u'/tmp/example/foods/dinner/fish', u'xusr': False, u'atime': 1604184480.3713806, u'inode': 62917805, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1604184480.3713806, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 66305, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True})
TASK [describe our food/lunch paths] ******************************************************************************************************************************
ok: [127.0.0.1] => {
"food_lunch_directory_paths": [
"/tmp/example/foods/lunch/burrito"
]
}
PLAY RECAP ********************************************************************************************************************************************************
127.0.0.1 : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Let's take into account missing files. For example, given the orders
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
'Joe':
food: 'steak'
dst: '/tmp/example-homes/joe/plate'
Create the list of the foods
- name: "create list of foods"
set_fact:
foods: "{{ orders|dict2items|
map(attribute='value.food')|unique|sort|list }}"
- debug:
var: foods
gives
foods:
- burrito
- fish
- steak
Find the files and create a dictionary of foods and related files. Then use the dictionary to copy the existing files to destinations
- name: "find the foods"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item }}"
loop: "{{ foods }}"
register: find_food_results
- name: "create dictionary of foods"
set_fact:
foods: "{{ dict(foods|zip(paths)) }}"
vars:
paths: "{{ find_food_results.results|
map(attribute='files')|list }}"
- name: "copy property files to destination"
debug:
msg: "Copy {{ foods[item.value.food][0]['path'] }} to {{ item.value.dst }}"
with_dict: "{{ orders }}"
loop_control:
label: "{{ item.key }}"
when: foods[item.value.food]|length > 0
give
ok: [localhost] => (item=Bob) =>
msg: Copy /tmp/example/foods/lunch/burrito to /tmp/example-homes/home/bob/plate
ok: [localhost] => (item=Jack) =>
msg: Copy /tmp/example/foods/dinner/fish to /tmp/example-homes/home/jack/plate
ok: [localhost] => (item=Mary) =>
msg: Copy /tmp/example/foods/dinner/fish to /tmp/example-homes/mary/plate
skipping: [localhost] => (item=Joe)
Q: "File 'burrito' in the breakfast, lunch, and dinner directories ... How can I iterate over ... find_food_results.files? Almost like a nested loop."
A: Display the dictionary foods with selected paths only. The task
- debug:
msg: "{{ msg.split('\n')[:-1] }}"
vars:
msg: |
{{ item.key }}
{{ item.value|map(attribute='path')|list|to_nice_yaml }}
loop: "{{ foods|dict2items }}"
loop_control:
label: "{{ item.key }}"
gives
TASK [debug] ****
ok: [localhost] => (item=burrito) =>
msg:
- burrito
- '- /tmp/example/foods/breakfast/burrito'
- '- /tmp/example/foods/dinner/burrito'
- '- /tmp/example/foods/lunch/burrito'
ok: [localhost] => (item=fish) =>
msg:
- fish
- '- /tmp/example/foods/dinner/fish'
ok: [localhost] => (item=steak) =>
msg:
- steak
- '[]'
Use subelements if you want to iterate the lists of the files. For example
- name: "List all property files"
debug:
msg: "{{ item.0.key }} {{ item.1.path }}"
with_subelements:
- "{{ foods|dict2items }}"
- value
loop_control:
label: "{{ item.0.key }}"
gives
TASK [List all property files] ****
ok: [localhost] => (item=burrito) =>
msg: burrito /tmp/example/foods/breakfast/burrito
ok: [localhost] => (item=burrito) =>
msg: burrito /tmp/example/foods/dinner/burrito
ok: [localhost] => (item=burrito) =>
msg: burrito /tmp/example/foods/lunch/burrito
ok: [localhost] => (item=fish) =>
msg: fish /tmp/example/foods/dinner/fish
And of course as soon as I ask the question, I find the answer to it :-/
Well, in case anyone else was struggling with this, here's how I fixed it. Though, I'd love to see more efficient solutions, so please do chime in if you have one.
I was able to create a new value in the dictionary called "src" that contained the path of the file found using the find module. Then, in the copy module, I was able to iterate over the dictionary and only copy when the src contained 'foods/lunch'.
Here's the code:
---
- name: "directory finder"
hosts: 127.0.0.1
connection: local
vars:
orders:
'Bob':
food: 'burrito'
dst: '/tmp/example-homes/home/bob/plate'
'Jack':
food: 'fish'
dst: '/tmp/example-homes/home/jack/plate'
'Mary':
food: 'fish'
dst: '/tmp/example-homes/mary/plate'
tasks:
- name: "describe orders"
debug:
var: orders
- name: "describe orders | dict2items"
debug:
var: orders | dict2items
- name: "find the food"
find:
paths: "/tmp/example"
recurse: yes
file_type: file
patterns: "{{ item.value.food }}"
with_items:
- "{{ orders | dict2items }}"
register: find_food_results
- name: "create a src key/value dictionary element"
set_fact:
orders: "{{ orders | combine( new_item, recursive=true ) }}"
vars:
new_item: "{ '{{ item.item.key }}': { 'src': '{{ item.files[0].path }}' } }"
with_items: "{{ find_food_results.results }}"
- name: "copy property files to destination"
copy:
src: "{{ item.value.src }}"
dest: "{{ item.value.dst }}"
owner: root
group: root
mode: 0644
with_dict: "{{ orders }}"
when: "'foods/lunch' in item.value.src"

Ansible: loop our shell command(Linux user group search) result and display the groups

Ansible: loop our shell command(Linux user group search) result and display the groups
Task to check if group exist
- name: "Checking if group doesn't exist"
shell: "grep -i {{ item.group }} /etc/group"
register: presence
loop: "{{ UserAddList.add_users }}"
ignore_errors: true
no_log: true
Json input file:
UserAddList is a json file
{
"add_users": [
{
"name": "test1_123",
"group": "test1_123",
"additional_groups":
[
"test2",
"group1"
],
"password" : "test1_newcdsaf",
"sudo_entry": "ALL=(ALL) NOPASSWD: ALL",
"comment": "test1"
}
],
"delete_users": [
]
}
Task to display the groups doesn't exist
- name: The following groups does't' exist
debug:
msg:
"{{ item._ansible_item_label.group }}"
loop: "{{ presence.results }}"
output:
(item={
'_ansible_parsed': True,
'stderr_lines': [
],
u'changed': True,
u'stdout': u'',
'_ansible_item_result': True,
u'msg': u'non-zero return code',
u'delta': u'0:00:00.008175',
'stdout_lines': [
],
'_ansible_item_label': {
u'comment': u'test1',
u'password': u'test1_newcdsaf',
u'group': u'test1_123',
u'name': u'test1_123',
u'sudo_entry': u'ALL=(ALL) NOPASSWD: ALL',
u'additional_groups': [
u'test2',
u'group1'
]
},
u'end': u'2019-12-10 14:23:15.725676',
'_ansible_no_log': True,
'item': {
u'comment': u'test1',
u'password': u'test1_newcdsaf',
u'group': u'test1_123',
u'name': u'test1_123',
u'sudo_entry': u'ALL=(ALL) NOPASSWD: ALL',
u'additional_groups': [
u'test2',
u'group1'
]
},
u'cmd': u'grep -i test1_123 /etc/group',
u'failed': True,
u'stderr': u'',
u'rc': 1,
u'invocation': {
u'module_args': {
u'warn': True,
u'executable': None,
u'_uses_shell': True,
u'_raw_params': u'grep -i test1_123 /etc/group',
u'removes': None,
u'argv': None,
u'creates': None,
u'chdir': None,
u'stdin': None
}
},
u'start': u'2019-12-10 14:23:15.717501'
})=>{
"changed": false,
"item": {
"changed": true,
"cmd": "grep -i test1_123 /etc/group",
"delta": "0:00:00.008175",
"end": "2019-12-10 14:23:15.725676",
"failed": true,
"invocation": {
"module_args": {
"_raw_params": "grep -i test1_123 /etc/group",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"warn": true
}
},
"item": {
"additional_groups": [
"test2",
"group1"
],
"comment": "test1",
"group": "test1_123",
"name": "test1_123",
"password": "test1_newcdsaf",
"sudo_entry": "ALL=(ALL) NOPASSWD: ALL"
},
"msg": "non-zero return code",
"rc": 1,
"start": "2019-12-10 14:23:15.717501",
"stderr": "",
"stderr_lines": [
],
"stdout": "",
"stdout_lines": [
]
},
"msg": "test1_123"
}
I don't want to display the whole output, I just want to display the groups information.
The debug is printing all the input data as well.
Please any suggestions
The debug is printing all the input data as well.
It's actually not the debug: task that is printing your data, ansible is showing you what it is looping over. However, you are using loop: over the top-level presence.results list, and .results contains not only the output you care about, but also the invocation parameters, success or failure, and the actual returned data that you care about
There are two ways of fixing that problem: tell ansible that you only want it to show something smaller in the loop label, or change the loop: to actually only loop over the deleted users
In the first way, loop_control: will do that (it even cites your exact circumstance in the docs saying When looping over complex data structures, the console output of your task can be enormous. To limit the displayed output, use the label directive with loop_control):
- name: The following groups does't' exist
debug:
msg:
"{{ item._ansible_item_label.group }}"
loop: "{{ presence.results }}"
loop_control:
label: "{{ item.item.name }}"
In the second way, just select out the group you care about and msg: it:
- name: The following groups does't' exist
debug:
msg:
"{{ item }}"
loop: "{{ presence.results | map(attribute='item') | map(attribute='group') | list }}"

Ansible register check_path and used it in with_dict loop

I have a following hash/dict structure of sites:
sites:
example.com:
site: example.com
mail: info#example.com
site_alias: www.example.com
example.fi:
site: example.fi
mail: info#example.fi
site_alias: example.fi
...
I register a value for every site, if there is also a folder for it. Print the result.
name: "Check if path already exists so it is the first time."
stat: path={{ cert_files }}/{{ item.value.site }}
register: check_path
with_dict: "{{ sites }}"
debug: var=check_path.results
# No need to print the whole dictionary, all results are already there.
# with_dict: "{{ sites }}"
So I get something like:
TASK [letsencrypt : debug] *****************************************************
ok: [78.47.67.114] => (item={'key': u'example.com', 'value': {u'mail': u'mail#example.com', u'site_alias': u'www.example.com', u'site': u'example.com'}}) => {
"check_path.results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/etc/letsencrypt/live/example.com"
},
"module_name": "stat"
},
"item": {
"key": "example.com",
"value": {
"mail": "info#example.com",
"site": "example.com",
"site_alias": "www.example.com"
}
},
"stat": {
"atime": 147869032.3522692,
"ctime": 149636484.0226028,
"dev": 2049,
"executable": true,
"exists": true,
"gid": 0,
"gr_name": "root",
"inode": 15725,
"isblk": false,
"ischr": false,
"isdir": true,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": false,
"issock": false,
"isuid": false,
"mode": "0755",
"mtime": 14632684.026028,
"nlink": 2,
"path": "/etc/letsencrypt/live/example.com",
"pw_name": "root",
"readable": true,
"rgrp": true,
"roth": true,
"rusr": true,
"size": 4096,
"uid": 0,
"wgrp": false,
"woth": false,
"writeable": true,
"wusr": true,
"xgrp": true,
"xoth": true,
"xusr": true
}
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/etc/letsencrypt/live/example.com"
},
"module_name": "stat"
},
"item": {
"key": "example.fi",
"value": {
"mail": "info#example.fi",
"site": "example.fi",
"site_alias": "www.example.fi"
}
},
"stat": {
"atime": 1493734857.9738503,
"ctime": 1485960159.8090317,
"dev": 2049,
"executable": true,
"exists": true,
How can I the use or get the value "check_path.results.stats.exists" the last value in the next task if I want to iterate again through {{ sites }} ?
I have tried something like this with no success.
- name: Make a certificate the first time.
command: /bin/bash /opt/letsencrypt/letsencrypt-auto certonly -- standalone --email "{{ item.value.mail }}" --agree-tos --keep-until- expiring -d "{{ item.value.site }}" -d "{{ item.value.site_alias }}"
with_items: check_path
when: check_path.results.stat.exists == false
or
- name: Make a certificate the first time.
command: /bin/bash /opt/letsencrypt/letsencrypt-auto certonly standalone --email "{{ item.value.mail }}" --agree-tos --keep-until-expiring -d "{{ item.value.site }}" -d "{{ item.value.site_alias }}"
with_dict: "{{ sites }}"
when: check_path.results.stat.exists == false
You should iterate over result, not over original list:
- name: Make a certificate the first time.
command: /bin/bash /opt/letsencrypt/letsencrypt-auto certonly standalone --email "{{ item.item.value.mail }}" --agree-tos --keep-until-expiring -d "{{ item.item.value.site }}" -d "{{ item.item.value.site_alias }}"
with_items: "{{ check_path.results }}"
when: not item.stat.exists
here item.item is an item of the original list.

ansible V2 -> "skip_reason": "Conditional check failed" with_items

I am getting some errors while doing the following:
group_vars:
tomcat_servers:
- name: tomcat_1
shutdown_port: 8005
connector_port: 8080
ajp_port: 8009
- name: tomcat_2
shutdown_port: 8105
connector_port: 8180
ajp_port: 8109
main code:
- name: "Check if tomcat is already installed"
stat: path={{ tomcat_server_dir }}/{{ item.name }}/RELEASE-NOTES
register: status
with_items: "{{ tomcat_servers }}"
- debug: var=status
- name: "Copy tomcat into folder if it is not installed"
command: /bin/tar -zxvf /tmp/{{ tomcat_catalina_base }} -C {{ tomcat_server_dir }}/{{ item.name }} --strip 2
when: not status.results[0].stat.exists
with_items:
- "{{ tomcat_servers }}"
- "{{ status.results }}"
Debug result:
ok: [VM1] => {
"status": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8009,
"connector_port": 8080,
"name": "tomcat_1",
"shutdown_port": 8005
},
"stat": {
"exists": false
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8109,
"connector_port": 8180,
"name": "tomcat_2",
"shutdown_port": 8105
},
"stat": {
"exists": false
}
}
]
}
}
Now unfortunally I seem to get the error
"skip_reason": "Conditional check failed", "skipped": true
I have been around the "have you googled it" many times but cannot seem to find the solution here. Google ansible check if file exists with_items and you will probably see the same results.
Any one got an idea how to get this working?
Correct second loop:
---
- hosts: localhost
vars:
results:
- item:
ajp_port: 8009
connector_port: 8080
name: tomcat_1
shutdown_port: 8005
stat:
exists: false
- item:
ajp_port: 8109
connector_port: 8180
name: tomcat_2
shutdown_port: 8105
stat:
exists: false
- item:
name: tomcat_exist
stat:
exists: true
tasks:
- debug:
msg: "name: {{ item.item.name }}, exists: {{ item.stat.exists }}"
when: not item.stat.exists
with_items: "{{ results }}"
So in your setup you need to loop over status.results and refer to item.item.name and item.stat.exists.

Resources