a ì)g+5ã@sŠddlmZmZmZeZdZdZddlZddl Z ddl Z ddl m Z ddl mZddlmZmZdd „Zd d „Zd d „Zedkr†eƒdS)é)Úabsolute_importÚdivisionÚprint_functiona‰ --- 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 I(dest), I(destfile) and I(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 C(marker_begin) (default="BEGIN") and C(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 C(marker_begin) and C(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 C(state) were specified to C(absent). type: str default: '' aliases: [ content ] insertafter: description: - 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. - 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 choices: [ EOF, '*regex*' ] default: EOF insertbefore: description: - 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. - 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 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 marker. type: str default: END version_added: '2.5' 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 I(dest) option has been changed to I(path) as default, but I(dest) still works as well. - Option I(follow) has been removed in Ansible 2.5, because this module modifies the contents of the file so I(follow=no) doesn't make sense. - When more then one block should be handled in one file you must change the I(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 aß # 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 ansible.builtin.blockinfile: path: /etc/ssh/sshd_config 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 Cs¶tj|jd�\}}t |d¡}| |¡| ¡|j dd¡}| }|r˜d|vr`|j d|d�|  ||¡\}} } |dk}|dkr˜|j d|| fd�|r²|j |||jd d �dS) N)ÚdirÚwbÚvalidatez%szvalidate must contain %%s: %s©Úmsgrz"failed to validate: rc:%s error:%sÚ unsafe_writes)r) ÚtempfileZmkstempZtmpdirÚosÚfdopenÚwriteÚcloseÚparamsÚgetÚ fail_jsonZ run_commandZ atomic_move) ÚmoduleÚcontentsÚpathZtmpfdZtmpfileÚfr ZvalidÚrcÚoutÚerr©rú?/usr/lib/python3.9/site-packages/ansible/modules/blockinfile.pyÚ write_changes¹s"  ÿr cCs<| |j¡}|j|d|d�r4|r(|d7}d}|d7}||fS)NF)Údiffz and Tz,ownership, perms or SE linux context changed)Zload_file_common_argumentsrZ set_file_attributes_if_different)rÚchangedÚmessager!Z file_argsrrrÚcheck_file_attrsÎs r$cCsÜtttddgd¢d�tddddgd�tdd d �tdd d gd �tdd�tdd�tddd �tddd �tdd�tddd �tddd �d� ddggddd�}|j}|d}tj |¡r¾|jdd|d�tj |¡}|�sp| |d¡sð|jdd|d�tj  |¡}tj |¡�sf|j �sfzt  |¡WnDt �yd}z*|jd||d|dfd �WYd}~n d}~00d}g}n>t |d!ƒ�}| ¡}Wdƒn1�sš0Y| d¡}d d d"|d"|d#œ} |j�rÚ|�rÚ|| d$<|d} |d} t|d%ƒ} t|d&ƒ} |d'dk}|�s,|�s,|jdd(|d)�| du�rD| du�rDd*} | d+v�rbt t| d,d-�¡}n"| d.v�r€t t| d,d-�¡}nd}t td/ƒt|d0ƒ| ¡ttjƒ}t td/ƒt|d1ƒ| ¡ttjƒ}|�r| �r|  ttjƒ¡�sø| ttjƒ7} |g|  d¡|g}ng}d}}t|ƒD]&\}}||k�r:|}||k�r$|}�q$d||fv�r(d}|du�r|jtj@�rÂ| |¡}|�ræ| �r¤t|ƒ d2d| ¡¡}n| �ræt|ƒ d2d|  ¡¡}n$t|ƒD]\}}| |¡�rÊ|}�qÊ|du�rút!|ƒ}n| du�r&|d7}n| du�rd}nt!|ƒ}n0||k�rDg|||d…<ng|||d…<|}|dk�r–||d ttjƒ¡�s–||dttjƒ7<||||…<|�r´d3 "|¡}nd3}|j�rÈ|| d4<||k�rÜd }d}n,|du�rðd5}d}n|�sd6}d}nd7}d}d}|�rV|j �sV| |d8¡�r:|�r:| #|¡}tj $|d¡}t%|||ƒ|j �rt|�st|j||| d9�i}t&||||ƒ\}}d:||d;<d:||d<<| |g}|du�rÆ|j|||d9�n|j||||d=�dS)>NrT)ÚdestZdestfileÚname)ÚtypeÚrequiredÚaliasesÚstrÚpresentZabsent)r'ÚdefaultÚchoicesz# {mark} ANSIBLE MANAGED BLOCK)r'r,ÚZcontent)r'r,r))r'ÚboolFZBEGINZEND) rÚstateÚmarkerÚblockÚ insertafterÚ insertbeforeÚcreateÚbackupr Ú marker_beginÚ marker_endr4r3)Z argument_specZmutually_exclusiveZadd_file_common_argsZsupports_check_modeézPath %s is a directory !)rr r5izPath %s does not exist !z6Error creating %s Error code: %s Error description: %srér Úrbz %s (content))ÚbeforeÚafterÚ before_headerÚ after_headerr<r2r1r0zFile %s not present)r"r ÚEOF)Nr@Zsurrogate_or_strict)Úerrors)NZBOFz{mark}r7r8Ú ór=z File createdz Block removedzBlock insertedr6)r"r r!z%s (file attributes)r>r?)r"r r!Ú backup_file)'rÚdictrrrÚisdirrÚexistsZbooleanÚdirnameZ check_modeÚmakedirsÚ ExceptionÚopenÚreadÚ splitlinesZ_diffrZ exit_jsonÚreÚcompileÚsubrÚlinesepÚendswithÚ enumerateÚflagsÚ MULTILINEÚsearchrÚcountÚendÚstartÚlenÚjoinZ backup_localÚrealpathr r$)rrrZ path_existsZdestpathÚeÚoriginalÚlinesrr!r4r3r2r1r+ZinsertreZmarker0Zmarker1Z blocklinesZn0Zn1ÚiÚlineÚmatchÚresultr r"rDZ real_pathZ attr_diffZdifflistrrrÚmainÛs     õ ð ÿ ÿ 4 ( ý      $$                       rdÚ__main__)Z __future__rrrr'Z __metaclass__Z DOCUMENTATIONZEXAMPLESrNrrZansible.module_utils.sixrZansible.module_utils.basicrZansible.module_utils._textrrr r$rdÚ__name__rrrrÚsj<   (