
    Vh$s                    .   d Z 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 ddlmZ ddlmZ ddlmZ dd	lmZ ej,                  rdd
lmZmZmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddlm%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+ ddl,m-Z- ddl,m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z;  e6       Z<dZ= G d d      Z>d Z?d Z@ e- e.dd d!"      e$#      d-d$       ZAd.d%ZB	 d/d&ZC	 d/d'ZD	 d/d(ZEd) ZFd* ZGd+ ZHed,        ZIy)0z7Concrete collection candidate management helper module.    )annotationsN)contextmanager)sha256)URLError)	urldefrag)rmtree)mkdtemp)	Candidate
CollectionRequirement)GalaxyToken)context)AnsibleError) get_collections_galaxy_meta_info)should_retry_error)_GALAXY_YAML)
user_agent)to_bytes	to_nativeto_text)retry_with_delays_and_condition)generate_jittered_backoff)get_bin_path)	yaml_load)open_url)Display)SentinelzMANIFEST.jsonc                      e Zd ZdZddZed        Zed        Zed        Zed        Z	e	j                  d        Z	d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zee	 	 	 	 	 dd              Zy)ConcreteArtifactsManagera  Manager for on-disk collection artifacts.

    It is responsible for:
        * downloading remote collections from Galaxy-compatible servers and
          direct links to tarballs or SCM repositories
        * keeping track of local ones
        * keeping track of Galaxy API tokens for downloads from Galaxy'ish
          as well as the artifact hashes
        * keeping track of Galaxy API signatures for downloads from Galaxy'ish
        * caching all of above
        * retrieving the metadata out of the downloaded artifacts
    Nc                    || _         i | _        i | _        i | _        i | _        i | _        || _        i | _        || _        || _	        || _
        || _        d| _        y)z;Initialize ConcreteArtifactsManager caches and constraints.TN)_validate_certs_artifact_cache_galaxy_artifact_cache_artifact_meta_cache_galaxy_collection_cache_galaxy_collection_origin_cache_b_working_directory_supplemental_signature_cache_keyringtimeout_required_signature_count_ignore_signature_errors_require_build_metadata)selfb_working_directoryvalidate_certskeyringr*   required_signature_countignore_signature_errorss          c/home/dcms/DCMS/lib/python3.12/site-packages/ansible/galaxy/collection/concrete_artifact_manager.py__init__z!ConcreteArtifactsManager.__init__@   sj      .!&(#$&!(*%/1,$7!-/*)A&(?%'+$    c                    | j                   S N)r)   r.   s    r4   r1   z ConcreteArtifactsManager.keyringQ   s    }}r6   c                    | j                   S r8   )r+   r9   s    r4   #required_successful_signature_countz<ConcreteArtifactsManager.required_successful_signature_countU   s    ---r6   c                6    | j                   g S | j                   S r8   )r,   r9   s    r4   r3   z0ConcreteArtifactsManager.ignore_signature_errorsY   s    ((0I,,,r6   c                    | j                   S r8   r-   r9   s    r4   require_build_metadataz/ConcreteArtifactsManager.require_build_metadata_   s     +++r6   c                    || _         y r8   r>   )r.   values     r4   r?   z/ConcreteArtifactsManager.require_build_metadatad   s     (-$r6   c           	     $   |j                   j                  }	 | j                  |   d   }| j                  |   \  }}d|j                  |j                  |j                  ||||dS # t        $ r!}t        dj                  |            |d }~ww xY w)Nr   z#The is no known source for {coll!s}collz1.0.0)format_version	namespacenameversionserverversion_urldownload_url
signatures)
src
api_serverr%   r&   KeyErrorRuntimeErrorformatrF   rG   ver)r.   
collectionrI   rK   signatures_urlrL   key_errs          r4   get_galaxy_artifact_source_infoz8ConcreteArtifactsManager.get_galaxy_artifact_source_infoi   s    **	88DQGL)-)M)Mj)Y&NJ &#--OO!~~)($	
 		
  	5J' 	s   $A% %	B.B

