I'm using Ansible for some IAC(infra as code) tasks.
I have a playbook where I'm using the find module recursively to search for readable files.
Here is an example of it:
- name: Application logs with read access
become: true
find:
paths: /
file_type: file
recurse: yes
patterns:
- '*.log'
- '*.config'
register: rapplogs
- set_fact: read_app_logs={{rapplogs.matched}}
- debug: var=read_app_logs
- set_fact: read_log_list={{rapplogs.files}}
- debug: var=read_log_list
run_once: True
failed_when: read_app_logs >= 1
ignore_errors: True
The output of it is like this:
TASK [infra_pt : set_fact] ******************************************************************
ok: [192.168.47.135]
TASK [infra_pt : debug] *********************************************************************
ok: [192.168.47.135] => {
"read_app_logs": "72"
}
TASK [infra_pt : set_fact] ******************************************************************
ok: [192.168.47.135]
TASK [infra_pt : debug] *********************************************************************
fatal: [192.168.47.135]: FAILED! => {
"failed_when_result": true,
"read_log_list": {
"changed": false,
"examined": 210060,
"failed": false,
"files": [
{
"atime": 1558446815.3474104,
"ctime": 1558446815.3474104,
"dev": 64768,
"gid": 0,
"gr_name": "root",
"inode": 2065610,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1558446815.3474104,
"nlink": 1,
"path": "/test2.log",
"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
},
From the output list I actually want to access only the "mode" and "path" objects, how this can be done? Any idea?
Try json_query
- set_fact:
read_app_logs: "{{ rapplogs.files|json_query('[].{path: path, mode: mode}') }}"
(not tested)
Sure. You can just iterate over the list of matched files and refer to whichever keys are of interest:
- debug:
msg: "mode of {{ item.path }} is {{ item.mode }}"
loop: "{{ read_log_list.files }}"
Which, given your example output, would produce something like this:
TASK [debug] **********************************************************************************
ok: [localhost] => (item={u'islnk': False, u'uid': 0, u'rgrp': True, u'xoth': False, u'rusr': True, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1558446815.3474104, u'gr_name': u'root', u'path': u'/test2.log', u'xusr': False, u'atime': 1558446815.3474104, u'inode': 2065610, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1558446815.3474104, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 64768, 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}) => {
"msg": "mode of /test2.log is 0644"
}
Related
I'm gathering info on SSL certs on servers (looking for expiration date) using the find module.
- name: Find certs on server
find:
path: /etc/ssl/custom/certs
file_type: file
patterns: "*.crt"
recurse: yes
register: find_result
- debug:
var: find_result
The results are:
ok: [server00] => {
"find_result": {
"changed": false,
"examined": 5,
"failed": false,
"files": [
{
"atime": 1622749788.1552677,
"ctime": 1622744497.4393551,
"dev": 2050,
"gid": 0,
"gr_name": "root",
"inode": 19531534,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1622744497.4393551,
"nlink": 1,
"path": "/etc/ssl/custom/certs/somewebsite0.com.crt",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 1879,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
{
"atime": 1622719627.2477663,
"ctime": 1616545902.3681087,
"dev": 2050,
"gid": 0,
"gr_name": "root",
"inode": 19531253,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1613754568.0,
"nlink": 1,
"path": "/etc/ssl/custom/certs/somewebsite1.com.crt",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 2081,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
{
"atime": 1622719627.2197664,
"ctime": 1616545902.3721087,
"dev": 2050,
"gid": 0,
"gr_name": "root",
"inode": 19535012,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1601653231.0,
"nlink": 1,
"path": "/etc/ssl/custom/certs/somewebsite2.com.crt",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 2269,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 3,
"msg": ""
}
}
I'm needing the path portion of the output ("path": "/etc/ssl/custom/certs/somewebsite1.com.crt"), and if I use find_result.files[0].path it only gives me a single result for each host, when I need every *.crt file.
How can I access each index? I try to use the shell module to perform an action on the .crt file, but again, it's only grabbing the first one due to the [0] index, like so:
- name: Check expiration
shell: "cat {{ find_result.files[0].path }} | openssl x509 -noout -enddate"
register: date
- debug:
var: date.stdout_lines
ok: [server00] => {
"date.stdout_lines": [
"notAfter=Apr 2 19:50:38 2018 GMT"
]
}
Here would be an example playbook based on it:
- hosts: localhost
tasks:
- name: Find certs on server
find:
path: /etc/ssl/custom/certs
file_type: file
patterns: "*.crt"
recurse: yes
register: find_result
- debug:
var: find_result
- name: Play with the data just to demonstrate
set_fact:
IRGeekSauce_list: "{{ (IRGeekSauce_list|default([])) + [item.path] }}"# <-- add each list item to a custom list
with_items: '{{ find_result.files }}' # <-- here we get the files as a list.
- name: your list
debug:
msg: '{{ IRGeekSauce_list }}'
- include_tasks: anothertasklist.yml
loop: '{{ IRGeekSauce_list }}'
loop_control:
loop_var: singlepathvariable
And then you have another "playbook" with just the tasks 'anothertasklist.yml'
- name: hello
debug:
msg: 'You are now in another playbook'
- name:
debug:
msg: 'Woho: {{ singlepathvariable }}'
- name:
openssl_certificate_info:
howeverthatmoduleworks...
And you should be able to just take the entire and include find_result.files as the loop, and then instead just use the loopvar singlepathvariable(and maybe rename it) and just take out the path as {{ singlepathvariable.path }}
I have simple playbook where trying to install the Debian packages downloaded locally in my server. This playbook runs on localhost and install the Debian packages in the same system. But this playbook gives an error "Dependency is not satisfiable for some of the packages even tough the dependency package is available in the local repository.
I can download all the dependencies required for the specific package in my local repository using apt-get install --download-only package_name
But in my playbook, i should have a mechanism to install the dependencies first than install the actual package. This task should be dynamic, playbook should resolve the dependencies by itself for any package install.
When the package has dependency over another package, How the playbook resolve dynamically.
Some of the options explored:
Using ordered indexed_items, using gdebi.. Looking for efficient Logic.
Local Repository has packages -> It can grow depends on the requirement:
wireshark_3.0.5-1_amd64.deb wireshark-qt_3.0.5-1_amd64.deb
Here wireshark_3.0.5-1_amd64.deb has dependency over wireshark-qt_3.0.5-1_amd64.deb.
install_dependencies.yml
---
- hosts: localhost
vars:
remote_media_directory: "/home/local_repository"
become: yes
tasks:
- name: find all debian Packages
find:
paths:
- "{{ remote_media_directory }}"
file_type: file
recurse: yes
use_regex: yes
patterns:
- '.*deb$'
register: files_matched_subdirectory
- name: installation debian packages
apt:
deb: "{{ item.path }}"
with_items: "{{ files_matched_subdirectory.files }}"
when: ansible_distribution == "Ubuntu"
ansible-playbook install_dependencies.yml
PLAY [localhost] **********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [localhost]
TASK [find all debian Packages] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [installation debian packages] ***************************************************************************************************************************************************************************
failed: [localhost] (item={u'uid': 0, u'woth': False, u'mtime': 1571850269.5720358, u'inode': 31195175, u'isgid': False, u'size': 46700, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/wireshark_3.0.5-1_amd64.deb', u'xusr': False, u'atime': 1571850391.3553286, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False}) => {"changed": false, "item": {"atime": 1571850391.3553286, "ctime": 1571850312.2437878, "dev": 2051, "gid": 0, "gr_name": "root", "inode": 31195175, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mode": "0644", "mtime": 1571850269.5720358, "nlink": 1, "path": "/home/local_repository/wireshark_3.0.5-1_amd64.deb", "pw_name": "root", "rgrp": true, "roth": true, "rusr": true, "size": 46700, "uid": 0, "wgrp": false, "woth": false, "wusr": true, "xgrp": false, "xoth": false, "xusr": false}, "msg": "Dependency is not satisfiable: wireshark-qt (= 3.0.5-1)\n"}
failed: [localhost] (item={u'uid': 0, u'woth': False, u'mtime': 1571850269.4560366, u'inode': 31195174, u'isgid': False, u'size': 3605060, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/wireshark-qt_3.0.5-1_amd64.deb', u'xusr': False, u'atime': 1571850394.3993108, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False}) => {"changed": false, "item": {"atime": 1571850394.3993108, "ctime": 1571850312.2437878, "dev": 2051, "gid": 0, "gr_name": "root", "inode": 31195174, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mode": "0644", "mtime": 1571850269.4560366, "nlink": 1, "path": "/home/local_repository/wireshark-qt_3.0.5-1_amd64.deb", "pw_name": "root", "rgrp": true, "roth": true, "rusr": true, "size": 3605060, "uid": 0, "wgrp": false, "woth": false, "wusr": true, "xgrp": false, "xoth": false, "xusr": false}, "msg": "Dependency is not satisfiable: libc6 (>= 2.29)\n"}
ok: [localhost] => (item={u'uid': 0, u'woth': False, u'mtime': 1571850217.1323407, u'inode': 31195169, u'isgid': False, u'size': 40654, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/tree_1.7.0-5_amd64.deb', u'xusr': False, u'atime': 1571850397.4392931, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False})
ok: [localhost] => (item={u'uid': 0, u'woth': False, u'mtime': 1571850217.0163412, u'inode': 31195168, u'isgid': False, u'size': 52132, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/dstat_0.7.3-1_all.deb', u'xusr': False, u'atime': 1571850399.3192823, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False})
to retry, use: --limit #/home/upgrade/ansible/install_dependencies.retry
PLAY RECAP ****************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1
First Setup local repository in the remote server and download install packages using apt-get install --download-only package_name in the remote server. Modify local system /etc/apt/sources.list to point to the local repository packages.
When ansible script try to install using apt-get -y install , it will connect to the local repository and fetches the packages and resolves the dependencies.
Please check the below links for more info
https://kerneltalks.com/package/how-to-configure-local-apt-repository/
https://askubuntu.com/questions/170348/how-to-create-a-local-apt-repository
Everyone, I am using the below script to find all the httpd.conf file in /tmp using the find module and after that, i need to change the server root for all the httpd.conf files that I got from the find module. I am using the Below code.
getting the below error while executing the lineinline module.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Destination {'files': [{'uid': 0, 'woth': False, 'mtime': 1554392266.9903164, 'inode': 4232796, 'isgid': False, 'size': 11753, 'roth': True, 'isuid': False, 'isreg': True, 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/tmp/httpd.conf', 'xusr': False, 'atime': 1554391744.8432574, 'isdir': False, 'ctime': 1554392266.9903164, 'wgrp': False, 'xgrp': False, 'dev': 51714, 'isblk': False, 'isfifo': False, 'mode': '0644', 'islnk': False}], 'changed': False, 'failed': False, 'examined': 14, 'msg': '', 'matched': 1} does not exist !", "rc": 257}
to retry, use: --limit #/etc/ansible/findnew.retry
---
- name: Recursively find httpd.conf file in /tmp
connection: local
hosts: localhost
tasks:
- find:
paths: /tmp
patterns: '*.conf'
recurse: yes
register: filestoser
- debug: var=filestoser
- lineinfile:
path: '{{ filestoser }}'
state: present
regexp: '^ServerRoot'
line: 'ServerRoot_new'
Your problem is that you're trying to use the variable filestoser as a filename, but it's not: it's the result of the find task. If you take a look at the output of your debug task you'll see something like this:
TASK [debug] **********************************************************************************
ok: [localhost] => {
"filestoser": {
"changed": false,
"examined": 44,
"failed": false,
"files": [
{
"atime": 1554394659.885133,
"ctime": 1554394659.885133,
"dev": 45,
"gid": 21937,
"gr_name": "lars",
"inode": 172846,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1554394659.885133,
"nlink": 1,
"path": "/tmp/etc/httpd/httpd.conf",
"pw_name": "lars",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 11753,
"uid": 21937,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 1,
"msg": ""
}
}
In other words, filestoser is a dictionary. The files key contains a list of files that were matched by the files task. You could rewrite your lineinfile task like this, if you want to operate on the first file found:
- lineinfile:
path: '{{ filestoser.files.0.path }}'
state: present
regexp: '^ServerRoot'
line: 'ServerRoot_new'
I'd like to be able to iterate over all of the name values, but I'm not sure how to do so with Ansible. The variable domain is a list, and register is used.
- name: find *.ccfg files in domain(s)
find:
paths: "/tmp/opt/{{ item }}/ccfg"
patterns: "*.ccfg"
recurse: yes
excludes: "Admin.ccfg"
with_items: "{{ domain }}"
register: files
when: ('local' in group_names)
- debug:
msg: "{{ files.results }}"
The path value in each array could be anywhere from 1 to 20. Each index in the array has multiple values. Some arrays may not have any values
Standard Output:
ok: [127.0.0.1] => {
"msg": [
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "CIE",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"examined": 3,
"failed": false,
"files": [
{
"atime": 1541632866.4095802,
"ctime": 1541632866.4095802,
"dev": 64768,
"gid": 0,
"gr_name": "root",
"inode": 52174935,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1541632866.4095802,
"nlink": 1,
"path": "/tmp/opt/CIE/ccfg/cie.ccfg",
"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
}
],
Take a look at the json_query filter:
- debug:
msg: "{{ item }}"
with_items: "{{ files | json_query('results[*].files[*].path') }}"
Official doco: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#json-query-filter
Shameless plug with more examples: https://parko.id.au/2018/08/16/complex-data-structures-and-the-ansible-json_query-filter
I am new to Ansible, I have to find some file and then replace some pattern in the all files. so I am using the find and replace module as follows.
- name: My Great Playbook
hosts: all
gather_facts: False
accelerate: False
strategy: free
vars:
dbname: "#DBNAME#"
repldbname: "connect to mydb"
tasks:
- block:
- name: finding fl
find:
paths: "/home/username1/temp"
patterns: "*.sql"
file_type: "file"
register: repos
- name: some thing
debug: msg="{{ item }}"
with_items: "{{ repos.files }}"
- name: replacing string
replace:
path: "{{ item }}"
#path: "/home/username1/temp/1.sql"
regexp: ({{ dbname }})
replace: '{{ repldbname }}'
backup: no
unsafe_writes: yes
with_items: "{{ repos.files }}"
I am getting following error as follows
failed: [localhost] (item={u'uid': 575479814, u'woth': True, u'mtime': 1504541305.603901, u'inode': 8433422, u'isgid': False, u'size': 256, u'roth': True, u'isuid': False, u'isreg': True, u'gid': 575144449, u'ischr': False, u'wusr': True, u'xoth': True, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'path': u'/home/username1/temp/1.sql', u'xusr': True, u'atime': 1504541305.604901, u'isdir': False, u'ctime': 1504541305.6059012, u'wgrp': True, u'xgrp': True, u'dev': 64772, u'isblk': False, u'isfifo': False, u'mode': u'0777', u'islnk': False}) => {
"failed": true,
"item": {
"atime": 1504541305.604901,
"ctime": 1504541305.6059012,
"dev": 64772,
"gid": 575144449,
"inode": 8433422,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0777",
"mtime": 1504541305.603901,
"nlink": 1,
"path": "/home/username1/temp/1.sql",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 256,
"uid": 575479814,
"wgrp": true,
"woth": true,
"wusr": true,
"xgrp": true,
"xoth": true,
"xusr": true
},
"rc": 257
}
MSG:
Path {'uid': 575479814, 'woth': True, 'mtime': 1504541305.603901, 'inode': 8433422, 'isgid': False, 'size': 256, 'wgrp': True, 'isuid': False, 'isreg': True, 'gid': 575144449, 'ischr': False, 'wusr': True, 'xoth': True, 'islnk': False, 'nlink': 1, 'issock': False, 'rgrp': True, 'path': '/home/username1/temp/1.sql', 'xusr': True, 'atime': 1504541305.604901, 'isdir': False, 'ctime': 1504541305.6059012, 'isblk': False, 'xgrp': True, 'dev': 64772, 'roth': True, 'isfifo': False, 'mode': '0777', 'rusr': True} does not exist !
Please let me know what is issue here ?
Replace:
path: "{{ item }}"
With:
path: "{{ item.path }}"
You are trying to pass a dictionary object to an argument which requires a string value.