U880D
U880D

Reputation: 12146

How to search for a string in a remote file using Ansible?

Based on a questions

and considerations like

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?

Upvotes: 2

Views: 1588

Answers (1)

U880D
U880D

Reputation: 12146

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

Upvotes: 4

Related Questions