Bc           	     H   	 | j                   |   S # t        $ r Y nw xY w	 | j                  |   \  }}}n-# t        $ r!}t        dj	                  |            |d}~ww xY wt
        j                  dj	                  |             	 t        || j                  || j                  |      }t
        j                  dj	                  ||j                  xs d|j                  |j                  j                  nd	
             n# t        $ r>}t        dj	                  t        |j                        t        |                  |d}~wt         $ r>}t        dj	                  t        |j                        t        |                  |d}~ww xY w|| j                   |<   |S )zGiven a Galaxy-stored collection, return a cached path.

        If it's not yet on disk, this method downloads the artifact first.
        z%There is no known source for {coll!s}rC   NzFFetching a collection tarball for '{collection!s}' from Ansible GalaxyrS   )expected_hashr0   tokenz=Collection '{coll!s}' obtained from server {server!s} {url!s}Galaxy )rD   rI   urlGFailed to download collection tar from '{coll_src!s}': {download_err!s}coll_srcdownload_errzmFailed to download collection tar from '{coll_src!s}' due to the following unforeseen error: {download_err!s})r#   rO   r%   rP   rQ   displayvvvv_download_filer'   r!   vvvrM   rN   r   r   r   	Exception)r.   rS   r]   sha256_hashrZ   rU   b_artifact_patherrs           r4   get_galaxy_artifact_pathz1ConcreteArtifactsManager.get_galaxy_artifact_path   s   	..z:: 			&*&C&CJ&O#Ce 	7J' 	 	#VzV:	

#	,)))#33O6 KK,,2F#JNN,Fh5?^^5O
11 -3 -)  	8&z~~6!*3     		# &z~~6!*3  	 		( 3B##J/sD    	5 	AAA$D 	F9EF9FFc           	     6   	 | j                   |j                     S # t        $ r Y nw xY w|j                  rt        j                  dj                  |j                               	 t        |j                  | j                  d| j                  | j                        }n# t        $ r>}t        dj                  t        |j                        t        |                  |d}~ww xY w|j                  r,t!        |j                  |j"                  | j                        }n_|j$                  s|j&                  s|j(                  rt+        |j                        }n%t-        dj                  |j.                              || j                   |j                  <   |S )	zGiven a concrete collection pointer, return a cached path.

        If it's not yet on disk, this method downloads the artifact first.
        zBCollection requirement '{collection!s}' is a URL to a tar artifactrX   N)rY   r0   r*   r^   r_   z2The artifact is of an unexpected type {art_type!s})art_type)r"   rM   rO   is_urlrb   rc   rQ   fqcnrd   r'   r!   r*   rf   r   r   is_scm_extract_collection_from_gitrR   is_fileis_dir
is_subdirsr   rP   type)r.   rS   rh   ri   s       r4   get_artifact_pathz*ConcreteArtifactsManager.get_artifact_path   sj   	''
77 		 LL$$*FjooF$F"0NN--"&#'#7#7 LL#  "<F!*:>>!:%.s^    :))O
 :#4#4
8M8M&z~~6O D
0 
 0?Z^^,s$    	''&8B 	C&(9C!!C&c                ^    |j                   r| j                  |      S | j                  |      S r8   )is_concrete_artifactru   rj   r.   rS   s     r4   get_artifact_path_from_unknownz7ConcreteArtifactsManager.get_artifact_path_from_unknown   s-    **))*55,,Z88r6   c                *    | j                  |      d   S )NrF   get_direct_collection_metarx   s     r4    _get_direct_collection_namespacez9ConcreteArtifactsManager._get_direct_collection_namespace  s    ..z:;GGr6   c                *    | j                  |      d   S )NrG   r{   rx   s     r4   _get_direct_collection_namez4ConcreteArtifactsManager._get_direct_collection_name	  s    ..z:6BBr6   c                ~    |j                   rydj                  | j                  |      | j                  |      f      S )zExtract FQCN from the given on-disk collection artifact.

        If the collection is virtual, ``None`` is returned instead
        of a string.
        N.)
