
    Vh\                        d dl mZ dZdZdZd dlZd dlZd dlZd dlm	Z	 d dl
mZmZmZ d Zd	 Zd
 Zd Zd Zedk(  r e        yy)    )annotationsa=  
---
module: lineinfile
short_description: Manage lines in text files
description:
  - This module ensures a particular line is in a file, or replace an
    existing line using a back-referenced regular expression.
  - This is primarily useful when you want to change a single line in a file only.
  - See the M(ansible.builtin.replace) module if you want to change multiple, similar lines
    or check M(ansible.builtin.blockinfile) if you want to insert/update/remove a block of lines in a file.
    For other cases, see the M(ansible.builtin.copy) or M(ansible.builtin.template) modules.
version_added: "0.7"
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: true
    aliases: [ dest, destfile, name ]
  regexp:
    description:
      - The regular expression to look for in every line of the file.
      - For O(state=present), the pattern to replace if found. Only the last line found will be replaced.
      - For O(state=absent), the pattern of the line(s) to remove.
      - If the regular expression is not matched, the line will be
        added to the file in keeping with O(insertbefore) or O(insertafter)
        settings.
      - When modifying a line the regexp should typically match both the initial state of
        the line as well as its state after replacement by O(line) to ensure idempotence.
      - Uses Python regular expressions. See U(https://docs.python.org/3/library/re.html).
    type: str
    aliases: [ regex ]
    version_added: '1.7'
  search_string:
    description:
      - The literal string to look for in every line of the file. This does not have to match the entire line.
      - For O(state=present), the line to replace if the string is found in the file. Only the last line found will be replaced.
      - For O(state=absent), the line(s) to remove if the string is in the line.
      - If the literal expression is not matched, the line will be
        added to the file in keeping with O(insertbefore) or O(insertafter)
        settings.
      - Mutually exclusive with O(backrefs) and O(regexp).
    type: str
    version_added: '2.11'
  state:
    description:
      - Whether the line should be there or not.
    type: str
    choices: [ absent, present ]
    default: present
  line:
    description:
      - The line to insert/replace into the file.
      - Required for O(state=present).
      - If O(backrefs) is set, may contain backreferences that will get
        expanded with the O(regexp) capture groups if the regexp matches.
    type: str
    aliases: [ value ]
  backrefs:
    description:
      - Used with O(state=present).
      - If set, O(line) can contain backreferences (both positional and named)
        that will get populated if the O(regexp) matches.
      - This parameter changes the operation of the module slightly;
        O(insertbefore) and O(insertafter) will be ignored, and if the O(regexp)
        does not match anywhere in the file, the file will be left unchanged.
      - If the O(regexp) does match, the last matching line will be replaced by
        the expanded line parameter.
      - Mutually exclusive with O(search_string).
    type: bool
    default: no
    version_added: "1.1"
  insertafter:
    description:
      - Used with O(state=present).
      - If specified, the line will be inserted after the last match of specified regular expression.
      - If the first match is required, use(firstmatch=yes).
      - A special value is available; V(EOF) for inserting the line at the end of the file.
      - If specified regular expression has no matches or no value is passed, V(EOF) will be used instead.
      - If O(insertbefore) is set, default value V(EOF) will be ignored.
      - If regular expressions are passed to both O(regexp) and O(insertafter), O(insertafter) is only honored if no match for O(regexp) is found.
      - May not be used with O(backrefs) or O(insertbefore).
    type: str
  insertbefore:
    description:
      - Used with O(state=present).
      - If specified, the line will be inserted before the last match of specified regular expression.
      - If the first match is required, use O(firstmatch=yes).
      - A value is available; V(BOF) for inserting the line at the beginning of the file.
      - If specified regular expression has no matches, the line will be inserted at the end of the file.
      - If regular expressions are passed to both O(regexp) and O(insertbefore), O(insertbefore) is only honored if no match for O(regexp) is found.
      - May not be used with O(backrefs) or O(insertafter).
    type: str
    version_added: "1.1"
  create:
    description:
      - Used with O(state=present).
      - If specified, the file will be created if it does not already exist.
      - By default it will fail if the file is missing.
    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
  firstmatch:
    description:
      - Used with O(insertafter) or O(insertbefore).
      - If set, O(insertafter) and O(insertbefore) will work with the first line that matches the given regular expression.
    type: bool
    default: no
    version_added: "2.5"
extends_documentation_fragment:
    - action_common_attributes
    - action_common_attributes.files
    - files
    - validate
attributes:
    check_mode:
        support: full
    diff_mode:
        support: full
    platform:
        platforms: posix
    safe_file_operations:
        support: full
    vault:
        support: none
notes:
  - As of Ansible 2.3, the O(dest) option has been changed to O(path) as default, but O(dest) still works as well.
seealso:
- module: ansible.builtin.blockinfile
- module: ansible.builtin.copy
- module: ansible.builtin.file
- module: ansible.builtin.replace
- module: ansible.builtin.template
- module: community.windows.win_lineinfile
author:
    - Daniel Hokka Zakrissoni (@dhozac)
    - Ahti Kitsik (@ahtik)
    - Jose Angel Munoz (@imjoseangel)
a6
  
# NOTE: Before 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path'
- name: Ensure SELinux is set to enforcing mode
  ansible.builtin.lineinfile:
    path: /etc/selinux/config
    regexp: '^SELINUX='
    line: SELINUX=enforcing

- name: Make sure group wheel is not in the sudoers configuration
  ansible.builtin.lineinfile:
    path: /etc/sudoers
    state: absent
    regexp: '^%wheel'

- name: Replace a localhost entry with our own
  ansible.builtin.lineinfile:
    path: /etc/hosts
    regexp: '^127\.0\.0\.1'
    line: 127.0.0.1 localhost
    owner: root
    group: root
    mode: '0644'

- name: Replace a localhost entry searching for a literal string to avoid escaping
  ansible.builtin.lineinfile:
    path: /etc/hosts
    search_string: '127.0.0.1'
    line: 127.0.0.1 localhost
    owner: root
    group: root
    mode: '0644'

- name: Ensure the default Apache port is 8080
  ansible.builtin.lineinfile:
    path: /etc/httpd/conf/httpd.conf
    regexp: '^Listen '
    insertafter: '^#Listen '
    line: Listen 8080

- name: Ensure php extension matches new pattern
  ansible.builtin.lineinfile:
    path: /etc/httpd/conf/httpd.conf
    search_string: '<FilesMatch ".php[45]?$">'
    insertafter: '^\t<Location \/>\n'
    line: '        <FilesMatch ".php[34]?$">'

- name: Ensure we have our own comment added to /etc/services
  ansible.builtin.lineinfile:
    path: /etc/services
    regexp: '^# port for http'
    insertbefore: '^www.*80/tcp'
    line: '# port for http by default'

- name: Add a line to a file if the file does not exist, without passing regexp
  ansible.builtin.lineinfile:
    path: /tmp/testfile
    line: 192.168.1.99 foo.lab.net foo
    create: yes

# NOTE: Yaml requires escaping backslashes in double quotes but not in single quotes
- name: Ensure the JBoss memory settings are exactly as needed
  ansible.builtin.lineinfile:
    path: /opt/jboss-as/bin/standalone.conf
    regexp: '^(.*)Xms(\d+)m(.*)$'
    line: '\1Xms${xms}m\3'
    backrefs: yes

# NOTE: Fully quoted because of the ': ' on the line. See the Gotchas in the YAML docs.
- name: Validate the sudoers file before saving
  ansible.builtin.lineinfile:
    path: /etc/sudoers
    state: present
    regexp: '^%ADMIN ALL='
    line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
    validate: /usr/sbin/visudo -cf %s

# See https://docs.python.org/3/library/re.html for further details on syntax
- name: Use backrefs with alternative group syntax to avoid conflicts with variable values
  ansible.builtin.lineinfile:
    path: /tmp/config
    regexp: ^(host=).*
    line: \g<1>{{ hostname }}
    backrefs: yes
#N)AnsibleModule)to_bytes	to_nativeto_textc                n   t        j                  | j                        \  }}t        j                  |d      5 }|j                  |       d d d        | j                  j                  dd       }| }|r^d|vr| j                  d|z         | j                  t        ||z  d            \  }}	}
|d	k(  }|d	k7  r| j                  d
|d|
       |rU| j                  |t        t        j                  j                  t        |d            d      | j                  d          y y # 1 sw Y   xY w)N)dirwbvalidatez%szvalidate must contain %%s: %smsgsurrogate_or_stricterrorsr   zfailed to validate: rc:z error:unsafe_writes)r   )tempfilemkstemptmpdirosfdopen
writelinesparamsget	fail_jsonrun_commandr   atomic_mover   pathrealpath)moduleb_linesdesttmpfdtmpfilefr   validrcouterrs              J/home/dcms/DCMS/lib/python3.12/site-packages/ansible/modules/lineinfile.pywrite_changesr+      s-   %%&--8NE7	5$	 1	W }}  T2HLEx!@H!MN++HX5GPe,fgS#a757"> ?7$RWW%5%5htLa6b%c  mB  C)/)G 	 	I  s   D++D4c                    | j                  | j                        }| j                  |d|      r|r|dz  }d}|dz  }||fS )NF)diffz and Tz,ownership, perms or SE linux context changed)load_file_common_argumentsr   set_fs_attributes_if_different)r    changedmessager-   	file_argss        r*   check_file_attrsr3     sS    11&--@I,,YD,IwGAAG    c           	        ddd|z  d|z  d}t        |d      }t        j                  j                  |      s}|s| j	                  dd|z         t        j                  j                  |      }|rAt        j                  j                  |      s"| j                  s	 t        j                  |       g }n%t        |d      5 }|j                         }d d d        | j                  rt        dj                              |d<   | t        j                   t        |d            }|dvr!t        j                   t        |d            }n'|dvr!t        j                   t        |d            }nd }ddg}d }d}t        |d      }|2t#              D ]$  \  }}j%                  |      }|s||d<   |}|
s$ n |0t#              D ]"  \  }}t        |d      |v }|s||d<   |}|
s" n |s^t#              D ]P  \  }}||j'                  d      k(  r||d<   d}"|%|j%                  |      s7|r|dz   |d<   |
r n|sH||d<   |
sP n d}d}t        t        j(                  d      }|d   dk7  rz|	r|r|j+                  |      }n|}|j-                  |      s||z  }|||fdk(  r)|s&|r|dk7  rr|d   dd  dvr|d   |z   |d<   t/        |      |d   k(  r8||d   dz
     j'                  d      |k7  r|j1                  ||z          d}d}n||d      j'                  d      |k7  r|j3                  |d   ||z          d}d}n|r|dk7  r|d   dk  r9|d      j'                  d      |k7  r|j3                  |d   ||z          d}d}ne|d   dz
     j'                  d      |k7  rG|j3                  |d   ||z          d}d}n)|d      |k7  r|||d   <   d}d}n|	rn|dk(  s|dk(  rj3                  d||z          d}d}n|dk(  s|d   dk(  r6r|d   dd  dvr|j1                  |       |j1                  ||z          d}d}n|r|d   dk7  r~t/              |d   k(  r6||d   dz
     j'                  d      |k7  rl|j1                  ||z          d}d}nS|||d      j'                  d      k7  r9|j3                  |d   ||z          d}d}nj3                  |d   ||z          d}d}| j                  rt        dj                              |d<   d}|rK| j                  s?|r0t        j                  j                  |      r| j5                  |      }t7        | |       | j                  r4t        j                  j                  |      s| j9                  ||||        i }t;        | |||      \  }}d!|z  |d"<   d!|z  |d#<   ||g} | j9                  ||||         y # t        $ r6}| j	                  d	t        |      d
