o
    .&ßaÌW  ã                   @   sž  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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 d dlZe  e¡Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Z			dQdd„Zdd„ Zdd„ Zedd„ ƒZdd„ Z ed d!„ ƒZ!d"d#„ Z"G d$d%„ d%e#ƒZ$G d&d'„ d'e$ƒZ%G d(d)„ d)e$ƒZ&G d*d+„ d+e$ƒZ'G d,d-„ d-e$ƒZ(G d.d/„ d/e$ƒZ)G d0d1„ d1e$ƒZ*G d2d3„ d3e$ƒZ+G d4d5„ d5e$ƒZ,G d6d7„ d7e%ƒZ-G d8d9„ d9e%ƒZ.G d:d;„ d;e%ƒZ/G d<d=„ d=e%ƒZ0G d>d?„ d?e$ƒZ1G d@dA„ dAe$ƒZ2G dBdC„ dCe$ƒZ3G dDdE„ dEe%ƒZ4G dFdG„ dGe$ƒZ5G dHdI„ dIe5ƒZ6G dJdK„ dKe$ƒZ7e&e'e(e)e*e+e,e.e-e/e5e6e1e0e7e4gZ8e2e3gZ9dLdM„ Z:dNe:iZ;G dOdP„ dPe#ƒZ<dS )Ré    N)Úsix)Úset_value_from_jmespath)Úurlparse)Úcontextmanager)Ú
exceptions)Ú	yaml_dumpÚ
yaml_parsec                 C   s   t | tjƒS ©N)Ú
isinstancer   Ústring_types©Úpath© r   úX/usr/lib/python3/dist-packages/awscli/customizations/cloudformation/artifact_exporter.pyÚis_path_value_valid#   s   r   c                 C   s.   t |ƒrtj |¡stj tj | |¡¡S |S r	   )r   Úosr   ÚisabsÚnormpathÚjoin)Ú	directoryr   r   r   r   Úmake_abs_path'   s   r   c                 C   s$   zt | ƒ W dS  ty   Y dS w )NTF)Úparse_s3_urlÚ
ValueError)Úurlr   r   r   Ú	is_s3_url.   s   ÿr   c                 C   ó   t | ƒo	tj | ¡S r	   )r   r   r   Úisdirr   r   r   r   Úis_local_folder6   ó   r   c                 C   r   r	   )r   r   r   Úisfiler   r   r   r   Úis_local_file:   r   r    c                 C   s   t | ƒot | ¡S r	   )r   ÚzipfileÚ
is_zipfiler   r   r   r   Úis_zip_file>   s   þr#   ÚBucketÚKeyc                 C   s¢   t | tjƒrJ|  d¡rJt | dd … ¡}t |j¡}|jrJ|jrJt	ƒ }|j||< |j 
d¡||< |d urHd|v rHt|d ƒdkrH|d d ||< |S td | ¡ƒ‚)Nzs3://é   ú/Ú	versionIdé   r   z7URL given to the parse method is not a valid S3 url {0})r
   r   r   Ú
startswithr   Úparse_qsÚqueryÚnetlocr   ÚdictÚlstripÚlenr   Úformat)r   Úbucket_name_propertyÚobject_key_propertyÚversion_propertyÚparsedr,   Úresultr   r   r   r   D   s"   ÿ
ÿr   c                 C   st   t  ||¡}|du r|}t|ƒrt d || ¡¡ |S t||ƒ}t|ƒr)t||ƒS t	|ƒr2| 
|¡S tj| ||d�‚)aD  
    Upload local artifacts referenced by the property at given resource and
    return S3 URL of the uploaded object. It is the responsibility of callers
    to ensure property value is a valid string

    If path refers to a file, this method will upload the file. If path refers
    to a folder, this method will zip the folder and upload the zip to S3.
    If path is omitted, this method will zip the current working folder and
    upload.

    If path is already a path to S3 object, this method does nothing.

    :param resource_id:     Id of the CloudFormation resource
    :param resource_dict:   Dictionary containing resource definition
    :param property_name:   Property name of CloudFormation resource where this
                            local path is present
    :param parent_dir:      Resolve all relative paths with respect to this
                            directory
    :param uploader:        Method to upload files to S3

    :return:                S3 URL of the uploaded object
    :raise:                 ValueError if path is not a S3 URL or a local path
    Nz'Property {0} of {1} is already a S3 URL©Úresource_idÚproperty_nameÚ
