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.
Related
I have to modified all bashrc files of all users on my linux servers.
I have this playbook to get all bashrc files :
- hosts: all
become: yes
gather_facts: no
tasks:
- name: List all bashrc in home directories
ansible.builtin.find:
path: /home/
pattern: '*.bashrc'
recurse: yes
hidden: yes
file_type: file
register: files_matched
- name: debug
debug:
var: item.path
loop: "{{ files_matched.files }}"
The result is I have on my screen all values for all bashrc files like this :
TASK [debug] ************************************************************************************************************************************************************************************
ok: [REDHAT7-DEV-01] => (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': 1556196786.966984, u'gr_name': u'root', u'path': u'/home/.bashrc', u'xusr': False, u'atime': 1556194629.8001442, u'inode': 12, u'isgid': False, u'size': 531, u'isdir': False, u'ctime': 1556196786.966984, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64773, 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}) => {
"ansible_loop_var": "item",
"item": {
"atime": 1556194629.8001442,
"ctime": 1556196786.966984,
"dev": 64773,
"gid": 0,
"gr_name": "root",
"inode": 12,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1556196786.966984,
"nlink": 1,
"path": "/home/.bashrc",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 531,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
"item.path": "/home/.bashrc"
}
I have this for all users in /home/
When I do this
- name: debug
debug:
var: files_matched
I have an array :
TASK [debug] ************************************************************************************************************************************************************************************
ok: [REDHAT7-DEV-01] => {
"files_matched": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"examined": 2268,
"failed": false,
"files": [
{
"atime": 1556194629.8001442,
"ctime": 1556196786.966984,
"dev": 64773,
"gid": 0,
"gr_name": "root",
"inode": 12,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1556196786.966984,
"nlink": 1,
"path": "/home/.bashrc",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 531,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
How I can have just the path in order to loop over it and add my modification ?
I have some difficulties with loop and array, I don't find a solution.
Thank you for your help.
I have done a modification on the last taks :
- name: debug
debug:
msg: "path is {{ item.path }}."
loop: "{{ files_matched.files }}"
I have what I want but I don't understand why I have all informations :
ok: [REDHAT7-DEV-01] => (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': 1666709700.946537, u'gr_name': u'root', u'path': u'/tmp/testdpi2.txt', u'xusr': False, u'atime': 1666709714.4843469, u'inode': 25, u'isgid': False, u'size': 14, u'isdir': False, u'ctime': 1666709700.946537, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, 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": "path is /tmp/testdpi2.txt."
}
ok: [REDHAT7-DEV-01] => (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': 1666709644.4183307, u'gr_name': u'root', u'path': u'/tmp/testdpi.txt', u'xusr': False, u'atime': 1666709706.733456, u'inode': 24, u'isgid': False, u'size': 6, u'isdir': False, u'ctime': 1666709644.4183307, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, 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": "path is /tmp/testdpi.txt."
}
ok: [REDHAT7-DEV-01] => (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': 1666709689.7376943, u'gr_name': u'root', u'path': u'/tmp/testdpi3.txt', u'xusr': False, u'atime': 1666709691.5566688, u'inode': 26, u'isgid': False, u'size': 21, u'isdir': False, u'ctime': 1666709689.7376943, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, 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": "path is /tmp/testdpi3.txt."
}
item.path is the variable I have to use to do my modification but how I can avoid the informations I don't want to see ((item={u'rusr': True, u'uid': 0, etc...) ?
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'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"
}
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