is_virtualjoinr}   r   rx   s     r4   get_direct_collection_fqcnz3ConcreteArtifactsManager.get_direct_collection_fqcn  sB       xx11*=,,Z8
  	r6   c                *    | j                  |      d   S )z;Extract version from the given on-disk collection artifact.rH   r{   rx   s     r4   get_direct_collection_versionz6ConcreteArtifactsManager.get_direct_collection_version  s     ..z:9EEr6   c                6    | j                  |      d   }|i }|S )z8Extract deps from the given on-disk collection artifact.dependenciesr{   )r.   rS   collection_dependenciess      r4   "get_direct_collection_dependenciesz;ConcreteArtifactsManager.get_direct_collection_dependencies"  s,     #'"A"A*"Mn"]"*&(#&&r6   c                r   	 | j                   |j                     S # t        $ r | j                  |      }Y nw xY w|j                  s|j
                  rt        |      }n|j                  rN	 t        || j                        }n# t        $ r*}t        dj                  t        |                  |d}~ww xY w|j                  rddt        |      didd}nF|j                  r4ddt         j#                  t%        t        |j&                        d      dd}nt(        || j                   |j                  <   |S )z8Extract meta from the given on-disk collection artifact.z/Failed to find the collection dir deps: {err!s})ri   N*)rG   rF   r   rH   )r$   rM   rO   ru   rm   rq   _get_meta_from_tarrr   _get_meta_from_dirr?   LookupErrorr   rQ   r   ro   rs   dictfromkeysmapnamespace_collection_pathsrP   )r.   rS   rh   collection_meta
lookup_errs        r4   r|   z3ConcreteArtifactsManager.get_direct_collection_meta*  s7   	A,,Z^^<< 	A"44Z@O	A 
 2 20AO""4_dFaFa"b ""EFy4F5 """
 !!*?!;S A	O ""! $	:#H#HI! 	O 4C!!*..1s$    88,B 	B6%B11B6c                J    |||f| j                   |<   ||f| j                  |<   y)zStore collection URL, SHA256 hash and Galaxy API token.

        This is a hook that is supposed to be called before attempting to
        download Galaxy-based collections with ``get_galaxy_artifact_path()``.
        N)r%   r&   )r.   rS   r]   rg   rZ   rT   rL   s          r4   save_collection_sourcez/ConcreteArtifactsManager.save_collection_sourceU  s0     58e4K%%j1;I:;U,,Z8r6   c              #     K   t        t        |d            }t        |d      }	  | |||||       t        |       y# t        |       w xY ww)a  Custom ConcreteArtifactsManager constructor with temp dir.

        This method returns a context manager that allocates and cleans
        up a temporary directory for caching the collection artifacts
        during the dependency resolution process.
        surrogate_or_stricterrors)dir)r1   r2   r3   N)r	   r   r   )	clstemp_dir_baser0   r1   r2   r3   r?   	temp_pathb_temp_paths	            r4   under_tmpdirz%ConcreteArtifactsManager.under_tmpdir_  s_     & /DE
	 y1FG		 )A(?  ;F;s   %AA AAA)TN<   NN)TNNNT)__name__
__module____qualname____doc__r5   propertyr1   r;   r3   r?   setterrV   rj   ru   ry   r}   r   r   r   r   r|   r   classmethodr   r    r6   r4   r   r   3   s    ,"   . . - -
 , , ""- #-
0>@<|9HC F
')VV   %)$(#'    r6   r   c                   d| v r| j                  dd      \  } }n	|dk(  s|sd}| j                  d      r| dd }n| }t        |      \  }}|j                  t        j
                  j                        }|j                  t        j
                  j                  dz         r-|j                  t        j
                  j                        d	   }n5d