local_path)ÚjmespathÚsearchr   ÚLOGÚdebugr1   r   r   Úzip_and_uploadr    Úupload_with_dedupr   ÚInvalidLocalPathError)r8   Úresource_dictr9   Ú
parent_dirÚuploaderr:   r   r   r   Úupload_local_artifactsd   s$   ÿ


ýrE   c                 C   s6   t | ƒ�}| |¡W  d   ƒ S 1 sw   Y  d S r	   )Ú
zip_folderr@   )r:   rD   r!   r   r   r   r?   �   s   
$ÿr?   c              	   c   sj   � t j t ¡ dt ¡ j ¡}t|| ƒ}z|V  W t j 	|¡r&t  
|¡ dS dS t j 	|¡r4t  
|¡ w w )zÇ
    Zip the entire folder and return a file to the zip. Use this inside
    a "with" statement to cleanup the zipfile after it is used.

    :param folder_path:
    :return: Name of the zipfile
    zdata-N)r   r   r   ÚtempfileÚ
gettempdirÚuuidÚuuid4ÚhexÚmake_zipÚexistsÚremove)Úfolder_pathÚfilenameÚzipfile_namer   r   r   rF   ¢   s   €
ÿ
ÿÿrF   c              	   C   sÜ   d  | ¡}tj |¡}t|dƒ�T}t |dtj¡}t 	|¡�.}tj
|dd�D ]\}}}|D ]} tj || ¡}	tj |	|¡}
| |	|
¡ q-q&W d   ƒ n1 sOw   Y  W d   ƒ |S W d   ƒ |S 1 sgw   Y  |S )Nz{0}.zipÚwbÚwT)Úfollowlinks)r1   r   r   ÚabspathÚopenr!   ÚZipFileÚZIP_DEFLATEDÚ
contextlibÚclosingÚwalkr   ÚrelpathÚwrite)rP   Úsource_rootrQ   ÚfÚzip_fileÚzfÚrootÚdirsÚfilesÚ	full_pathÚrelative_pathr   r   r   rL   ·   s,   
ÿüÿÿ
þ
ø
þ
ö
rL   c               	   c   sŠ   � t  ¡ } tj | t ¡ j¡}z(t|dƒ�}|V  W d   ƒ n1 s#w   Y  W tj 	|¡r6t 
|¡ d S d S tj 	|¡rDt 
|¡ w w )Nzw+)rG   rH   r   r   r   rI   rJ   rK   rV   rM   rN   )r   rP   Úhandler   r   r   Ú
mktempfileÇ   s   €ÿ€ÿÿrh   c                 C   s.   t  ¡ }tj |tj | ¡¡}t | |¡ |S r	   )rG   Úmkdtempr   r   r   ÚbasenameÚshutilÚcopy)ÚfilepathÚtmp_dirÚdstr   r   r   Úcopy_to_temp_dirÔ   s   rp   c                   @   s8   e Zd ZdZdZdZdZdZdd„ Zdd„ Z	d	d
„ Z
dS )ÚResourcezP
    Base class representing a CloudFormation resource that can be exported
    NTFc                 C   s
   || _ d S r	   )rD   ©ÚselfrD   r   r   r   Ú__init__ç   s   
zResource.__init__c              
   C   sô   |d u rd S t  | j|¡}|s| jsd S t|tƒr%t d | j|¡¡ d S d }t	|ƒr=t
|ƒs=| jr=t|ƒ}t|| j|ƒ z3z	|  |||¡ W n tyd } ztjd|d� tj|| j||d�‚d }~ww W |rot |¡ d S d S |ryt |¡ w w )Nz)Property {0} of {1} resource is not a URLzUnable to export)Úexc_info)r8   r9   Úproperty_valueÚex)r;   r<   ÚPROPERTY_NAMEÚPACKAGE_NULL_PROPERTYr
   r.   r=   r>   r1   r    r#   Ú	FORCE_ZIPrp   r   Ú	do_exportÚ	Exceptionr   ÚExportFailedErrorrk   Úrmtree)rs   r8   rB   rC   rv   Útemp_dirrw   r   r   r   Úexportê   sH   


