
    VhQ                    |   d dl mZ d dlZd dlZd dl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 d dlmZ d dlmZmZ d dlmZmZmZ d dlmZ d d	lmZ d d
lmZmZmZm Z m!Z! d dl"m#Z# d dl$m%Z%  e%       Z& ejN                  dejP                  jR                  dejP                  jR                  d      Z* G d d      Z+y)    )annotationsN)	constants)AnsibleFileNotFoundAnsibleParserError)is_executable)binary_type	text_type)to_bytes	to_nativeto_text)unquote)	from_yaml)VaultLibis_encryptedis_encrypted_fileparse_vaulttext_envelopePromptVaultSecret)unfrackpath)Displayz(?:^|z)+tasksz?$c                      e Zd ZdZd ZddZdddZdddZddZddZ	ddZ
d d	Zdd
Zd!d"dZd#dZd$dZd%dZd&dZddZd'd(dZd'd)dZd*dZd+d,dZd-dZd.dZd/d0dZd1dZy)2
DataLoaderaU  
    The DataLoader class is used to load and parse YAML or JSON content,
    either from a given file name or from a string that was previously
    read in through other means. A Vault password can be specified, and
    any vault-encrypted files will be decrypted.

    Data read from files will also be cached, so the file will never be
    read from disk more than once.

    Usage:

        dl = DataLoader()
        # optionally: dl.set_vault_secrets([('default', ansible.parsing.vault.PrompVaultSecret(...),)])
        ds = dl.load('...')
        ds = dl.load_from_file('/path/to/file')
    c                    d| _         t               | _        t               | _        i | _        t               | _        | j                  d        y )N.)	_basedirdict_FILE_CACHEset
_tempfiles_vaultsr   _vaultset_vault_secretsselfs    J/home/dcms/DCMS/lib/python3.12/site-packages/ansible/parsing/dataloader.py__init__zDataLoader.__init__4   s@      6
 %
 jt$    c                &    || j                   _        y N)r    secrets)r#   vault_secretss     r$   r!   zDataLoader.set_vault_secretsI   s    +r&   c                J    t        |||| j                  j                  |      S )zBackwards compat for now)	json_only)r   r    r)   )r#   data	file_nameshow_contentr,   s        r$   loadzDataLoader.loadL   s     y,8K8KW`aar&   c                   | j                  |      }t        j                  d|z         |dk7  r|| j                  v r| j                  |   }na| j	                  |      \  }}t        |d      }| j                  ||||      }|dk(  r|| j                  |<   n|dk(  r|s|| j                  |<   |r|S t        j                  |      S )a  
        Loads data from a file, which can contain either JSON or YAML.

        :param file_name: The name of the file to load data from.
        :param cache: Options for caching: none|all|vaulted
        :param unsafe: If True, returns the parsed data as-is without deep copying.
        :param json_only: If True, only loads JSON data from the file.
        :return: The loaded data, optionally deep-copied for safety.
        zLoading data from %snonesurrogate_or_stricterrors)r-   r.   r/   r,   allvaulted)		path_dwimdisplaydebugr   _get_file_contentsr   r0   copydeepcopy)	r#   r.   cacheunsafer,   parsed_datab_file_datar/   	file_datas	            r$   load_from_filezDataLoader.load_from_fileP   s     NN9-	 	,y89 F?yD,<,<<**95K +/*A*A)*L'[,4IJI))iVbnw)xK ~.9  +)#L.9  + ==--r&   c                x    | j                  |      }t        j                  j                  t	        |d            S Nr3   r4   )r8   ospathexistsr
   r#   rG   s     r$   path_existszDataLoader.path_existsw   s+    ~~d#ww~~ht4IJKKr&   c                    | j                  |      }t        j                  j                  t	        |d            xs |t        j
                  k(  S rE   )r8   rF   rG   isfiler
   devnullrI   s     r$   is_filezDataLoader.is_file{   s<    ~~d#ww~~ht4IJKatWYWaWaOaar&   c                x    | j                  |      }t        j                  j                  t	        |d            S rE   )r8   rF   rG   isdirr
   rI   s     r$   is_directoryzDataLoader.is_directory   s+    ~~d#ww}}Xd3HIJJr&   c                N    | j                  |      }t        j                  |      S r(   )r8   rF   listdirrI   s     r$   list_directoryzDataLoader.list_directory   s    ~~d#zz$r&   c                :    | j                  |      }t        |      S )zis the given path executable?)r8   r   rI   s     r$   r   zDataLoader.is_executable   s    ~~d#T""r&   Nc                    t        |      sd}||fS t        |      \  }}}}| j                  j                  ||      }d}||fS )zMDecrypt b_vault_data if encrypted and return b_data and the show_content flagTfilenameF)r   r   r    decrypt)	r#   b_vault_datab_file_namer/   b_ciphertext	b_versioncipher_namevault_idb_datas	            r$   _decrypt_if_vault_dataz!DataLoader._decrypt_if_vault_data   sY     L)L--9QR^9_6ih$$\K$H|##r&   c           	        |rt        |t        t        f      st        dt	        |      z        t        | j                  |            }| j                  |      st        d|      	 t        |d      5 }|j                         }| j                  ||      cddd       S # 1 sw Y   yxY w# t        t        f$ r!}t        d|dt	        |      |      d}~ww xY w)	a	  
        Reads the file contents from the given file name

        If the contents are vault-encrypted, it will decrypt them and return
        the decrypted data

        :arg file_name: The name of the file to read.  If this is a relative
            path, it will be expanded relative to the basedir
        :raises AnsibleFileNotFound: if the file_name does not refer to a file
        :raises AnsibleParserError: if we were unable to read the file
        :return: Returns a byte string of the file contents
        Invalid filename: '%s'z Unable to retrieve file contentsr.   rbN1an error occurred while trying to read the file '': orig_exc)
