How to filter Ansible 'find' output - ansible

I would like to view the list of symbolic links from some remote servers in the terminal, but a lot of information is being printed when I run the playbook.
This is ansible 2.7.12 running on an Ubuntu server. I am using 'find' module and file_type: link to get the softlink details.
Find is returning a lot of details with the return value key "files" but I just need the soft links and corresponding server name in the terminal.
---
# tasks file for application
- name: Get the current applications running
find:
paths: /path/to/app
file_type: link
register: find_result
- name: Print find output
debug:
var: find_result.results
Actual Result:
ok: [client3.example.com] => {
"find_result.files": [
{
"atime": 1559027986.555,
"ctime": 1559027984.828,
"dev": 64768,
"gid": 0,
"gr_name": "root",
"inode": 4284972,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": true,
"isreg": false,
"issock": false,
"isuid": false,
"mode": "0777",
"mtime": 1559027984.828,
"nlink": 1,
"path": "/path/to/app/softlink.1",
"pw_name": "root",
"rgrp": true,
...
...
Would like to get some filtered output in the terminal like:
ok: [client3.example.com] => {
"find_result.files": [
{
"path": "/path/to/app/softlink.1",
},

There are a couple of ways of addressing this question. You could use the map filter to extract just the path attribute from your results:
- name: Print find output
debug:
var: results.files|map(attribute='path')|list
Given the sample data in your question, this would result in:
TASK [Print find output] *****************************************************************************************************************************************************
ok: [localhost] => {
"results.files|map(attribute='path')|list": [
"/path/to/app/softlink.1"
]
}
You can also accomplish something similar using the json_query filter, which applies JMESPath queries to your data:
- name: Print find output
debug:
var: results.files|json_query('[*].path')

Related

how to filter e filter string from list in ansible

this is the list which i have filtered from a nested json using the below json_query
Please see the content of tmpdata
{
"content_length": "4883",
"status": 200,
"cookies": {},
"changed": false,
"strict_transport_security": "max-age=15768000",
"x_api_total_time": "0.234s",
"_ansible_item_result": true,
"_ansible_no_log": false,
"json": {
"job_tags": "",
"type": "job",
"scm_revision": "",
"status": "successful",
"credential": null,
"force_handlers": false,
"job_slice_number": 0,
"ask_credential_on_launch": false,
"started": "2021-02-24T06:48:29.884643Z",
"ask_job_type_on_launch": false,
"start_at_task": "",
"event_processing_finished": true,
"elapsed": 27.82,
"finished": "2021-02-24T06:48:57.704791Z",
"ask_variables_on_launch": true,
"ask_limit_on_launch": false,
"job_slice_count": 1,
"ask_skip_tags_on_launch": false,
"extra_vars": "{\"domain\": \"abc-cn-1\", \"mgmt_password\": \"admin123\", \"mgmt_server\": \"192.168.20.30\", \"fingerprint\": \"9125544D272B5AD28F3E9AB7BC8AA3F276E45064\", \"fwcmd\": \"fw sam -v -J src 192.68.10.10\", \"targets\": [\"abc-cn-c1\"]}",
"use_fact_cache": false,
"name": "test-Checkpoint",
"created": "2021-02-24T06:48:29.003796Z",
"url": "/api/v2/jobs/1198/",
"vault_credential": null,
"verbosity": 4,
"job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-vvvv\", \"-i\", \"/tmp/awx_1198_e4iie_fm/tmpz4bfietf\", \"-e\", \"#/tmp/awx_1198_e4iie_fm/env/extravars\", \"chkpoint.yml\"]",
"modified": "2021-02-24T06:48:29.720325Z",
"unified_job_template": 7,
"project": 6,
"limit": "",
"timeout": 0,
"host_status_counts": {
"ok": 1
},
"result_traceback": "",
"launch_type": "manual"
},
"server": "nginx/1.12.2",
"connection": "close",
"_ansible_parsed": true,
"allow": "GET, DELETE, HEAD, OPTIONS",
"redirected": false,
"cookies_string": "",
"_ansible_ignore_errors": null
}
i am using the below json_query to filter the output from the tempdata
- name: "search for traget fw"
set_fact:
job_status2: "{{ tmpdata | json_query('[json.status, json.extra_vars]') }}"
please see the output from the above facts, you can see dict inside the list and i want to filter only expected output mentioned below
current output:
ok: [localhost] => {
"msg": [
"successful",
"{\"domain\": \"abc-cn-1\", \"mgmt_password\": \"admxxxxxin123\", \"mgmt_server\": \"192.168.10.20\", \"fingerprint\": \"9125544D272B5AD28F3E9AB7BC8AA3F276E45064\", \"fwcmd\": \"fw sam -v -J src 192.68.10.10\", \"targets\": [\"abc-cn-c1\"]}"
]
}
expected output:
["successful", targets": ["abc-cn-c1"]]
please help me id if this is possible
There are (at least) two answers to your question if you want to continue to use json_query, and one that sidesteps that mess entirely. We'll start with the latter because it's less typing for me :-)
- set_fact:
job_status2: '{{ [ tmpdata.json.status, (tmpdata.json.extra_vars|from_json).targets] }}'
the second is a slight variation on that, in that someone needs to resolve that embedded JSON to a dict and (AFAIK) JMESPath has no such ability
- set_fact:
job_status2: "{{ newdata | json_query('[json.status, json.extra_vars.targets]') }}"
vars:
newdata: >-
{{ tmpdata
| combine({"json":{"extra_vars", tmpdata.json.extra_vars|from_json}}, recursive=True)
}}
I mention that one mostly for the case where you are doing other things with json_query and thus it would be advantageous to know how to coerce the structure to be friendlier for JMESPath
and finally, you can cheat and use the JMESPath literal notation to embed the already JSON-ified string right into the query
- set_fact:
job_status2: "{{ newdata | json_query('[json.status, `' + newdata.json.extra_vars + '`.targets]') }}"

Fetch the values of the variables in ansible

I am trying to list the names whose matches have been found.
- name: search for files containing string
find:
paths: /root/ansible-dir
patterns: "file3.yml"
contains: "{{ item }}"
with_items: "{{ names_list }}"
register: file_match
- name: print file
debug:
msg: "{{ file_match }}"
After the above code is run, the below code gets generated :
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"examined": 14,
"failed": false,
"files": [],
"invocation": {
"module_args": {
"age": null,
"age_stamp": "mtime",
"contains": "node_mem",
"depth": null,
"excludes": null,
"file_type": "file",
"follow": false,
"get_checksum": false,
"hidden": false,
"paths": [
"/root/ansible-dir"
],
"patterns": [
"file3.yml"
],
"recurse": false,
"size": null,
"use_regex": false
}
},
"item": "node_mem",
"matched": 0,
"msg": ""
},
How to fetch the name of the item where the matched attribute is >=1?
Use subelements. The debug below gives you a hint how to iterate the results and fetch files that contain the items
- debug:
msg: "Fetch {{ item.1 }}"
with_subelements:
- "{{ file_match.results }}"
- files
It is not necessary to test the number of files is >=1. If the list of files is empty the iteration will be skipped anyway.

filter out text from a complex json object created by an ansible register of gentent module using a json_qry

Specifically I want a "string" of account IDs that are missing from a list I give the task on a server in my inventory.
I run the getent module in the task and I register the result which seems to be a complext JSON object with the data I want as a ket called "item" buried in an array of objects called "results" which is itself an object of "result".
I'm attempting to parse the "result" object for any key called "failed" that has a value of true and extract that object's key value for "item" which is the account id.
I need a boast to get beyond my lack of understanding.
thanks!
Nothing I've tried works. I'm not sure if it's my syntax or a lack of understanding how to parse or "interpret" the JSON object stored in "result"
I think my syntax for the qry variable is asking for any array element in results (an array of objects) which has a key called "failed" with a value of true and if a match is found, return the value of its "item" key. I know if it worked it would return a list. what I need is a string, but I haven't been able to get any result except an empty list [].
I've tried many variations, but the result is always blank.
qry: "result.results[?failed == true].item"
qry: "results[?failed == true].item"
qry: "[?failed == true].item"
Here is the JSON object returned by ansible "debug: var=result "
TASK [debug] *******************************************************************
ok: [x.y.z.abc.com] => {
"result": {
"changed": false,
"failed": true,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": true,
"invocation": {
"module_args": {
"database": "passwd",
"fail_key": true,
"key": "abc123",
"split": null
}
},
"item": "abc123",
"msg": "One or more supplied key could not be found in the database."
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": true,
"invocation": {
"module_args": {
"database": "passwd",
"fail_key": true,
"key": "pubsub",
"split": null
}
},
"item": "pubsub",
"msg": "One or more supplied key could not be found in the database."
}
]
}
}
Here is the playbook section of code:
- name: "Account checks"
ignore_errors: True
with_items:
- abc123
- pubsub
getent: database=passwd key={{ item }}
register: result
- debug: var=result
- debug: msg="Account id is {{ result | json_query(qry) }} "
vars:
qry: "result.results[?failed == true].item"
Here is the output of my json_qry call:
TASK [debug] *******************************************************************
ok: [xyz.abc.com] => {}
MSG:
Account id is
What I want is something like:
"Account id is abc123, pubsub"
result is the top construct you are passing to json_query so it does not exists as top element when it starts processing the data. Moreover, checking for a field without comparison will make sure that field exists and that its value is not false.
Therefore, the correct query to get your info is: results[?failed].item
As you already guessed, this will return a list of item strings for all failed results. You just have to loop over that list to get the individual values.
Below a sample playbook. I changed one failed value to false in your sample data to illustrate.
---
- name: Parse result list with json_query
hosts: localhost
gather_facts: false
vars:
"result": {
"changed": false,
"failed": true,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": true,
"invocation": {
"module_args": {
"database": "passwd",
"fail_key": true,
"key": "abc123",
"split": null
}
},
"item": "abc123",
"msg": "One or more supplied key could not be found in the database."
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"database": "passwd",
"fail_key": true,
"key": "pubsub",
"split": null
}
},
"item": "pubsub",
"msg": "One or more supplied key could not be found in the database."
}
]
}
tasks:
- name: Get item value of failed results
vars:
query: results[?failed].item
debug:
msg: "The user id is {{ item }}"
loop: "{{ result | json_query(query) }}"
which gives:
PLAY [Parse result list with json_query] PLAY RECAP **********************************
TASK [Get item value of failed results] PLAY RECAP ***********************************
ok: [localhost] => (item=abc123) => {
"msg": "The user id is abc123"
}
PLAY RECAP ***********************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

