o nnh<@sddlmZdZdZddlZddlZddlZddlmZddl m Z ddl m Z m Z dd Zd d Zd d Zedkr?edSdS)) annotationsa --- module: blockinfile short_description: Insert/update/remove a text block surrounded by marker lines version_added: '2.0' description: - This module will insert/update/remove a block of multi-line text surrounded by customizable marker lines. author: - Yaegashi Takeshi (@yaegashi) options: path: description: - The file to modify. - Before Ansible 2.3 this option was only usable as O(dest), O(destfile) and O(name). type: path required: yes aliases: [ dest, destfile, name ] state: description: - Whether the block should be there or not. type: str choices: [ absent, present ] default: present marker: description: - The marker line template. - C({mark}) will be replaced with the values in O(marker_begin) (default="BEGIN") and O(marker_end) (default="END"). - Using a custom marker without the C({mark}) variable may result in the block being repeatedly inserted on subsequent playbook runs. - Multi-line markers are not supported and will result in the block being repeatedly inserted on subsequent playbook runs. - A newline is automatically appended by the module to O(marker_begin) and O(marker_end). type: str default: '# {mark} ANSIBLE MANAGED BLOCK' block: description: - The text to insert inside the marker lines. - If it is missing or an empty string, the block will be removed as if O(state) were specified to V(absent). type: str default: '' aliases: [ content ] insertafter: description: - If specified and no begin/ending O(marker) lines are found, the block will be inserted after the last match of specified regular expression. - A special value is available; V(EOF) for inserting the block at the end of the file. - If specified regular expression has no matches, V(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 choices: [ EOF, '*regex*' ] default: EOF insertbefore: description: - If specified and no begin/ending O(marker) lines are found, the block will be inserted before the last match of specified regular expression. - A special value is available; V(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. - 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 choices: [ BOF, '*regex*' ] create: description: - Create a new file if it does not exist. type: bool default: no backup: description: - Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly. type: bool default: no marker_begin: description: - This will be inserted at C({mark}) in the opening ansible block O(marker). type: str default: BEGIN version_added: '2.5' marker_end: required: false description: - This will be inserted at C({mark}) in the closing ansible block O(marker). type: str default: END version_added: '2.5' append_newline: required: false description: - Append a blank line to the inserted block, if this does not appear at the end of the file. - Note that this attribute is not considered when C(state) is set to C(absent) type: bool default: no version_added: '2.16' prepend_newline: required: false description: - Prepend a blank line to the inserted block, if this does not appear at the beginning of the file. - Note that this attribute is not considered when C(state) is set to C(absent) type: bool default: no version_added: '2.16' notes: - When using 'with_*' loops be aware that if you do not set a unique mark the block will be overwritten on each iteration. - As of Ansible 2.3, the O(dest) option has been changed to O(path) as default, but O(dest) still works as well. - Option O(ignore:follow) has been removed in Ansible 2.5, because this module modifies the contents of the file so O(ignore:follow=no) does not make sense. - When more than one block should be handled in one file you must change the O(marker) per task. extends_documentation_fragment: - action_common_attributes - action_common_attributes.files - files - validate attributes: check_mode: support: full diff_mode: support: full safe_file_operations: support: full platform: support: full platforms: posix vault: support: none a6 # Before Ansible 2.3, option 'dest' or 'name' was used instead of 'path' - name: Insert/Update "Match User" configuration block in /etc/ssh/sshd_config prepending and appending a new line ansible.builtin.blockinfile: path: /etc/ssh/sshd_config append_newline: true prepend_newline: true block: | Match User ansible-agent PasswordAuthentication no - name: Insert/Update eth0 configuration stanza in /etc/network/interfaces (it might be better to copy files into /etc/network/interfaces.d/) ansible.builtin.blockinfile: path: /etc/network/interfaces block: | iface eth0 inet static address 192.0.2.23 netmask 255.255.255.0 - name: Insert/Update configuration using a local file and validate it ansible.builtin.blockinfile: block: "{{ lookup('ansible.builtin.file', './local/sshd_config') }}" path: /etc/ssh/sshd_config backup: yes validate: /usr/sbin/sshd -T -f %s - name: Insert/Update HTML surrounded by custom markers after line ansible.builtin.blockinfile: path: /var/www/html/index.html marker: "" insertafter: "" block: |

Welcome to {{ ansible_hostname }}

Last updated on {{ ansible_date_time.iso8601 }}

- name: Remove HTML as well as surrounding markers ansible.builtin.blockinfile: path: /var/www/html/index.html marker: "" block: "" - name: Add mappings to /etc/hosts ansible.builtin.blockinfile: path: /etc/hosts block: | {{ item.ip }} {{ item.name }} marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.name }}" loop: - { name: host1, ip: 10.10.1.10 } - { name: host2, ip: 10.10.1.11 } - { 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: " " N)b) AnsibleModule)to_bytes to_nativec Cstj|jd\}}t|d}||||jdd}| }|rLd|vr0|j d|d| ||\}} } |dk}|dkrL|j d|| fd|r[|j |||jd d dSdS) N)dirwbvalidatez%szvalidate must contain %%s: %smsgrz"failed to validate: rc:%s error:%s unsafe_writes)r ) tempfilemkstemptmpdirosfdopenwritecloseparamsget fail_json run_command atomic_move) modulecontentspathtmpfdtmpfilefr validrcouterrr#F/usr/local/lib/python3.10/dist-packages/ansible/modules/blockinfile.py write_changess$  r%cCs<||j}|j|d|dr|r|d7}d}|d7}||fS)NF)diffz and Tz,ownership, perms or SE linux context changed)load_file_common_argumentsr set_file_attributes_if_different)rchangedmessager& file_argsr#r#r$check_file_attrss r,c!Cstttddgddtddddgdtdd d tdd d gd tddtddtddd tddd tddtddd tddd tddd tddd d ddggddd}|j}|d}tj|ri|jdd|dtj|}|s||ds|jdd|dtj |}|rtj|s|j szt |Wn<t y}z|jd||j |jfdWYd}~n"d}~wty}z|jd|t|fdWYd}~nd}~wwd}g}nt|d  }|}Wdn1swY|d}d d d!|d!|d"} |jr|r|| d#<|d} |d} t|d$} t|d%} |d&dk}ttjg}|s>|s>|jdd'|d(| durJ| durJd)} | d*vrYtt| d+d,}n| d-vrhtt| d+d,}nd}ttd.t|d/| ttj}ttd.t|d0| ttj}|r| r| ttjs| ttj7} |g| d|g}ng}d}}t|D]\}}||kr|}||kr|}qd||fvr<d=||d?<| |g} |durT|j||| d<dS|j||| |d@dS)ANrT)destdestfilename)typerequiredaliasesstrpresentabsent)r0defaultchoicesz# {mark} ANSIBLE MANAGED BLOCK)r0r6content)r0r6r2)r0boolFBEGINEND) rstatemarkerblock insertafter insertbeforecreatebackupr marker_begin marker_endappend_newlineprepend_newlinerAr@) argument_specmutually_exclusiveadd_file_common_argssupports_check_modezPath %s is a directory !)r r rBizPath %s does not exist !z6Error creating %s Error code: %s Error description: %sr zError creating %s Error: %srbz %s (content))beforeafter before_header after_headerrNr?r>r=zFile %s not present)r)r EOF)NrRsurrogate_or_strict)errors)NBOFz{mark}rDrE rrGrFrOz File createdz Block removedzBlock insertedrC)r)r r&z%s (file attributes)rPrQ)r)r r& backup_file)*rdictrrrisdirrexistsbooleandirname check_modemakedirsOSErrorerrnostrerror Exceptionropenread splitlines_diffrrlinesep exit_jsonrecompilesubendswith enumerateflags MULTILINEsearchcountendstartlenjoin backup_localrealpathr%r,)!rrr path_existsdestpatheoriginallinesrr&rAr@r?r>r4 blank_lineinsertremarker0marker1 blocklinesn0n1ilinematchline_after_blockresultr r)rY real_path attr_diffdifflistr#r#r$mains8          &$          $$             "   "         r__main__) __future__r DOCUMENTATIONEXAMPLESrkrr ansible.module_utils.sixransible.module_utils.basicr+ansible.module_utils.common.text.convertersrrr%r,r__name__r#r#r#r$s {>   @