a ì)gœMã@s ddlmZmZmZeZddlZddlZddlZddl Z ddl Z ddl m Z ddlmZmZddlmZddlmZmZddlmZmZmZddlmZdd lmZdd lmZm Z m!Z!m"Z"m#Z#dd l$m%Z%dd l&m'Z'e'ƒZ(e  )d ej*j+ej*j+f¡Z,Gdd„dƒZ-dS)é)Úabsolute_importÚdivisionÚprint_functionN)Ú constants)ÚAnsibleFileNotFoundÚAnsibleParserError)Ú is_executable)Ú binary_typeÚ text_type)Úto_bytesÚ to_nativeÚto_text)Úunquote)Ú from_yaml)ÚVaultLibÚb_HEADERÚ is_encryptedÚis_encrypted_fileÚparse_vaulttext_envelope)Ú unfrackpath)ÚDisplayz(?:^|%s)+tasks%s?$c@sÖeZdZdZdd„Zdd„Zd4d d „Zd5d d „Zd d„Zdd„Z dd„Z dd„Z dd„Z d6dd„Z dd„Zdd„Zdd„Zd d!„Zd"d#„Zd7d$d%„Zd8d&d'„Zd(d)„Zd9d*d+„Zd,d-„Zd.d/„Zd:d0d1„Zd2d3„ZdS);Ú DataLoadera  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_password('foo') ds = dl.load('...') ds = dl.load_from_file('/path/to/file') cCs2d|_tƒ|_tƒ|_i|_tƒ|_| d¡dS)NÚ.) Ú_basedirÚdictÚ _FILE_CACHEÚsetÚ _tempfilesZ_vaultsrÚ_vaultÚset_vault_secrets©Úself©r"ú>/usr/lib/python3.9/site-packages/ansible/parsing/dataloader.pyÚ__init__5s zDataLoader.__init__cCs ||j_dS©N)rÚsecrets)r!Z vault_secretsr"r"r#rKszDataLoader.set_vault_secretsúTFcCst||||jj|dS)zBackwards compat for now)Ú json_only)rrr&)r!ÚdataÚ file_nameÚ show_contentr(r"r"r#ÚloadNszDataLoader.loadc Cs~| |¡}t d|¡|r2||jvr2|j|}n6| |¡\}}t|dd}|j||||d}||j|<|rp|St |¡SdS)zA Loads data from a file, which can contain either JSON or YAML. zLoading data from %sÚsurrogate_or_strict©Úerrors)r)r*r+r(N) Ú path_dwimÚdisplayÚdebugrÚ_get_file_contentsr r,ÚcopyÚdeepcopy) r!r*ÚcacheZunsafer(Z parsed_dataZ b_file_datar+Z file_datar"r"r#Úload_from_fileRs    zDataLoader.load_from_filecCs| |¡}tj t|dd¡S©Nr-r.)r0ÚosÚpathÚexistsr ©r!r:r"r"r#Ú path_existsls zDataLoader.path_existscCs(| |¡}tj t|dd¡p&|tjkSr8)r0r9r:Úisfiler Údevnullr<r"r"r#Úis_fileps zDataLoader.is_filecCs| |¡}tj t|dd¡Sr8)r0r9r:Úisdirr r<r"r"r#Ú is_directoryts zDataLoader.is_directorycCs| |¡}t |¡Sr%)r0r9Úlistdirr<r"r"r#Úlist_directoryxs zDataLoader.list_directorycCs| |¡}t|ƒS)zis the given path executable?)r0rr<r"r"r#r|s zDataLoader.is_executableNc Cs@t|ƒsd}||fSt|ƒ\}}}}|jj||d}d}||fS)zMDecrypt b_vault_data if encrypted and return b_data and the show_content flagT©ÚfilenameF)rrrÚdecrypt) r!Z b_vault_dataÚ b_file_namer+Z b_ciphertextZ b_versionZ cipher_nameZvault_idZb_datar"r"r#Ú_decrypt_if_vault_datasz!DataLoader._decrypt_if_vault_datac CsÐ|rt|ttfƒs"tdt|ƒƒ‚t| |¡ƒ}| |¡sFtd|d‚zDt |dƒ&}|  ¡}|  ||¡WdƒWS1s~0YWn@t t fyÊ}z$td|t|ƒf|d‚WYd}~n d}~00dS)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*ÚrbNú8an error occurred while trying to read the file '%s': %s©Zorig_exc)Ú isinstancer r rr r r0r=rÚopenÚreadrIÚIOErrorÚOSError)r!r*rHÚfr)Úer"r"r#r3Žs    0zDataLoader._get_file_contentscCs|jS)z returns the current basedir )rr r"r"r#Ú get_basedir«szDataLoader.get_basedircCs|durt|ƒ|_dS)zK sets the base directory, used to find files when a relative path is given N)r r)r!Úbasedirr"r"r#Ú set_basedir¯szDataLoader.set_basedircCs^t|ƒ}t|dd}| ttjjƒ¡s0| d¡r6|}nt|jdd}tj ||¡}t|ddS)z= make relative paths work like folks expect. r-r.ú~F©Úfollow) rr Ú startswithr9r:ÚseprÚjoinr)r!Zgivenr:rWr"r"r#r0µs zDataLoader.path_dwimc Cs,t|dd}tj |¡}tt|dddd}tj |d¡tj |d¡tj |d¡f}tj |d¡tj |d ¡tj |d ¡tj |d ¡tj |d ¡tj |d ¡tj |d¡tj |d ¡tj |d ¡tj |d ¡tj |d ¡tj |d ¡f }ttjj|ƒ}ttjj|ƒ}t  |¡rt |ƒs$t |ƒr(dSdS)zR imperfect role detection, roles are still valid w/o tasks|meta/main.yml|yaml|etc r-r.FrZsmain.ymls main.yamlsmainstasks/main.ymlstasks/main.yamls tasks/mains meta/main.ymlsmeta/main.yamls meta/mainT) r r9r:Údirnamerr^Úmapr;ÚRE_TASKSÚsearchÚany) r!r:Úb_pathZb_path_dirnameÚb_upathZuntasked_pathsZ tasked_pathsZexists_untaskedZ exists_taskedr"r"r#Ú_is_roleÅs2     ý            ô zDataLoader._is_rolec Cs†g}t|dd}| ttjjƒ¡s,| d¡rB| t|dd¡n| tj |||¡¡t|dd}|sr| |¡}|r”t   |¡r”ttj  |¡dd}|j }|  |¡| ttj |||¡dd¡|  |¡|rø| |¡sø| ttj |d|¡dd¡| ttj ||¡dd¡| ttj ||¡dd¡| | tj ||¡¡¡| | |¡¡|D]"}tj t|dd¡r^q‚q^|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. r-r.rYFrZZtasks)r r\r9r:r]Úappendrr^rfrarbr_rrXÚendswithr0r;r ) r!r:r_ÚsourceÚis_rolerbrWZ cur_basedirÚ candidater"r"r#Úpath_dwim_relativeçs0       zDataLoader.path_dwim_relativecCst|dd}t|dd}d}g}|dur6t d¡nÀ|rz| d¡sR| tjj¡rzt|dd} tj t| dd¡rv| }n|t  dd   |¡¡|D]¶} t| dd} t| dd} tj  | ¡} |sÊ|  | ¡r |   d ¡r | tj  tj  | ¡||¡¡| tj  | |¡¡q’| d ¡d |kr4| tj  | ||¡¡| tj  | |¡¡q’| d ¡d |kr€| tj  t| ¡dd||¡¡| tj  t| ¡dd|¡¡t  d td  |¡ƒ¡|D]8}t d|t|ƒf¡tj |¡r¼t|ƒ}qöq¼|durt|dd„|Dƒd‚|S)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 r-r.Nz:Invalid request to find a file that matches a "null" valuerYFrZzevaluation_path: %sz s/tasksó/rzsearch_path: %ss zlooking for "%s" at "%s"cSsg|] }t|ƒ‘qSr")r )Ú.0Úpr"r"r#Ú Uóz7DataLoader.path_dwim_relative_stack..)r*Úpaths)r r1Úwarningr\r9r:r]rr;r2r^r_rfrhrgÚsplitrVr Zvvvvvr)r!rrr_rirjZ b_dirnameZb_sourceÚresultrbZ test_pathr:ZupathreZ b_pb_base_dirZ b_candidater"r"r#Úpath_dwim_relative_stacksB      "   z#DataLoader.path_dwim_relative_stackc Csˆtjtjd\}}t |d¡}t|ƒ}zRz| |¡Wn6tyl}zt  |¡t|ƒ‚WYd}~n d}~00W|  ¡n |  ¡0|S)z. Create a tempfile containing defined content )ÚdirÚwbN) ÚtempfileZmkstempÚCZDEFAULT_LOCAL_TMPr9Úfdopenr ÚwriteÚ ExceptionÚremoveÚclose)r!ZcontentÚfdZcontent_tempfilerTÚerrr"r"r#Ú_create_content_tempfileYs   z#DataLoader._create_content_tempfilec Cs0|rt|ttfƒs"tdt|ƒƒ‚t|dd}| |¡rB| |¡sLt|d‚|  |¡}zŽ|ràt t|ƒdƒf}t |t t ƒdrÂ| ¡}|jjsœtdt|ƒƒ‚|jj||d}| |¡}|j |¡Wd ƒn1sÖ0Y|WSttfy*}z(td t|ƒt|ƒf|d ‚WYd }~n d }~00d S) 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 rJr-r.rKrL)Úcountz:A vault password or secret must be specified to decrypt %srENrMrN)rOr r rr r r=r@rr0rPrÚlenrrQrr&rGr‚rÚaddrRrS)r!Ú file_pathrGZ b_file_pathZ real_pathrTr)rUr"r"r#Ú get_real_filegs&    *zDataLoader.get_real_filecCs$||jvr t |¡|j |¡dS)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)rr9Úunlinkr~)r!r†r"r"r#Úcleanup_tmp_files  zDataLoader.cleanup_tmp_filec CsZt|jƒD]J}z| |¡Wq tyR}zt dt|ƒ¡WYd}~q d}~00q dS)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)Úlistrr‰r}r1rsr )r!rTrUr"r"r#Úcleanup_all_tmp_files™s z DataLoader.cleanup_all_tmp_filesc Cs¬ttj ||¡ƒ}g}|dur*dgtj}|D]x}d|vrH|t|ƒ}n|r`d |t|ƒg¡}n|}| |¡r.| |¡r˜|r.| |  t |ƒ|¡¡q¢q.n |  |¡q¨q.|S)z¶ Find vars files in a given path with specified name. This will find files in a dir named / or a file called ending in known extensions. NÚró.) r r9r:r^rzZYAML_FILENAME_EXTENSIONSr=rBÚextendÚ_get_dir_vars_filesr rg) r!r:ÚnameÚ extensionsZ allow_dirrdÚfoundÚextÚ full_pathr"r"r#Úfind_vars_files¤s$    zDataLoader.find_vars_filescCs”g}t| |¡ƒD]|}| d¡s| d¡stj |¡d}tj ||¡}| |¡rj|sj|  |  ||¡¡q|  |¡r|r„t |ƒ|vr|  |¡q|S)NrrYéÿÿÿÿ)ÚsortedrDr\rhr9r:Úsplitextr^rBrŽrr@r rg)r!r:r‘r’Zspathr“Z full_spathr"r"r#rÆs zDataLoader._get_dir_vars_files)r'TF)TFF)N)F)F)T)NT)Ú__name__Ú __module__Ú __qualname__Ú__doc__r$rr,r7r=r@rBrDrrIr3rVrXr0rfrlrvr‚r‡r‰r‹r•rr"r"r"r#r"s0   " 7 ; (  "r).Z __future__rrrÚtypeZ __metaclass__r4r9Zos.pathÚreryZansiblerrzZansible.errorsrrZansible.module_utils.basicrZansible.module_utils.sixr r Zansible.module_utils._textr r r Zansible.parsing.quotingrZansible.parsing.utils.yamlrZansible.parsing.vaultrrrrrZansible.utils.pathrZansible.utils.displayrr1Úcompiler:r]rarr"r"r"r#Ús&