|vrd|vr|}n*|j                  d      d   }|j                  d      r|dd }||||fS )z>Extract name, version, path and subdir out of the SCM pointer.,   r   HEADzgit+   Nz.gitz://@/)split
startswithr   stripospathsependswith)rS   rH   r   fragmentrG   s        r4   	parse_scmr     s    
j(..sA6
G	CwV$!"~t_ND(~~bggkk*H}}RWW[[6)*zz"''++&r*	d	s$zz#r"== 9D$((r6   c           	     t   t        | |      \  }}}}t        |t        |d            }	 t        d      }|dk(  r|dd	|t        |      g}
n|d|t        |      g}
t        j                  d
   st        j                  r|
j                  ddg       	 t        j                  |
       |dt        |      f}	 t        j                  ||       |r)t"        j$                  j'                  |t        |            S |S # t        $ r*}	t        dj                  t        |                  |	d }	~	ww xY w# t        j                   $ r*}t        dj                  t        |                  |d }~ww xY w# t        j                   $ r4}t        dj                  t        |      t        |                  |d }~ww xY w)Nr   r   r   prefixgitz_Could not find git executable to extract the collection from the Git repository `{repo_url!s}`.)repo_urlr   clonez	--depth=1ignore_certsz-czhttp.sslVerify=falsez5Failed to clone a Git repository from `{repo_url!s}`.checkout)cwdz\Failed to switch a cloned Git repo `{repo_url!s}` to the requested revision `{commitish!s}`.)	commitishr   )r   r	   r   r   
ValueErrorr   rQ   r   r   r   CLIARGSCGALAXY_IGNORE_CERTSextend
subprocess
check_callCalledProcessErrorr   r   r   )r   coll_verb_pathrG   rH   git_urlr   b_checkout_pathgit_executableri   git_clone_cmdproc_errgit_switch_cmds                r4   rp   rp     s   '08'D$D'7H%:;O
%e, &'+wP_H`a''7?;ST ~&!*?*?d$:;<m, $Z1AAN
n/B  	_hx&89(K  mFIg.F/
 	$ (( CFIg.F/
 	 (( 9F#G,"7+  
 	sG   C: D0 6E0 :	D-%D((D-0E-%E((E-0F7/F22F7      (   )retries
delay_basedelay_threshold)backoff_iteratorr   c                   t        | j                  dd      d   d      }|d t        d        }t        |dj	                  |df            }t
        j                  j	                  ||      }	t        j                  d	| d
t        |             	 t        t        | d      ||d n|j                         dgt               |      }
t        |	d      5 }t!        |
|      }d d d        |r6t        j#                  dj%                  |             ||k7  rt        d      |	S # t        $ r}t        t        |      |      d }~ww xY w# 1 sw Y   jxY w)Nr   r   r   r   z.tar.gz   -r6   r   zDownloading z to Authorization)r0   headersunredirected_headers
http_agentr*   )orig_excwb)write_tozTValidating downloaded file hash {actual_hash!s} with expected hash {expected_hash!s})actual_hashrY   z+Mismatch artifact hash with downloaded file)r   rsplitlenr	   r   r   r   rb   r   r   r   r   r   rf   r   open_consume_filerc   rQ   )r]   r   rY   r0   rZ   r*   b_tarball_nameb_file_nameb_tarball_dirb_file_pathrespri   download_filer   s                 r4   rd   rd     sR    

31&;N !!13y>/2Kyy+s+,M
 '',,}n=KOOc7=3IJK	9c"78)!MDu}}"1!2z|
 
k4	  BM#D=AB .F{-FH	

 K'LMM  99S>C889B Bs$   7D& E&	E