json_query for a value of json output in Ansible

The following outputs to the shell when I run my Ansible play:
TASK [java : debug] ************************************************************************************************************************************************************
ok: [10.3.16.114] => {
"msg": {
"changed": false,
"examined": 1,
"failed": false,
"files": [
{
"attributes": "Directory, NotContentIndexed",
"creationtime": 1551375173.18858,
"filename": "jre1.8.0_201",
"isarchive": false,
"isdir": true,
"ishidden": false,
"islnk": false,
"isreadonly": false,
"isshared": false,
"lastaccesstime": 1551375199.2058175,
"lastwritetime": 1551375199.2058175,
"owner": "NT AUTHORITY\\SYSTEM",
"path": "C:\\Program Files\\Java\\jre1.8.0_201",
"size": 205713652
}
],
"matched": 1
}
}
I need just the value of path so that I can use it as a varuable to set a dynamic java_home inside of windows.
I have been trying to use json_query inside of my yaml but I'm having knowledge limitations here.
- name: Obtain information about a folder
win_find:
paths: C:\Program Files\Java
recurse: no
file_type: directory
register: java_folder
- set_fact:
java_home_dir: "{{java_folder.file | json_query()}}"
It's a simple path. Addressing of the first element is needed, because "files" is a list.
- set_fact:
java_home_dir: "{{ java_folder.files[0].path }}"
If there is more files in the list json_query will be needed.