isinstancer   r	   r   r   r
   r8   rJ   r   openreadra   IOErrorOSError)r#   r.   r[   fr-   es         r$   r;   zDataLoader._get_file_contents   s     
9{I6N O$%=	)@T%TUUt~~i89 ,%&HT]^^	Ik4( FAvvx224EF F F ! 	I$clnwxynz%{  GH  I  I	Is6   )B- 5"B!	B- !B*&B- *B- -C<CCc                    | j                   S )z returns the current basedir )r   r"   s    r$   get_basedirzDataLoader.get_basedir   s    }}r&   c                *    |t        |      | _        yy)zK sets the base directory, used to find files when a relative path is given N)r   r   )r#   basedirs     r$   set_basedirzDataLoader.set_basedir   s     #G,DM r&   c                F   t        |      }t        |d      }|j                  t        t        j                  j
                              s|j                  d      r|}n7t        | j                  d      }t        j                  j                  ||      }t        |d      S )z=
        make relative paths work like folks expect.
        r3   r4   ~Ffollow)	r   r   
startswithrF   rG   sepr   joinr   )r#   givenrG   rt   s       r$   r8   zDataLoader.path_dwim   sy    
 &;<GBGGKK01U5E5Ed5KDdmm4IJG77<</D4..r&   c                   t        |d      }t        j                  j                  |      }t        t	        |d      d      }t        j                  j                  |d      t        j                  j                  |d      t        j                  j                  |d      f}t        j                  j                  |d      t        j                  j                  |d	      t        j                  j                  |d
      t        j                  j                  |d      t        j                  j                  |d      t        j                  j                  |d      t        j                  j                  |d      t        j                  j                  |d	      t        j                  j                  |d
      t        j                  j                  |d      t        j                  j                  |d      t        j                  j                  |d      f}t        t        j                  j                  |      }t        t        j                  j                  |      }t        j                  |      rt        |      st        |      ryy)zR imperfect role detection, roles are still valid w/o tasks|meta/main.yml|yaml|etc r3   r4   Frx   s   main.ymls	   main.yamls   mains   tasks/main.ymls   tasks/main.yamls
   tasks/mains   meta/main.ymls   meta/main.yamls	   meta/mainT)r
   rF   rG   dirnamer   r|   maprH   RE_TASKSsearchany)	r#   rG   b_pathb_path_dirnameb_upathuntasked_pathstasked_pathsexists_untaskedexists_taskeds	            r$   _is_rolezDataLoader._is_role   s    $'<=0;tE:CXY GGLL-GGLL.GGLL)
 GGLL"34GGLL"45GGLL-0GGLL"23GGLL"34GGLL,/GGLL):;GGLL);<GGLL7GGLL)9:GGLL):;GGLL6
 bggnnn=BGGNNL9??4 S%9S=Or&   c           	        g }t        |d      }|j                  t        t        j                  j                              s|j                  d      r|j                  t        |d             n|j                  t        j                  j                  |||             t        |d      }|s| j                  |      }|r?t        j                  |      r*t        t        j                  j                  |      d      }| j                  }| j                  |       |j                  t        t        j                  j                  |||      d             | j                  |       |rL|j                  |      s;|j                  t        t        j                  j                  |d|      d             |j                  t        t        j                  j                  ||      d             |j                  t        t        j                  j                  ||      d             |j                  | j                  t        j                  j                  ||                   |j                  | j                  |             |D ]/  }t        j                  j!                  t#        |d            s. |S  S )z
        find one file in either a role or playbook dir with or without
        explicitly named dirname subdirs

        Used in action plugins and lookups to find supplemental files that
        could be in either place.
        r3   r4   rw   Frx   tasks)r   rz   rF   rG   r{   appendr   r|   r   r   r   r   r   ru   endswithr8   rH   r
   )	r#   rG   r   sourceis_roler   rt   cur_basedir	candidates	            r$   path_dwim_relativezDataLoader.path_dwim_relative   s    (=> WRWW[[12f6G6G6MMM+fU;< MM"'',,tWf=>!$u5G ---8??40%bggood&;EJ--KW%MM+bggll7GV&LUZ[\[)vw7k"'',,w*PY^_` MM+bggll7F&CERS MM+bggll7F&CERS MM$..gv)FGH MM$..01 	Iww~~hy9NOP		 r&   c           	        t        |d      }t        |d      }d}g }|t        j                  d       n'|rv|j                  d      s)|j                  t        j
                  j                        r<t        |d      }	t        j
                  j                  t        |	d            r|	}nt        j                  dd	j                  |      z         |D ]R  }