/EE
Ec                    d}t               }| j                  |      }|rH|!|j                  |       |j                          |j	                  |       | j                  |      }|rH|j                         S )Ni   )r   readwriteflushupdate	hexdigest)	read_fromr   bufsizesha256_digestdatas        r4   r   r     sm    GHM>>'"D
NN4 NNT"~~g&  ""$$r6   c                   t               }t               }t               }t               }t               }t               }|D ]V  }	|	j                  dd      r|j                  |	d          ||||d|	j                  dd         }
|
j                  |	d          X t	        ||z  |z  |z  |z        }t        | j                               }|j                  |      }|rVdt        |      dd	j                  t        |            }|rt        |      t        j                  |       t        |      |j                  |      }t        |      d
kD  r3t        j                  dt        |      dd	j                  |             |D ]  }|| vsd | |<    |D ]3  }| j                  |d       }|g | |<   t!        |t"              r.|g| |<   5 |D ]  }|| vsi | |<    |D ]  }|| vst$        | |<    | j                  d      sd| d<   | S )NrequiredFkey)strlistr   sentinelrt   r   The collection galaxy.yml at 'z+' is missing the following mandatory keys: z, r   z0Found unknown keys in collection galaxy.yml at 'z': rH   r   )r   setgetadd	frozensetkeys
differencer   r   sortedr   rb   warningr   r   r   
isinstancer  r   )
galaxy_ymlb_galaxy_yml_pathr?   galaxy_yml_schemamandatory_keysstring_keys	list_keys	dict_keyssentinel_keysinfokey_list_typeall_keysset_keysmissing_keysmsg
extra_keysoptional_stringoptional_listlist_valoptional_dictoptional_sentinels                        r4   _normalize_galaxy_yml_manifestr!    sE    	)* 
 UN%KIIEM! 
'88J&tE{+ %	

 ((65
!# 	$u+&
' +5	AIMP]]^H:??$%H!,,X6L *+TYYvl7K-LN 	 "s##o$$X.J
:"#45tyy7LN 	O ' /*,*.J'/ # 3>>-6(*J}%Hd+)1
J}%3 # +
*(*J}%+ + 5J.,4J()5 >>)$ #
9r6   c                P    	 t        |       S # t        $ r t        | |      cY S w xY wr8   )_get_meta_from_installed_dirr   _get_meta_from_src_dir)r   r?   s     r4   r   r   `  s2    F+F33 F%f.DEEFs   
 %%c           
        t         j                  j                  | t              }t         j                  j	                  |      s$t        dj                  t        |                  t        |d      5 }	 t        |      }	 d d d        t        t              sT|rt        dt        |       d      t         j#                  dt        |       d       t%        dt        |       d      t'        |||      S # t        j                  j                  $ r4}t        dj                  t        |      t        |                  |d }~ww xY w# 1 sw Y   xY w)Nz9The collection galaxy.yml path '{path!s}' does not exist.r   rbzRFailed to parse the galaxy.yml at '{path!s}' with the following error:
{err_txt!s})r   err_txtr  z' is incorrectly formatted.)r   r   r   r   isfiler   rQ   r   r   r   yamlerror	YAMLErrorr   r  r   rb   r  r   r!  )r   r?   r  manifest_file_objmanifestyaml_errs         r4   r$  r$  j  sC    fl3J77>>*%GF	*-F.
 	

 
j$	 #4
	 !23H h%!!?	*@U?VVqrss8:9N8OOjkl9)J:O9PPklmm)(J@VWW# zz## 	4":.%h/   	 s*   4E6C;;E/EEEEc           	        t         j                  j                  | t        |d            }	 t	        |d      5 }|j                         }d d d        t        d      }	 t        j                  |      }|S # 1 sw Y   .xY w# t        t        f$ r& t        dj                  |t        |                  w xY w# t        $ r t        dj                  |            w xY w)Nr   r   r'  z;The collection {manifest!s} path '{path!s}' does not exist.)r.  r   KCollection tar file member {member!s} does not contain a valid json string.member)r   r   r   r   r   r   IOErrorOSErrorr   rQ   r   r   jsonloadsr   r   )r   filenameb_json_filepathmanifest_fdb_json_textmanifest_txtr.  s          r4   _get_json_from_installed_dirr=    s    
 ggll68HEZ+[\O

/4( 	-K%**,K	- ;/DEL
::l+ O-	- 	-W 
IF!/  
 	

  
+F(F#
 	

s.   B A7
B  B; 7B <B 5B8;%C c                    t        | t              }|d   }|j                  d      }|s<t        dj	                  t        t        |       t        t        |                        |S )Ncollection_inforH   zCollection metadata file `{manifest_filename!s}` at `{meta_file!s}` is expected to have a valid SemVer version value but got {version!s})manifest_filename	meta_filerH   )r=  MANIFEST_FILENAMEr  r   rQ   r   repr)r   r.  r?  rH   s       r4   r#  r#    so     ,F4EFH01O!!),GHF"3!&/W.  
 	
 r6   c           	     8   t         j                  j                  |       st        dt	        |        d      t        j                  |       s$t        dj                  t	        |                   t        j                  | d      5 }	 |j                  t              }t        ||      5 \  }}|t        d	j                  t        
            t        |j                         d      }	 t        j                   |      }|d   cd d d        cd d d        S # t        $ r* t        dj                  t	        |       t                    w xY w# t"        $ r  t        dj                  t        
            w xY w# 1 sw Y   nxY w	 d d d        y # 1 sw Y   y xY w)Nz,Unable to find collection artifact file at 'z'.z:Collection artifact at '{path!s}' is not a valid tar file.r&  r)modezNCollection at '{path!s}' does not contain the required file {manifest_file!s}.)r   manifest_filez6Collection tar file does not contain member {member!s}r2  r   r   r1  r?  )r   r   existsr   r   tarfile
