Blockinfile multiline search (#75090)

pull/77924/head
OscarBell 3 years ago committed by GitHub
parent 813afcbbb4
commit 74eb8b779d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
minor_changes:
- blockinfile - The presence of the multiline flag (?m) in the regular expression for insertafter opr insertbefore controls whether the match is done line by line or with multiple lines (https://github.com/ansible/ansible/pull/75090).

@ -50,6 +50,8 @@ options:
- If specified and no begin/ending C(marker) lines are found, the block will be inserted after the last match of specified regular expression. - If specified and no begin/ending C(marker) lines are found, the block will be inserted after the last match of specified regular expression.
- A special value is available; C(EOF) for inserting the block at the end of the file. - A special value is available; C(EOF) for inserting the block at the end of the file.
- If specified regular expression has no matches, C(EOF) will be used instead. - If specified regular expression has no matches, C(EOF) will be used instead.
- The presence of the multiline flag (?m) in the regular expression controls whether the match is done line by line or with multiple lines.
This behaviour was added in ansible-core 2.14.
type: str type: str
choices: [ EOF, '*regex*' ] choices: [ EOF, '*regex*' ]
default: EOF default: EOF
@ -58,6 +60,8 @@ options:
- If specified and no begin/ending C(marker) lines are found, the block will be inserted before the last match of specified regular expression. - If specified and no begin/ending C(marker) lines are found, the block will be inserted before the last match of specified regular expression.
- A special value is available; C(BOF) for inserting the block at the beginning of the file. - A special value is available; C(BOF) for inserting the block at the beginning of the file.
- If specified regular expression has no matches, the block will be inserted at the end of the file. - If specified regular expression has no matches, the block will be inserted at the end of the file.
- The presence of the multiline flag (?m) in the regular expression controls whether the match is done line by line or with multiple lines.
This behaviour was added in ansible-core 2.14.
type: str type: str
choices: [ BOF, '*regex*' ] choices: [ BOF, '*regex*' ]
create: create:
@ -158,6 +162,14 @@ EXAMPLES = r'''
- { name: host1, ip: 10.10.1.10 } - { name: host1, ip: 10.10.1.10 }
- { name: host2, ip: 10.10.1.11 } - { name: host2, ip: 10.10.1.11 }
- { name: host3, ip: 10.10.1.12 } - { name: host3, ip: 10.10.1.12 }
- name: Search with a multiline search flags regex and if found insert after
blockinfile:
path: listener.ora
block: "{{ listener_line | indent(width=8, first=True) }}"
insertafter: '(?m)SID_LIST_LISTENER_DG =\n.*\(SID_LIST ='
marker: " <!-- {mark} ANSIBLE MANAGED BLOCK -->"
''' '''
import re import re
@ -165,7 +177,7 @@ import os
import tempfile import tempfile
from ansible.module_utils.six import b from ansible.module_utils.six import b
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_bytes from ansible.module_utils._text import to_bytes, to_native
def write_changes(module, contents, path): def write_changes(module, contents, path):
@ -292,6 +304,14 @@ def main():
if None in (n0, n1): if None in (n0, n1):
n0 = None n0 = None
if insertre is not None: if insertre is not None:
if insertre.flags & re.MULTILINE:
match = insertre.search(original)
if match:
if insertafter:
n0 = to_native(original).count('\n', 0, match.end())
elif insertbefore:
n0 = to_native(original).count('\n', 0, match.start())
else:
for i, line in enumerate(lines): for i, line in enumerate(lines):
if insertre.search(line): if insertre.search(line):
n0 = i n0 = i

@ -38,3 +38,4 @@
- import_tasks: validate.yml - import_tasks: validate.yml
- import_tasks: insertafter.yml - import_tasks: insertafter.yml
- import_tasks: insertbefore.yml - import_tasks: insertbefore.yml
- import_tasks: multiline_search.yml

@ -0,0 +1,70 @@
- name: Create multiline_search test file
copy:
dest: "{{ remote_tmp_dir }}/listener.ora"
content: |
LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))) # line added by Agent
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=ON # line added by Agent
SID_LIST_LISTENER_DG =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = DB01_DG)
(ORACLE_HOME = /u01/app/oracle/product/12.1.0.1/db_1)
(SID_NAME = DB011)
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = DB02)
(ORACLE_HOME = /u01/app/oracle/product/12.1.0.1/db_1)
(SID_NAME = DB021)
)
)
- name: Set fact listener_line
set_fact:
listener_line: |
(SID_DESC =
(GLOBAL_DBNAME = DB03
(ORACLE_HOME = /u01/app/oracle/product/12.1.0.1/db_1)
(SID_NAME = DB031)
)
- name: Add block using multiline_search enabled
blockinfile:
path: "{{ remote_tmp_dir }}/listener.ora"
block: "{{ listener_line }}"
insertafter: '(?m)SID_LIST_LISTENER_DG =\n.*\(SID_LIST ='
marker: " <!-- {mark} ANSIBLE MANAGED BLOCK 1-->"
register: multiline_search1
- name: Add block using multiline_search enabled again
blockinfile:
path: "{{ remote_tmp_dir }}/listener.ora"
block: "{{ listener_line }}"
insertafter: '(?m)SID_LIST_LISTENER_DG =\n.*\(SID_LIST ='
marker: " <!-- {mark} ANSIBLE MANAGED BLOCK 1-->"
register: multiline_search2
- name: Try to add block using without multiline flag in regex should add block add end of file
blockinfile:
path: "{{ remote_tmp_dir }}/listener.ora"
block: "{{ listener_line }}"
insertafter: 'SID_LIST_LISTENER_DG =\n.*\(SID_LIST ='
marker: " <!-- {mark} ANSIBLE MANAGED BLOCK 2-->"
register: multiline_search3
- name: Stat the listener.ora file
stat:
path: "{{ remote_tmp_dir }}/listener.ora"
register: listener_ora_file
- name: Ensure insertafter worked correctly
assert:
that:
- multiline_search1 is changed
- multiline_search2 is not changed
- multiline_search3 is changed
- listener_ora_file.stat.checksum == '5a8010ac4a2fad7c822e6aeb276931657cee75c0'
Loading…
Cancel
Save