ÿÿÿü€þþ
ÿÿzResource.exportc                 C   s&   t ||| j|| jƒ}t|| j|ƒ dS )z|
        Default export action is to upload artifacts and set the property to
        S3 URL of the uploaded object
        N)rE   rx   rD   r   )rs   r8   rB   rC   Úuploaded_urlr   r   r   r{     s
   þzResource.do_export)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚRESOURCE_TYPErx   ry   rz   rt   r€   r{   r   r   r   r   rq   Û   s    $rq   c                       s4   e Zd ZdZdZdZdZ‡ fdd„Zdd„ Z‡  Z	S )ÚResourceWithS3UrlDictz‰
    Represents CloudFormation resources that need the S3 URL to be specified as
    an dict like {Bucket: "", Key: "", Version: ""}
    Nc                    ó   t t| ƒ |¡ d S r	   )Úsuperr‡   rt   rr   ©Ú	__class__r   r   rt   #  r   zResourceWithS3UrlDict.__init__c                 C   s<   t ||| j|| jƒ}t|| j| j| jd�}t|| j|ƒ dS )zq
        Upload to S3 and set property to an dict representing the S3 url
        of the uploaded object
        )r2   r3   r4   N)rE   rx   rD   r   ÚBUCKET_NAME_PROPERTYÚOBJECT_KEY_PROPERTYÚVERSION_PROPERTYr   )rs   r8   rB   rC   Úartifact_s3_urlÚ
parsed_urlr   r   r   r{   &  s   þÿüzResourceWithS3UrlDict.do_export)
r‚   rƒ   r„   r…   rŒ   r�   rŽ   rt   r{   Ú__classcell__r   r   rŠ   r   r‡     s    r‡   c                   @   ó   e Zd ZdZdZdZdS )ÚServerlessFunctionResourcezAWS::Serverless::FunctionÚCodeUriTN©r‚   rƒ   r„   r†   rx   rz   r   r   r   r   r“   9  ó    r“   c                   @   r’   )ÚServerlessApiResourcezAWS::Serverless::ApiÚDefinitionUriFN©r‚   rƒ   r„   r†   rx   ry   r   r   r   r   r—   ?  ó    r—   c                   @   r’   )ÚGraphQLSchemaResourcezAWS::AppSync::GraphQLSchemaÚDefinitionS3LocationFNr™   r   r   r   r   r›   G  rš   r›   c                   @   r’   )Ú&AppSyncResolverRequestTemplateResourceúAWS::AppSync::ResolverÚ RequestMappingTemplateS3LocationFNr™   r   r   r   r   r�   O  rš   r�   c                   @   r’   )Ú'AppSyncResolverResponseTemplateResourcerž   Ú!ResponseMappingTemplateS3LocationFNr™   r   r   r   r   r    W  rš   r    c                   @   r’   )Ú3AppSyncFunctionConfigurationRequestTemplateResourceú#AWS::AppSync::FunctionConfigurationrŸ   FNr™   r   r   r   r   r¢   _  rš   r¢   c                   @   r’   )Ú4AppSyncFunctionConfigurationResponseTemplateResourcer£   r¡   FNr™   r   r   r   r   r¤   g  rš   r¤   c                   @   ó$   e Zd ZdZdZdZdZdZdZdS )ÚLambdaFunctionResourcezAWS::Lambda::FunctionÚCodeÚS3BucketÚS3KeyÚS3ObjectVersionTN©	r‚   rƒ   r„   r†   rx   rŒ   r�   rŽ   rz   r   r   r   r   r¦   o  ó    r¦   c                   @   r¥   )ÚApiGatewayRestApiResourcezAWS::ApiGateway::RestApiÚBodyS3LocationFr$   r%   ÚVersionN)	r‚   rƒ   r„   r†   rx   ry   rŒ   r�   rŽ   r   r   r   r   r­   x  r¬   r­   c                   @   s    e Zd ZdZdZdZdZdZdS )Ú"ElasticBeanstalkApplicationVersionz)AWS::ElasticBeanstalk::ApplicationVersionÚSourceBundler¨   r©   N)r‚   rƒ   r„   r†   rx   rŒ   r�   rŽ   r   r   r   r   r°   �  s    r°   c                   @   r¥   )ÚLambdaLayerVersionResourcezAWS::Lambda::LayerVersionÚContentr¨   r©   rª   TNr«   r   r   r   r   r²   ‰  r¬   r²   c                   @   r’   )ÚServerlessLayerVersionResourcezAWS::Serverless::LayerVersionÚ
ContentUriTNr•   r   r   r   r   r´   ’  r–   r´   c                   @   r’   )ÚServerlessRepoApplicationReadmeú AWS::ServerlessRepo::ApplicationÚ	ReadmeUrlFNr™   r   r   r   r   r¶   ˜  r–   r¶   c                   @   r’   )Ú ServerlessRepoApplicationLicenser·   Ú
LicenseUrlFNr™   r   r   r   r   r¹   ž  r–   r¹   c                   @   r¥   )Ú+StepFunctionsStateMachineDefinitionResourcez AWS::StepFunctions::StateMachinerœ   r$   r%   r¯   FN)	r‚   rƒ   r„   r†   rx   rŒ   r�   rŽ   ry   r   r   r   r   r»   ¤  r¬   r»   c                       s0   e Zd ZdZdZdZ‡ fdd„Zdd„ Z‡  ZS )ÚCloudFormationStackResourcez{
    Represents CloudFormation::Stack resource that can refer to a nested
    stack template via TemplateURL property.
    zAWS::CloudFormation::StackÚTemplateURLc                    rˆ   r	   )r‰   r¼   rt   rr   rŠ   r   r   rt   µ  r   z$CloudFormationStackResource.__init__c                 C   sö   |  | jd¡}|du st|ƒs| d¡s| d¡rdS t||ƒ}t|ƒs-tj| j||d�‚t||| j	ƒ 