is_tarfilerQ   r   	getmemberrB  rO   _tarfile_extractr   r   r6  r7  r   )r   collection_tarr3  _member
member_objtext_contentr.  s          r4   r   r     s    77>>&!:9V;L:MRP
 	
 f%HF	&)F*
 	

 
f3	' !/>
	#--.?@F nf5 	/9N':!"((.6G(H 
 #!,L
::l3 -.)	/ 	/!/ !/  	3"6*"3   	0  "3F"3F4 	/ 	/ 	/!/ !/ !/sU   F
DF+A E:,EE:	F3EF)E77E::F	?FFc              #     K   | j                  |      }	 ||f ||j                          y y # ||j                          w w xY wwr8   )extractfileclose)tarr3  tar_objs      r4   rL  rL    sM      oof%GgoMMO 7MMO s   A/ AAA)Nr   r8   )T)Jr   
__future__r   r6  r   rI  r   typingtr*  
contextlibr   hashlibr   urllib.errorr   urllib.parser   shutilr   tempfiler	   TYPE_CHECKING0ansible.galaxy.dependency_resolution.dataclassesr
   r   r   ansible.galaxy.tokenr   ansibler   ansible.errorsr   ansible.galaxyr   ansible.galaxy.apir   r   ansible.galaxy.user_agentr   +ansible.module_utils.common.text.convertersr   r   r   ansible.module_utils.apir   r   #ansible.module_utils.common.processr    ansible.module_utils.common.yamlr   ansible.module_utils.urlsr   ansible.utils.displayr   ansible.utils.sentinelr   ansible.constants	constantsr   rb   rB  r   r   rp   rd   r   r!  r   r$  r=  r#  r   rL  r   r6   r4   <module>rp     s   > "  	     %  ! "  ??  1  ' ; 1 I 0 T T D > < 6 . ) +  )# L  L ^
)61j !.qQXZ[))	)X%$  $Lb  $F  $XDB*//d 
 
r6   