t        |
d      }t        |d      }t        j
                  j                  |      }|s| j                  |
      r|j                  d
      r||j                  t        j
                  j                  t        j
                  j                  |      ||             |j                  t        j
                  j                  ||             |j                  d      d   |k7  r0|j                  t        j
                  j                  |||             |j                  t        j
                  j                  ||             U |j                  d      d   |k7  rI|j                  t        j
                  j                  t        | j!                         d      ||             |j                  t        j
                  j                  t        | j!                         d      |             t        j                  dt#        dj                  |            z         |D ]S  }t        j%                  d|dt#        |      d       t        j
                  j                  |      sHt#        |      } n |$t'        ||D cg c]  }t)        |       c}      |S c c}w )au  
        find one file in first path in stack taking roles into account and adding play basedir as fallback

        :arg paths: A list of text strings which are the paths to look for the filename in.
        :arg dirname: A text string representing a directory.  The directory
            is prepended to the source to form the path to search for.
        :arg source: A text string which is the filename to search for
        :rtype: A text string
        :returns: An absolute path to the filename ``source`` if found
        :raises: An AnsibleFileNotFound Exception if the file is found to exist in the search paths
        r3   r4   Nz:Invalid request to find a file that matches a "null" valuerw   Frx   zevaluation_path:
	%sz
	s   /tasks   /r   zsearch_path:
	%ss   
	zlooking for "z" at "")r.   paths)r
   r9   warningrz   rF   rG   r{   r   rH   r:   r|   r   r   r   r   splitrr   r   vvvvvr   r   )r#   r   r   r   r   	b_dirnameb_sourceresultr   	test_pathrG   upathr   b_pb_base_dirb_candidateps                   r$   path_dwim_relative_stackz#DataLoader.path_dwim_relative_stack)  s    W-BC	F+@A>OOXY**3/63D3DRWW[[3Q#HU;Iww~~hy9NOP"MM3fkk%6HHI ?#D7"51FG " 8 t}}T28N8Ny8YMM"'',,rww}/MyZb"cdMM"'',,}h"GH>>$'*g5MM"'',,w	8"LMbggll7H=>?  ~~d#A&'1bggll8D4D4D4FOd+egprz{|MM"'',,x0@0@0BK`'acklmMM/'',,v:N2OOP% VW[EYZ[77>>+.$[1F	 >%U[>\PQy|>\]] ?]s   +N
c                h   t        j                  t        j                        \  }}t	        j
                  |d      }t        |      }	 |j                  |       	 |j                          |S # t        $ r%}t	        j                  |       t        |      d}~ww xY w# |j                          w xY w)z. Create a tempfile containing defined content )dirwbN)tempfilemkstempCDEFAULT_LOCAL_TMPrF   fdopenr
   write	Exceptionremoveclose)r#   contentfdcontent_tempfilero   errs         r$   _create_content_tempfilez#DataLoader._create_content_tempfilec  s    '//A4G4GHIIb$7#	GGG
 GGI  	!II&'C. 	! GGIs$   
A. .	B7 BBB B1c           	        |rt        |t        t        f      st        dt	        |      z        t        |d      }| j                  |      r| j                  |      st        |      | j                  |      }	 |rt        t        |      d      5 }t        |      r|j                         }| j                  j                  st        dt	        |      z        | j                  j                  ||      }| j!                  |      }| j"                  j%                  |       ddd       |S |S # 1 sw Y   |S xY w# t&        t(        f$ r*}t        d	t	        |      d
t	        |      |      d}~ww xY w)z
        If the file is vault encrypted return a path to a temporary decrypted file
        If the file is not encrypted then the path is returned
        Temporary files are cleanup in the destructor
        rc   r3   r4   rd   re   z:A vault password or secret must be specified to decrypt %srW   Nrf   rg   rh   )rj   r   r	   r   r   r
   rJ   rN   r   r8   rk   r   rl   r    r)   rY   r   r   addrm   rn   )r#   	file_pathrY   b_file_path	real_pathro   r-   rp   s           r$   get_real_filezDataLoader.get_real_fileq  s    