Fetch doesn't transfer when i use variable

fetch module does not transfer file when i use variable and getting message as "msg": "the remote file does not exist, not transferring, ignored". But file exits in the source directory. Please suggest if anything wrong in this.
ansible 2.1.0.0
---
- hosts: host_A
become_user: yes
gather_facts: no
tasks:
- name: list files
shell: ls -1 /root/stuff/install.1_comiskey-v01
register: dumpfiles
-debug: var=dumpfiles
- name: fetch files
fetch: src={{item}} dest=/tmp/fetched/ flat=yes
with_items: ('{{dumpfiles.stdout_lines}}')
register: test
- debug: var=test
Output:
TASK [fetch files]
*************************************************************
ok: [10.1.31.82] => (item=('[u'/root/stuff/install.1_comiskey-v01',u'/root/stuff/install.1_comiskey-v02']'))
TASK [debug] *******************************************************************
ok: [10.1.31.82] => {
"test": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"file": "('[u'/root/stuff/install.1_comiskey-v01', u'/root/stuff/install.1_comiskey-v02']')",
"invocation": {
"module_args": {
"dest": "/tmp/fetched/",
"flat": "yes",
"src": "('[u'/root/stuff/install.1_comiskey-v01', u'/root/stuff/install.1_comiskey-v02']')"
},
"module_name": "fetch"
},
"item": "('[u'/root/stuff/install.1_comiskey-v01', u'/root/stuff/install.1_comiskey-v02']')",
"msg": "the remote file does not exist, not transferring, ignored"
}
]
}
}
Remove parentheses from with_items. You can note that item variable is not correct on your debug output.

Resources