¡ }t|ƒ}tƒ �4}| |¡ | ¡  | j	 |jd¡}	t|	dd�}
| j	 |
d |
  dd¡¡}t|| j|ƒ W d  ƒ dS 1 stw   Y  dS )	zÏ
        If the nested stack template is valid, this method will
        export on the nested template, upload the exported template to S3
        and set property to URL of the uploaded S3 template
        Nzhttp://zhttps://)r9   r8   Útemplate_pathÚtemplater¯   )r4   r%   )Úgetrx   r   r*   r   r    r   Ú InvalidTemplateUrlParameterErrorÚTemplaterD   r€   r   rh   r]   Úflushr@   Únamer   Úto_path_style_s3_urlr   )rs   r8   rB   rC   r¾   Úabs_template_pathÚexported_template_dictÚexported_template_strÚtemporary_filer   ÚpartsÚs3_path_urlr   r   r   r{   ¸  s:   ÿþ
ýÿ
ÿÿ"õz%CloudFormationStackResource.do_export)	r‚   rƒ   r„   r…   r†   rx   rt   r{   r‘   r   r   rŠ   r   r¼   ­  s    r¼   c                   @   r’   )ÚServerlessApplicationResourcezx
    Represents Serverless::Application resource that can refer to a nested
    app template via Location property.
    zAWS::Serverless::ApplicationÚLocationN©r‚   rƒ   r„   r…   r†   rx   r   r   r   r   rÌ   á  s    rÌ   c                   @   r’   )Ú$GlueJobCommandScriptLocationResourcez(
    Represents Glue::Job resource.
    zAWS::Glue::JobzCommand.ScriptLocationNrÎ   r   r   r   r   rÏ   ë  s    rÏ   c                 C   s|   |   dd ¡dkr
| S |   di ¡  dd ¡}|rt|ƒrt|ƒr | S tj ||¡}t|ƒr6| |¡| d d< | S tj	dd|d�‚)NÚNamezAWS::IncludeÚ
ParametersrÍ   r7   )
rÀ   r   r   r   r   r   r    r@   r   rA   )Útemplate_dictrD   rC   Úinclude_locationÚabs_include_locationr   r   r   Ú include_transform_export_handler  s$   ÿþûýrÕ   zFn::Transformc                   @   s6   e Zd ZdZeefdd„Zdd„ Zdd„ Zdd	„ Z	d
S )rÂ   z3
    Class to export a CloudFormation template
    c           
      C   s�   t |ƒr
