Based on a questions
slurp
be used as a direct replacement for lookup
?and considerations like
slurp
module one is going to transfer the whole file from the Remote Node to the Control Node over the network just in order to process it and looking up a string. For log files these can be several MB and whereby one is mostly interested only in the information if the file on the Remote Node contains a specific string and therefore one would only need to transfer that kind of information, true
or false
.I was wondering how this can be solved instead of using the shell
module?
---
- hosts: localhost
become: false
gather_facts: false
vars:
SEARCH_STRING: "test"
SEARCH_FILE: "test.file"
tasks:
- name: Search for string in file
command:
cmd: "grep '{{ SEARCH_STRING }}' {{ SEARCH_FILE }}"
register: result
# Since it is a reporting task
# which needs to deliver a result in any case
failed_when: result.rc != 0 and result.rc != 1
check_mode: false
changed_when: false
Or instead of using a workaround with the lineinfile
module?
---
- hosts: localhost
become: false
gather_facts: false
vars:
SEARCH_STRING: "test"
SEARCH_FILE: "test.file"
tasks:
- name: Search for string
lineinfile:
path: "{{ SEARCH_FILE }}"
regexp: "{{ SEARCH_STRING }}"
line: "SEARCH_STRING FOUND"
state: present
register: result
# Since it is a reporting task
changed_when: false
failed_when: "'replaced' not in result.msg" # as it means SEARCH_STRING NOT FOUND
check_mode: true # to prevent changes and to do a dry-run only
- name: Show result, if not found
debug:
var: result
when: "'added' in result.msg" # as it means SEARCH_STRING NOT FOUND
Since I am looking for a more generic approach for tasks in example like
grep ${SEARCH_STRING} /var/log/messages* | cut -d ':' -f 1 | uniq
could it be a feasible case for Should you develop a module?
Following Developing modules and Creating a module I've found the following simple solution with
Custom Module library/pygrep.py
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
def run_module():
module_args = dict(
path=dict(type='str', required=True),
search_string=dict(type='str', required=True)
)
result = dict(
changed=False,
found_lines='',
found=False
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
with open(module.params['path'], 'r') as f:
for line in f.readlines():
if module.params['search_string'] in line:
result['found_lines'] = result['found_lines'] + line
result['found'] = True
result['changed'] = False
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()
Playbook pygrep.yml
---
- hosts: localhost
become: false
gather_facts: false
vars:
SEARCH_FILE: "test.file"
SEARCH_STRING: "test"
tasks:
- name: Grep string from file
pygrep:
path: "{{ SEARCH_FILE }}"
search_string: "{{ SEARCH_STRING }}"
register: search
- name: Show search
debug:
var: search
when: search.found
For a simple test.file
NOTEST
This is a test file.
It contains several test lines.
321tset
123test
cbatset
abctest
testabc
test123
END OF TEST
it will result into an output of
TASK [Show search] ******************
ok: [localhost] =>
search:
changed: false
failed: false
found: true
found_lines: |-
This is a test file.
It contains several test lines.
123test
abctest
testabc
test123
Some Links