File: example_file.txt
`
string1 string2 string3
string4 string5 string0
string7 string8 string9
`
File: run.sh
`
#!/usr/bin/env bash
ansible-playbook -vvv -i ‘localhost,’ -c local test.yml
`
File: test.yml
`
-
hosts:
-
localhost
tasks:
-
name: “Slurp the file we wish to search”
slurp:
src: ./example_file.txt
register: slurped_file
-
name: “To avoid base64 decoding multiple times, we do it once”
set_fact: plain_file=“{{ slurped_file[‘content’] | b64decode }}”
- name: “You can use this task to test your regex”
debug: msg=“{{ plain_file | regex_search(‘string7’) is none}}”
- name: “Insert the wanted line into the file as it doesn’t exist”
lineinfile:
dest: ./example_file.txt
line: “something {{ item }} somethingelse”
state: present
when: plain_file | regex_search(item) is none
with_items:
- string6
- string1
- string8
- foobar
`
Example output:
`
$ ./run.sh
Using /etc/ansible/ansible.cfg as config file
PLAYBOOK: test.yml *************************************************************
1 plays in test.yml
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/system/setup.py
ESTABLISH LOCAL CONNECTION FOR USER: algomi-deploy
EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo ~/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950
” && echo ansible-tmp-1485515755.89-254326766505950=“echo ~/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950
” ) && sleep 0’
PUT /tmp/tmpP7Zu66 TO /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950/setup.py
EXEC /bin/sh -c ‘chmod u+x /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950/ /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950/setup.py && sleep 0’
EXEC /bin/sh -c ‘/usr/bin/python /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950/setup.py; rm -rf “/opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515755.89-254326766505950/” > /dev/null 2>&1 && sleep 0’
ok: [localhost]
TASK [Slurp the file we wish to search] ****************************************
task path: /opt/home/algomi-deploy/test.yml:4
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/network/basics/slurp.py
ESTABLISH LOCAL CONNECTION FOR USER: algomi-deploy
EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo ~/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445
” && echo ansible-tmp-1485515756.18-190467128946445=“echo ~/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445
” ) && sleep 0’
PUT /tmp/tmpUjpiaz TO /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445/slurp.py
EXEC /bin/sh -c ‘chmod u+x /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445/ /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445/slurp.py && sleep 0’
EXEC /bin/sh -c ‘/usr/bin/python /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445/slurp.py; rm -rf “/opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.18-190467128946445/” > /dev/null 2>&1 && sleep 0’
ok: [localhost] => {
“changed”: false,
“content”: “c3RyaW5nMSBzdHJpbmcyIHN0cmluZzMKc3RyaW5nNCBzdHJpbmc1IHN0cmluZzAKc3RyaW5nNyBzdHJpbmc4IHN0cmluZzkK”,
“encoding”: “base64”,
“invocation”: {
“module_args”: {
“src”: “./example_file.txt”
},
“module_name”: “slurp”
},
“source”: “./example_file.txt”
}
TASK [To avoid base64 decoding multiple times, we do it once] ******************
task path: /opt/home/algomi-deploy/test.yml:10
ok: [localhost] => {
“ansible_facts”: {
“plain_file”: “string1 string2 string3\nstring4 string5 string0\nstring7 string8 string9\n”
},
“changed”: false,
“invocation”: {
“module_args”: {
“plain_file”: “string1 string2 string3\nstring4 string5 string0\nstring7 string8 string9\n”
},
“module_name”: “set_fact”
}
}
TASK [Insert the wanted line into the file as it doesn’t exist] ****************
task path: /opt/home/algomi-deploy/test.yml:17
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/files/lineinfile.py
ESTABLISH LOCAL CONNECTION FOR USER: algomi-deploy
EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo ~/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270
” && echo ansible-tmp-1485515756.42-101048875702270=“echo ~/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270
” ) && sleep 0’
PUT /tmp/tmpPv_qtT TO /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270/lineinfile.py
EXEC /bin/sh -c ‘chmod u+x /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270/ /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270/lineinfile.py && sleep 0’
EXEC /bin/sh -c ‘/usr/bin/python /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270/lineinfile.py; rm -rf “/opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.42-101048875702270/” > /dev/null 2>&1 && sleep 0’
changed: [localhost] => (item=string6) => {
“backup”: “”,
“changed”: true,
“diff”: [
{
“after”: “”,
“after_header”: “./example_file.txt (content)”,
“before”: “”,
“before_header”: “./example_file.txt (content)”
},
{
“after_header”: “./example_file.txt (file attributes)”,
“before_header”: “./example_file.txt (file attributes)”
}
],
“invocation”: {
“module_args”: {
“backrefs”: false,
“backup”: false,
“content”: null,
“create”: false,
“delimiter”: null,
“dest”: “./example_file.txt”,
“directory_mode”: null,
“follow”: false,
“force”: null,
“group”: null,
“insertafter”: null,
“insertbefore”: null,
“line”: “something string6 somethingelse”,
“mode”: null,
“owner”: null,
“regexp”: null,
“remote_src”: null,
“selevel”: null,
“serole”: null,
“setype”: null,
“seuser”: null,
“src”: null,
“state”: “present”,
“unsafe_writes”: null,
“validate”: null
},
“module_name”: “lineinfile”
},
“item”: “string6”,
“msg”: “line added”
}
skipping: [localhost] => (item=string1) => {
“changed”: false,
“item”: “string1”,
“skip_reason”: “Conditional check failed”,
“skipped”: true
}
skipping: [localhost] => (item=string8) => {
“changed”: false,
“item”: “string8”,
“skip_reason”: “Conditional check failed”,
“skipped”: true
}
Using module file /usr/lib/python2.7/site-packages/ansible/modules/core/files/lineinfile.py
EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo ~/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938
” && echo ansible-tmp-1485515756.52-54649606538938=“echo ~/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938
” ) && sleep 0’
PUT /tmp/tmpAvxVae TO /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938/lineinfile.py
EXEC /bin/sh -c ‘chmod u+x /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938/ /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938/lineinfile.py && sleep 0’
EXEC /bin/sh -c ‘/usr/bin/python /opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938/lineinfile.py; rm -rf “/opt/home/algomi-deploy/.ansible/tmp/ansible-tmp-1485515756.52-54649606538938/” > /dev/null 2>&1 && sleep 0’
changed: [localhost] => (item=foobar) => {
“backup”: “”,
“changed”: true,
“diff”: [
{
“after”: “”,
“after_header”: “./example_file.txt (content)”,
“before”: “”,
“before_header”: “./example_file.txt (content)”
},
{
“after_header”: “./example_file.txt (file attributes)”,
“before_header”: “./example_file.txt (file attributes)”
}
],
“invocation”: {
“module_args”: {
“backrefs”: false,
“backup”: false,
“content”: null,
“create”: false,
“delimiter”: null,
“dest”: “./example_file.txt”,
“directory_mode”: null,
“follow”: false,
“force”: null,
“group”: null,
“insertafter”: null,
“insertbefore”: null,
“line”: “something foobar somethingelse”,
“mode”: null,
“owner”: null,
“regexp”: null,
“remote_src”: null,
“selevel”: null,
“serole”: null,
“setype”: null,
“seuser”: null,
“src”: null,
“state”: “present”,
“unsafe_writes”: null,
“validate”: null
},
“module_name”: “lineinfile”
},
“item”: “foobar”,
“msg”: “line added”
}
PLAY RECAP *********************************************************************
localhost : ok=4 changed=1 unreachable=0 failed=0
`
Final contents of the example_file.txt file:
`
string1 string2 string3
string4 string5 string0
string7 string8 string9
something string6 somethingelse
something foobar somethingelse
`
- The above slurps a file from the “remote” node.
- It converts the base64 encoded contents of the file into plain text so that we can regex search it
- It uses lineinfile to insert lines using with_items when the regex_search of the plain test file doesn’t match an item
The downsides of the above play are that the slurping a large file may not be possible for you due to memory restrictions. Also, you weren’t clear on what should be inserted into the file if the sought for string was not found and so the solution may not be complete.
Note: the regex_search filter is something new (i.e. not in the docs yet). I didn’t know about it until I came across this PR https://github.com/ansible/ansible/pull/14696
I ran the above on ansible 2.2.1.0.