t        |      d       Y d }~zd }~ww xY w# 1 sw Y   dxY w)$N %s (content)beforeafterbefore_headerafter_headerr   r   i  zDestination %s does not exist !r'   r   zError creating z ()r   rbr4   r9   )NBOFEOF)Nr@   Fr      
T   NNNrA   )   
   z
line addedr@   zline replaceds   
r:   )r0   r   backupr-   %s (file attributes)r;   r<   )r   r   r   existsr   dirname
check_modemakedirs	Exceptionr   open	readlines_diffr   joinrecompile	enumeratesearchrstriplinesepexpandendswithlenappendinsertbackup_localr+   	exit_jsonr3   )!r    r"   regexpsearch_stringlineinsertafterinsertbeforecreaterH   backrefs
firstmatchr-   b_dest
b_destpather!   r%   bre_mbre_insindexmatchexact_line_matchb_linelineno
b_cur_linematch_foundr   r0   	b_linesep
b_new_line
backupdest	attr_diffdifflists!                                    r*   presentry      s    +d2*T13D
 d#89F77>>&!)JT)QRWW__V,
bggnnZ8ARARcJ' &$ 	$1kkmG	$ ||"388G#45X

8F3HIJ..**Xk:OPQ	]	***Xl;PQR HEEd#89F "+G"4 	FJ,,z2K!a#	  "+G"4 	FJ"=9NOS]]K!a#	 "+G"4 	FJ**733!a#' $
)C%zE!H!%E!H!!	$ CG,ABIQx2~f-J  J""9-)#J M5)-??HX {e3 72;rs#3~#E")"+	"9GBK w<58+uQx!|,33G<Fv	'9:*"&U1X&--g6&@NN58Vi-?@&C"G,%"7 8q=uQx(//8FBuQx)1CD*"&U1X\*11':fDNN58Vi-?@&C"GU1X*, *GE!H!CG	 			+"6q&9,- 
	qR 72;rs+~=NN9%v	)*	qR w<58#uQx!|$++G4>v	12"wuQx(//88NN58Vi%78CG 	uQx)!34||!#((7"34WJv((bggnnV,,,T2Jfgt,!7c*4PI#FGS)DLC!7$!>Io 6 =Ini H
