o nnhWl@sddlmZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z m Z mZddlmZddlmZmZmZddlmZddlmZdd lmZeed Zd d Zd dZ dddZ!GdddeZ"dS)) annotationsN) constants) AnsibleErrorAnsibleActionFailAnsibleFileNotFound)FILE_COMMON_ARGUMENTS)to_bytes to_nativeto_text)boolean) ActionBase)checksum)statepath_original_basenamerecurseforce _diff_peeksrccCtdd|DS)z)remove keys that are not relevant to filecss$|] \}}|tvr||fVqdSN)REAL_FILE_ARGS.0kvrF/usr/local/lib/python3.10/dist-packages/ansible/plugins/action/copy.py -"z+_create_remote_file_args..dictitems module_argsrrr_create_remote_file_args+r%cCr)zremove action plugin only keyscss$|] \}}|dvr||fVqdS))contentdecryptNrrrrrr2rz+_create_remote_copy_args..r r#rrr_create_remote_copy_args0r&r)Fcsgggdd fdd d}|r||}n|tjj}|dur%|}|s-tj|}||r6t|}|rA||sA|d7}n |tjjsL|d7}tj|rcsct|tj |fd<St |}t |j |j ff}|||S) aD Walk a filesystem tree returning enough information to copy the files :arg topdir: The directory that the filesystem tree is rooted at :kwarg base_path: The initial directory structure to strip off of the files for the destination directory. If this is None (the default), the base_path is set to ``top_dir``. :kwarg local_follow: Whether to follow symlinks on the source. When set to False, no symlinks are dereferenced. When set to True (the default), the code will dereference most symlinks. However, symlinks can still be present if needed to break a circular link. :kwarg trailing_slash_detector: Function to determine if a path has a trailing directory separator. Only needed when dealing with paths on a remote machine (in which case, pass in a function that is aware of the directory separator conventions on the remote machine). :returns: dictionary of tuples. All of the path elements in the structure are text strings. This separates all the files, directories, and symlinks along with important information about each:: { 'files': [('/absolute/path/to/copy/from', 'relative/path/to/copy/to'), ...], 'directories': [('/absolute/path/to/copy/from', 'relative/path/to/copy/to'), ...], 'symlinks': [('/symlink/target/path', 'relative/path/to/copy/to'), ...], } The ``symlinks`` field is only populated if ``local_follow`` is set to False *or* a circular symlink cannot be dereferenced. files directoriessymlinksc s.t|D]\}}}|D]H}tj||}tj|||d} tj|rLtj|} r?tj| r?d| | fq dt|| fq d|| fq |D]} tj|| } tj|| |d} tj| }t |}tj| r r|j |j f|vrdt| | fqXt }tj | tjj}tt|ddD]!}t d|d|}|j |j f|vrn ||j |j fq|j |j f|vrdt| | fqXd|| ft|d}||||| d qXdt| | fqXd| | fqXqdS) a This is a closure (function utilizing variables from it's parent function's scope) so that we only need one copy of all the containers. Note that this function uses side effects (See the Variables used from outer scope). :arg topdir: The directory we are walking for files :arg rel_offset: Integer defining how many characters to strip off of the beginning of a path :arg parent_dirs: Directories that we're copying that this directory is in. :kwarg rel_base: String to prepend to the path after ``rel_offset`` is applied to form the relative path. Variables used from the outer scope ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :r_files: Dictionary of files in the hierarchy. See the return value for :func:`walk` for the structure of this dictionary. :local_follow: Read-only inside of :func:`_recurse`. Whether to follow symlinks Nr+r-r/r,)rel_base)oswalkrjoinislinkrealpathisfileappendreadlinkstatst_devst_inosetdirnamesplitseprangelenaddunion)topdir rel_offset parent_dirsr2 base_path sub_foldersr+filenamefilepath dest_filepath real_filer?dirpath dest_dirpathreal_dir dir_stats new_parentsparent_dir_listparent parent_statoffset_recurse local_followr_filesrrrYVsF     z_walk_dirs.._recurseFNr1r-)r.)endswithr3rrAr? startswithrCr6r:basenamer; frozensetr<r=)rFrIrZtrailing_slash_detectorsource_trailing_slashrWrRparentsrrXr _walk_dirs5s. S       rccsBeZdZdZddZddZddZdd Zd fd d ZZ S) ActionModuleTcCsd|vr|jjr d|d<n|jj|d<|jj|dd<t|dtrGd|dvr2d|dd<|ddiddurGd|ddd<|S)N invocationzCENSORED: no_log is setr$r'z'CENSORED: content is a no_log parameter#VALUE_SPECIFIED_IN_NO_LOG_PARAMETER)_taskno_logargscopy isinstancer!get)selfresultrrr_ensure_invocations   zActionModule._ensure_invocationc Cst|jjdddd}t|jjdddd} t|jjdddd} i} g| d <z |jj||d }Wn"tyV} zd| d <d |t| f| d <| WYd} ~ Sd} ~ wwd} |jjdddkrndt t |j } |j j |r~|j j ||}n|}|j|||| d}|dr|dr|dur|||d| d <d| d <| S|j j ||}|j|||| d}|dr| sdSt|}||dkrc|jjr| s| d ||||||jjr|||d| d<| S|j j |j j jd}t j|d}|r||7}d}| s|||}n|||||||j||r1||j j j|f| r6dSt|jj}|t||||d|jjdsS||d<| rZ| |d<|j d||d}n\||||j|| rtdS|r|j||dd}|drd|!vr|d}t"|jj}|t||ddd z|d!=Wn t#yYnw| r| |d<|j d"||d}|ds||d<| || S)#Nr(TFstrictryesrawnodiff)r(failedzcould not find src=%s, %smsgmodepreservez0%03o)all_varsfollowr existsisdir&can not use content with a dir as destr changedz.sourcer1)rdestrr{ansible.legacy.copy module_namer$ task_vars)rzr{islnk lnk_sourcefile)rrrrransible.legacy.file)$r rgrirl_loader get_real_filerr r;S_IMODEr3st_mode _connection_shellpath_has_trailing_slash join_path_execute_remote_stat#_remove_tempfile_if_content_definedr rur9_get_diff_data check_modetmpdirrsplitext_transfer_filecleanup_tmp_file _fixup_perms2r)updater!_execute_modulekeysr%KeyError)rm source_full source_relr'content_tempfilerrr{r(rrsrnelmode dest_file dest_statuslocal_checksumtmp_srcsuffix remote_pathnew_module_args module_returndest_status_nofollowrrr _copy_files              zActionModule._copy_filec Cs|tjtjdd\}}t|d}t|}z$z||Wnty1}z t |t|d}~wwW| |S| w)z. Create a tempfile containing defined content .)dirprefixwbN) tempfilemkstempCDEFAULT_LOCAL_TMPr3fdopenrwrite Exceptionremoveclose)rmr'fdrferrrrr_create_content_tempfiles   z%ActionModule._create_content_tempfilecCs|dur t|dSdSr)r3r)rmr'rrrrrsz0ActionModule._remove_tempfile_if_content_definedNc s|durt}tt|||}~dD]}|jj|ddur'td|dq|jjdd}|jjdd}|jjdd}t|jjdd d d }t|jjd d d d } d |d <|sg|durgd|d<n'|snd|d<n |ry|duryd|d<n|dur|dur| drd|d<n|d =|d r| |Sd} |durzt |tst |t r| t|} n| |} | }Wnty} zd |d <dt| |d<| |WYd} ~ Sd} ~ ww|r||jd|d| |S| tjj} z|d|}Wn(ty&} zd |d <t| |d<t|d<| |WYd} ~ Sd} ~ ww| | tjjkrG|dtjjkrA|dd}n|tjj}gggd}tjt|ddrst|| |jj j!d}|jj !|sr|jj "|d}n |tj#|fg|d<d }td d}d }|$|}t%}|dD]o\}}|d rd }n t|jjd!d d d }|&|||| |||}|durq|d r||| |Stj'|}d}|D]}tj(|||)|qd"|vr|d"s|d"=d }|p|d#d }q|d D]U\}}||vrqt*|jj}tj(|||d$<d%|d&<|jjd'd|d(<d |d)<|d=|jd*||d+}|d rP||| |Sd }|pZ|d#d }q|d,D]\\}}t*|jj}tj(|||d$<||d<d-|d&<d |d.<|d rd |d!<|d(dd/kr|+d(|jd*||d+}d }|d r||| |S|p|d#d }qa|rt,|dd0kr||d$|vrd|vr|d$|d<n |t|||d1|-|jj j.| |S)2z& handler for file transfer operations N)rrzInvalid parameter specified: ""rr'r remote_srcFrprZTrvzsrc (or content) is requiredrwzdest is requiredz&src and content are mutually exclusiver0r~z%could not write content temp file: %sr)rrr+ exceptionr/r*surrogate_or_strict)errors)rZr`r.)rr,r{rurr directoryrdirectory_moderxrrrr-linkrryr1)rrr)/r!superrdrunrgrirlrr r\rorklistrjsondumpsrr rrr3rrA _find_needlerr traceback format_excr}rrcrrrrr^_remote_expand_userr>rr@r5rDr%poprC_remove_tmp_pathr)rmtmprrninternalsourcer'rrrZrrtrailing_slashr source_filesrrmodule_executedimplicit_directoriesrrr{pathsdir_path dir_componentr dest_pathr target_path __class__rrrs                                 zActionModule.run)NN) __name__ __module__ __qualname__TRANSFERS_FILESrorrrr __classcell__rrrrrds#rd)NFN)# __future__rrr3os.pathr;rransiblerransible.errorsrrransible.module_utils.basicr+ansible.module_utils.common.text.convertersrr r )ansible.module_utils.parsing.convert_boolr ansible.plugins.actionr ansible.utils.hashingr r_rrErr%r)rcrdrrrrs,