1

Based on a questions

and considerations like

  • By using the 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.
  • How to execute a script on a Remote Node using Ansible?

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, could it be a feasible case for Should you develop a module?

U880D
  • 8,601
  • 6
  • 24
  • 40

1 Answers1

1

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

U880D
  • 8,601
  • 6
  • 24
  • 40