W#jxPE  c  ATV]^_V`%a bbc
	$ 	$s$   W4 X64	X3=+X..X36Y c                   t        |d      }t        j                  j                  |      s| j	                  dd       d}ddd|z  d|z  d}t        |d	      5 }	|	j                         }
d d d        | j                  rt        d
j                  
            |d<    t        j                  t        d            g t        |d      fd}
D cg c]  } ||      s| }
}t              dkD  }| j                  rt        d
j                  |
            |d<   d}|r,| j                  s |r| j                  |      }t        | |
|       |rdt              z  }i }t!        | |||      \  }}d|z  |d<   d|z  |d<   ||g}| j	                  |t              |||       y # 1 sw Y   CxY wc c}w )Nr   r   Fzfile not present)r0   r   r6   r7   r8   r?   r4   r9   c                    j                  |       }n&t        d      | v }n| j                  d      k(  }|rj                  |        | S )Nr   r   rC   )rV   r   rW   r\   )rr   rs   rp   bre_cfoundr`   ra   s     r*   matcherzabsent.<locals>.matcher  s\    ,,z2K&"=9NOS]]K J$5$5g$>>KLL$r4   r   r:   z%s line(s) removedrI   r;   r<   )r0   r}   r   rH   r-   )r   r   r   rJ   r_   rO   rP   rQ   r   rR   rS   rT   r[   rL   r^   r+   r3   )r    r"   r`   ra   rb   rH   rh   r   r-   r%   r!   r~   lr0   rv   rw   rx   rp   r|   r}   s     ``             @@@r*   absentr     s   d#89F77>>&!,>?
C+d2*T13D
 