9{I6N O$%=	)@T%TUUy1FG,DLL4M%	::NN9-		T(9-t4 7 )+  !vvx#{{22"45qt}  H  uI  6I  #J  J#{{224)2L$($A$A$$G	++I67" 9#7" ! 	T$clmvcw  zC  DE  zF  &G  RS  T  T	Ts=   =D? BD2&	D? 0D? 2D<7D? <D? ?E8%E33E8c                    || j                   v r1t        j                  |       | j                   j                  |       yy)z
        Removes any temporary files created from a previous call to
        get_real_file. file_path must be the path returned from a
        previous call to get_real_file.
        N)r   rF   unlinkr   )r#   r   s     r$   cleanup_tmp_filezDataLoader.cleanup_tmp_file  s3     'IIi OO""9- (r&   c                    t        | j                        D ]  }	 | j                  |        y# t        $ r+}t        j                  dt        |      z         Y d}~Gd}~ww xY w)z
        Removes all temporary files that DataLoader has created
        NOTE: not thread safe, forks also need special handling see __init__ for details.
        z Unable to cleanup temp files: %sN)listr   r   r   r9   r   r   )r#   ro   rp   s      r$   cleanup_all_tmp_filesz DataLoader.cleanup_all_tmp_files  s_    
 doo& 	QAQ%%a(	Q  Q BWQZ OPPQs   .	A"!AA"c                   t        t        j                  j                  ||            }g }|dgt        j
                  z   }|D ]  }d|v r|t        |      z   }n!|rdj                  |t        |      g      }n|}| j                  |      sI| j                  |      r0|r-|j                  | j                  t        |      |              |S |j                  t        |              |S  |S )z
        Find vars files in a given path with specified name. This will find
        files in a dir named <name>/ or a file called <name> ending in known
        extensions.
         r      .)r
   rF   rG   r|   r   YAML_FILENAME_EXTENSIONSrJ   rQ   extend_get_dir_vars_filesr   r   )	r#   rG   name
extensions	allow_dirr   foundext	full_paths	            r$   find_vars_fileszDataLoader.find_vars_files  s     "'',,tT23 : ::J 	Ccz"Xc]2	 IIvx}&=>	"		*$$Y/ T%=%=gi>PR\%]^
 	 !LL!34%	$ r&   c                   g }t        | j                  |            D ]  }|j                  d      r|j                  d      r't        j
                  j                  |      d   }t        j
                  j                  ||      }| j                  |      r$|s"|j                  | j                  ||             | j                  |      s|rt        |      |v s|j                  |        |S )Nr   rw   )sortedrT   rz   r   rF   rG   splitextr|   rQ   r   r   rN   r   r   )r#   rG   r   r   spathr   
full_spaths          r$   r   zDataLoader._get_dir_vars_files  s    D//56 
	-E##D)%..2Fgg&&u-b1WW\\$6
$$Z0LL!9!9*j!QR\\*-sgclj>XLL,
	- r&   )r*   z*list[tuple[str, PromptVaultSecret]] | NonereturnNone)z<string>TF)
r-   strr.   r   r/   boolr,   r   r   t.Any)r6   FF)
r.   r   r>   r   r?   r   r,   r   r   r   )rG   r   r   r   )rG   r   r   	list[str]r(   )rZ   bytesr[   zbytes | Noner   tuple[bytes, bool])r.   r   r   r   )r   r   )rt   r   r   r   )r}   r   r   r   )F)
rG   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )r   zstr | bytesr   r   )T)r   r   rY   r   r   r   )r   r   r   r   )r   r   )NT)
rG   r   r   r   r   zlist[str] | Noner   r   r   r   )rG   r   r   r   r   r   )__name__
__module____qualname____doc__r%   r!   r0   rC   rJ   rN   rQ   rT   r   ra   r;   rr   ru   r8   r   r   r   r   r   r   r   r   r    r&   r$   r   r   !   s    "%*,b%.NLbK #
$I:-/  D5n8t &TP.	Q Dr&   r   ),
__future__r   r<   rF   os.pathrer   typingtansibler   r   ansible.errorsr   r   ansible.module_utils.basicr   ansible.module_utils.sixr   r	   +ansible.module_utils.common.text.convertersr
   r   r   ansible.parsing.quotingr   ansible.parsing.utils.yamlr   ansible.parsing.vaultr   r   r   r   r   ansible.utils.pathr   ansible.utils.displayr   r9   compilerG   r{   r   r   r   r&   r$   <module>r      sz   
 #  	  	   " B 4 ; T T + 0 x x * )
)
 2::rww{{BGGKKHI} }r&   