tj |¡std |¡ƒ‚t||ƒ}tj |¡}t|dƒ�}| 	¡ }	W d  ƒ n1 s0w   Y  t
|	ƒ| _|| _|| _|| _|| _dS )zB
        Reads the template and makes it ready for export
        z=parent_dir parameter must be an absolute path to a folder {0}ÚrN)r   r   r   r   r   r1   r   ÚdirnamerV   Úreadr   rÒ   Útemplate_dirÚresources_to_exportÚmetadata_to_exportrD   )
rs   r¾   rC   rD   rÚ   rÛ   rÆ   rÙ   rg   Útemplate_strr   r   r   rt   /  s   þ

ÿ

zTemplate.__init__c                 C   sv   |  ¡ D ]4\}}|tv rt| || j| jƒ||< qt|tƒr$|  |¡ qt|tƒr8|D ]}t|tƒr7|  |¡ q+q|S )a  
        Template params such as AWS::Include transforms are not specific to
        any resource type but contain artifacts that should be exported,
        here we iterate through the template dict and export params with a
        handler defined in GLOBAL_EXPORT_DICT
        )ÚitemsÚGLOBAL_EXPORT_DICTrD   rÙ   r
   r.   Úexport_global_artifactsÚlist)rs   rÒ   ÚkeyÚvalÚitemr   r   r   rß   G  s   



€z Template.export_global_artifactsc                 C   sX   d|vr|S |d   ¡ D ]\}}| jD ]}|j|krq|| jƒ}| ||| j¡ qq|S )zâ
        Exports the local artifacts referenced by the metadata section in
        the given template to an s3 bucket.

        :return: The template with references to artifacts that have been
        exported to s3.
        ÚMetadata)rÝ   rÛ   r†   rD   r€   rÙ   )rs   rÒ   Úmetadata_typeÚmetadata_dictÚexporter_classÚexporterr   r   r   Úexport_metadataY  s   


ûzTemplate.export_metadatac                 C   s”   |   | j¡| _d| jvr| jS |  | j¡| _| jd  ¡ D ])\}}| dd¡}| dd¡}| jD ]}|j|kr8q0|| jƒ}| ||| j	¡ q0q| jS )zÊ
        Exports the local artifacts referenced by the given template to an
        s3 bucket.

        :return: The template with references to artifacts that have been
        exported to s3.
        Ú	ResourcesÚTypeNÚ
Properties)
ré   rÒ   rß   rÝ   rÀ   rÚ   r†   rD   r€   rÙ   )rs   r8   ÚresourceÚresource_typerB   rç   rè   r   r   r   r€   n  s   



úzTemplate.exportN)
r‚   rƒ   r„   r…   ÚRESOURCES_EXPORT_LISTÚMETADATA_EXPORT_LISTrt   rß   ré   r€   r   r   r   r   rÂ   *  s    
þrÂ   )r$   r%   N)=Úloggingr   rG   r!   rY   rI   rk   Úawscli.compatr   Úbotocore.utilsr   r   r   Ú$awscli.customizations.cloudformationr   Ú/awscli.customizations.cloudformation.yamlhelperr   r   r;   Ú	getLoggerr‚   r=   r   r   r   r   r    r#   r   rE   r?   rF   rL   rh   rp   Úobjectrq   r‡   r“   r—   r›   r�   r    r¢   r¤   r¦   r­   r°   r²   r´   r¶   r¹   r»   r¼   rÌ   rÏ   rï   rð   rÕ   rÞ   rÂ   r   r   r   r   Ú<module>   sš   

ý 9

> 				4

ðþÿ