fd	  q++-  ||"388G#45X

8F3HIJEd#89F	 	 "0QWQZq0G0%j1nG||!#((7"34WJv((,,T2Jfgt,"SZ/I#FGS)DLC!7$!>Io 6 =Ini H
WCJC
Yab]   . 1s    F2 F?.F?2F<c                    t        t        t        ddg d      t        ddddg      t        dd	g
      t        d      t        ddg
      t        d      t        d      t        dd      t        dd      t        dd      t        dd      t        d            ddgddgddggdd      } | j                  }|d   }|d   }|d   }|d   }|d   }|d   }|d   }|d   }	d||fv r$d}
d}|dk(  rd}|
dz  }
| j                  |
|z         t	        |d !      }t
        j                  j                  |      r| j                  d"d#|z  $       |d%   dk(  rP|r|| j                  d&'       |	| j                  d('       |d   |d   }}||d)}t        | ||||	||||||       y |||	fd*k(  r| j                  d+'       t        | ||||	|       y ),Nr   T)r"   destfilename)typerequiredaliasesstrry   r   )r   defaultchoicesregex)r   r   )r   valueboolF)r   r   )r   stater`   ra   rb   rc   rd   rf   re   rH   rg   r   rd   rc   r`   ra   rf   )argument_specmutually_exclusiveadd_file_common_argssupports_check_modere   rH   rg   rb   r6   zThe %s is an empty string, which will match every line in the file. This may have unintended consequences, such as replacing the last line in the file rather than appending.zsearch stringzregular expressionzT If this is desired, use '^' to match every line in the file and avoid this warning.r   r      zPath %s is a directory !r=   r   z%regexp is required with backrefs=truer   z#line is required with state=presentrA   rE   zCone of line, search_string, or regexp is required with state=absent)r   dictr   warnr   r   r   isdirr   ry   r   )r    r   re   rH   rf   r   rg   r`   ra   rb   r   
param_nameb_pathins_befins_afts                  r*   mainr   2  s=   6D:VWE9x>STUWI6E*57)4%(5)vu5VU3VU37u%
 ]+h-H:WfJgi! %F* ]]FHFHFj!H&>D%JHF?+M&>D	fm$${$
R<-JiiCC*$%d#89F	ww}}VC%?$%FGg)#!HI<!FG ".16-3H?wGfmT&&(J	H M4(,>>!fgvtV]D&Ar4   __main__)
__future__r   DOCUMENTATIONEXAMPLESRETURNr   rS   r   ansible.module_utils.basicr   +ansible.module_utils.common.text.convertersr   r   r   r+   r3   ry   r   r   __name__ r4   r*   <module>r      sm    #PdSj 
 	 	  5 T TI,
RQj:cz@BF zF r4   