U
    n/eb                     @   s2  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mZ d dl	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d dlZd dlmZ e e!Z"G dd dej#j$Z%G dd deZ&G d	d
 d
e&eZ'G dd deZ(G dd de&eZ)G dd deZ*G dd deZ+G dd deZ,dS )    N)InvalidIMDSEndpointErrorMetadataRetrievalError) DEFAULT_METADATA_SERVICE_TIMEOUTMETADATA_BASE_URLRETRYABLE_HTTP_ERRORS	ArnParserBadIMDSRequestErrorClientErrorContainerMetadataFetcherHTTPClientErrorIMDSFetcherIMDSRegionProviderInstanceMetadataFetcherInstanceMetadataRegionFetcherReadTimeoutErrorS3RegionRedirectorS3RegionRedirectorv2get_environ_proxiesosresolve_imds_endpoint_mode)asynccontextmanagerc                       s(   e Zd Z fddZedd Z  ZS )_RefCountedSessionc                    s   t  j|| d| _d | _d S )Nr   )super__init___RefCountedSession__ref_count_RefCountedSession__lock)selfargskwargs	__class__ 5/tmp/pip-unpacked-wheel-8mnez3y6/aiobotocore/utils.pyr   '   s    z_RefCountedSession.__init__c                 C  s   | j st | _ | j 4 I d H V |  jd7  _z| jdkrH|  I d H  W n$ tk
rn   |  jd8  _ Y nX W 5 Q I d H R X z
| V  W 5 | j 4 I d H 2 | jdkr| d d d I d H  |  jd8  _W 5 Q I d H R X X d S )N   )r   asyncioLockr   
__aenter__BaseException	__aexit__)r   r!   r!   r"   acquire,   s     



z_RefCountedSession.acquire)__name__
__module____qualname__r   r   r)   __classcell__r!   r!   r   r"   r   &   s   r   c                   @   sX   e Zd ZededdddfddZdd ZdddZd	d
 Zdd Z	dd Z
dddZdS )AioIMDSFetcherr#   Nc                 C   s   || _ || _|d kri }| ||| _|| _|d kr>tj }|dd	 | _
| j
dk| _
|| _|pxt| j t| jd| _d S )NZAWS_EC2_METADATA_DISABLEDfalsetrue)timeoutproxies)_timeout_num_attemptsZ_select_base_urlZ	_base_url_configr   environcopygetlowerZ	_disabledZ_user_agentr   r   _session)r   r1   num_attemptsbase_urlenv
user_agentconfigsessionr!   r!   r"   r   G   s    

zAioIMDSFetcher.__init__c           	         s  |    | | j}d| ji}| | tjjd||d}| j	 4 I d H ^}t
| jD ]J}zz|| I d H }|jdkr|jI d H W   W  5 Q I d H R  S |jdkrW  W 5 Q I d H R  d S |jdkrt|W qZ tk
r   Y  W 5 Q I d H R  d S  tk
r8 } ztjd||dd	 W 5 d }~X Y qZ tk
r } zN|jd
}|rnt|dd dkstt|dd dkrt||dn W 5 d }~X Y qZX qZW 5 Q I d H R X d S )Nz$x-aws-ec2-metadata-token-ttl-secondsPUTmethodurlheaders   )i  i  i  )i  OCaught retryable HTTP exception while making metadata service request to %s: %sTexc_infoerrorerrno   Zos_errorzDomain name not found)endpointrJ   )_assert_enabled_construct_urlZ_TOKEN_PATHZ
_TOKEN_TTL_add_user_agentbotocore
awsrequest
AWSRequestr:   r)   ranger4   sendpreparestatus_codetextr   r   r   loggerdebugr   r   r8   getattrstrr   )	r   rD   rE   requestr@   iresponseerJ   r!   r!   r"   _fetch_metadata_tokenc   sV     
  
$

&z$AioIMDSFetcher._fetch_metadata_tokenc                    s  |    |d kr| j}| |}i }|d k	r4||d< | | | j 4 I d H }t| jD ]}zftj	j
d||d}|| I d H }	||	}
t|
r|
I d H }
|
s|	W   W  5 Q I d H R  S W q\ tk
r } ztjd||dd W 5 d }~X Y q\X q\W 5 Q I d H R X |  d S )Nzx-aws-ec2-metadata-tokenGETrB   rG   TrH   )rN   _default_retryrO   rP   r:   r)   rT   r4   rQ   rR   rS   rU   rV   inspectisawaitabler   rY   rZ   _RETRIES_EXCEEDED_ERROR_CLS)r   url_path
retry_functokenrD   rE   r@   r^   r]   r_   Zshould_retryr`   r!   r!   r"   _get_request   s<    

  

 *zAioIMDSFetcher._get_requestc                    s    |  |I d H p| |I d H S N_is_non_ok_response	_is_emptyr   r_   r!   r!   r"   rc      s
    
zAioIMDSFetcher._default_retryc                    s(   |j dkr$| j|dddI d H  dS dS )NrF   znon-200Tlog_bodyF)rW   _log_imds_responsero   r!   r!   r"   rm      s    
z"AioIMDSFetcher._is_non_ok_responsec                    s*   |j I d H s&| j|dddI d H  dS dS )Nzno bodyTrp   F)contentrr   ro   r!   r!   r"   rn      s    zAioIMDSFetcher._is_emptyFc                    sD   d}||j |jg}|r0|d7 }||jI d H  tj|f|  d S )NzHMetadata service returned %s response with status code of %s for url: %sz, content body: %s)rW   rD   appendrs   rY   rZ   )r   r_   Zreason_to_logrq   Z	statementZlogger_argsr!   r!   r"   rr      s    z!AioIMDSFetcher._log_imds_response)N)F)r*   r+   r,   r   r   r   ra   rj   rc   rm   rn   rr   r!   r!   r!   r"   r.   F   s   
.
! r.   c                   @   s@   e Zd Zdd ZdddZdddZdd	 Zd
d Zdd ZdS )AioInstanceMetadataFetcherc              
      s   z|   I d H }| |I d H }| ||I d H }| |rl||d |d |d |d d}| | |W S d|krd|krtd| i W S W nR | jk
r   td	| j Y n0 t	k
r } ztd
|j
 W 5 d }~X Y nX i S )NZAccessKeyIdZSecretAccessKeyTokenZ
Expiration)	role_nameZ
access_keyZ
secret_keyri   Zexpiry_timeCodeMessagez7Error response received when retrievingcredentials: %s.\Max number of attempts exceeded (%s) when attempting to retrieve data from metadata service.zBad IMDS request: %s)ra   _get_iam_role_get_credentialsZ_contains_all_credential_fieldsZ_evaluate_expirationrY   rZ   rf   r4   r   r]   )r   ri   rw   credentialsr`   r!   r!   r"   retrieve_iam_role_credentials   s6    


 z8AioInstanceMetadataFetcher.retrieve_iam_role_credentialsNc                    s"   | j | j| j|dI d H jI d H S Nrg   rh   ri   )rj   	_URL_PATH_needs_retry_for_role_namerX   )r   ri   r!   r!   r"   r{      s    
z(AioInstanceMetadataFetcher._get_iam_rolec                    s0   | j | j| | j|dI d H }t|jI d H S r   )rj   r   _needs_retry_for_credentialsjsonloadsrX   )r   rw   ri   rr!   r!   r"   r|      s    z+AioInstanceMetadataFetcher._get_credentialsc                    sF   zt |jI d H  W dS  tk
r@   | |dI d H  Y dS X d S )NFzinvalid jsonT)r   r   rX   
ValueErrorrr   ro   r!   r!   r"   _is_invalid_json  s    z+AioInstanceMetadataFetcher._is_invalid_jsonc                    s    |  |I d H p| |I d H S rk   rl   ro   r!   r!   r"   r     s
    
z5AioInstanceMetadataFetcher._needs_retry_for_role_namec                    s0   |  |I d H p.| |I d H p.| |I d H S rk   )rm   rn   r   ro   r!   r!   r"   r     s
    z7AioInstanceMetadataFetcher._needs_retry_for_credentials)N)N)	r*   r+   r,   r~   r{   r|   r   r   r   r!   r!   r!   r"   ru      s   !
	
ru   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )AioIMDSRegionProviderc                    s   |   I dH }|S )z#Provide the region value from IMDS.N)_get_instance_metadata_region)r   Zinstance_regionr!   r!   r"   provide  s    zAioIMDSRegionProvider.providec                    s   |   }| I d H }|S rk   )Z_get_fetcherretrieve_region)r   fetcherregionr!   r!   r"   r     s    z3AioIMDSRegionProvider._get_instance_metadata_regionc                 C   sN   | j d}| j d}| j dt| j d}t||| j| j  |d}|S )NZmetadata_service_timeoutZmetadata_service_num_attemptsec2_metadata_service_endpoint)r   Z"ec2_metadata_service_endpoint_mode)r1   r;   r=   r>   r?   )r:   Zget_config_variabler    AioInstanceMetadataRegionFetcherZ_environr>   )r   Zmetadata_timeoutZmetadata_num_attemptsZimds_configr   r!   r!   r"   _create_fetcher$  s*    z%AioIMDSRegionProvider._create_fetcherN)r*   r+   r,   r   r   r   r!   r!   r!   r"   r     s   r   c                   @   s   e Zd Zdd Zdd ZdS )r   c                    s>   z|   I d H }|W S  | jk
r8   td| j Y nX d S )Nrz   )_get_regionrf   rY   rZ   r4   )r   r   r!   r!   r"   r   @  s    
z0AioInstanceMetadataRegionFetcher.retrieve_regionc                    sD   |   I d H }| j| j| j|dI d H }|jI d H }|d d }|S )Nr   )ra   rj   r   rc   rX   )r   ri   r_   Zavailability_zoner   r!   r!   r"   r   L  s    z,AioInstanceMetadataRegionFetcher._get_regionN)r*   r+   r,   r   r   r!   r!   r!   r"   r   =  s   r   c                   @   s   e Zd Zdd Zdd ZdS )AioS3RegionRedirectorv2c                    s  |dkrdS | di  di }t| dr>td dS | drVtd dS |d  d	i }| d
}|d  di }|dko|jdk}	|dko|jdkod| di k}
|dkod|k}|d dk	o|d jdk}|dk}t|	|||
|gsdS |d d d }|d  d}| ||I dH }|dkrLtd||f  dS td|||f  || j	|< | j
j}|j||d d d |d dI dH }| |d |j|d< d|d d d< |j d}|dk	r||}|\}}||d d< |d  di ||d d< dS ) a  
        An S3 request sent to the wrong region will return an error that
        contains the endpoint the request should be sent to. This handler
        will add the redirect information to the signing context and then
        redirect the request.
        NcontextZs3_redirectbucketzBS3 request was previously for an Accesspoint ARN, not redirecting.Z
redirected6S3 request was previously redirected, not redirecting.r#   Errorrx   ResponseMetadataZ301Z400
HeadObject
HeadBucketx-amz-bucket-regionHTTPHeadersAuthorizationHeaderMalformedRegionr   i-  i.  i3  PermanentRedirectclient_regionS3 client configured for region %s but the bucket %s is not in that region and the proper region could not be automatically determined.S3 client configured for region %s but the bucket %s is in region %s; Please configure the proper region to avoid multiple unnecessary redirects and signing attempts.params)Zoperation_modelZ	call_argsrequest_contextrD   TZauthSchemes	auth_typesigning)r8   r   Zis_arnrY   rZ   namerW   anyget_bucket_region_cache_clientZ_ruleset_resolverZconstruct_endpointset_request_urlrD   Z
propertiesZauth_schemes_to_signing_ctx)r   request_dictr_   	operationr   Zredirect_ctxrJ   
error_coderesponse_metadatais_special_head_objectis_special_head_bucketis_wrong_signing_regionis_redirect_statusis_permanent_redirectr   r   
new_regionZep_resolverZep_infoZauth_schemesZ	auth_infor   signing_contextr!   r!   r"   redirect_from_errorY  s    


	

 

z+AioS3RegionRedirectorv2.redirect_from_errorc              
      s   |d }|d d }d|kr$|d S | di  dd}|dk	rD|S z$| jj|dI dH }|d d }W n0 tk
r } z|jd d }W 5 d}~X Y nX | dd}|S )	a-  
        There are multiple potential sources for the new region to redirect to,
        but they aren't all universally available for use. This will try to
        find region from response elements, but will fall back to calling
        HEAD on the bucket if all else fails.
        :param bucket: The bucket to find the region for. This is necessary if
            the region is not available in the error response.
        :param response: A response representing a service request that failed
            due to incorrect region configuration.
        r#   r   r   r   r   r   NZBucketr8   r   Zhead_bucketr	   r_   r   r   r_   Zservice_responseresponse_headersr   rE   r`   r!   r!   r"   r     s     z)AioS3RegionRedirectorv2.get_bucket_regionNr*   r+   r,   r   r   r!   r!   r!   r"   r   X  s   rr   c                   @   s   e Zd Zdd Zdd ZdS )AioS3RegionRedirectorc                    s  |d krd S |  |di r,td d S |di drLtd d S |d di }|d}|d di }|d	ko|jd
k}|d	ko|jdkod|di k}	|dkod|k}
|d d k	o|d jdk}|dk}t||
||	|gsd S |d d d }|d d}| ||I d H }|d krBtd||f  d S td|||f  | j	d|}|d }|||d}||d d< || j
|< | ||d  d|d d< dS )Nr   z=S3 request was previously to an accesspoint, not redirecting.Zs3_redirectedr   r#   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Zs3Zendpoint_url)r   r   rM   T)Z_is_s3_accesspointr8   rY   rZ   r   rW   r   r   Z_endpoint_resolverresolver   r   )r   r   r_   r   r   rJ   r   r   r   r   r   r   r   r   r   r   rM   r   r!   r!   r"   r     s    

	

z)AioS3RegionRedirector.redirect_from_errorc              
      s   |d }|d d }d|kr$|d S | di  dd }|d k	rD|S z$| jj|dI d H }|d d }W n0 tk
r } z|jd d }W 5 d }~X Y nX | dd }|S )Nr#   r   r   r   r   r   r   r   r   r!   r!   r"   r   I  s     z'AioS3RegionRedirector.get_bucket_regionNr   r!   r!   r!   r"   r     s   [r   c                   @   s@   e Zd ZdejfddZdddZdd Zddd	Zd
d Z	dS )AioContainerMetadataFetcherNc                 C   s$   |d krt | jd}|| _|| _d S )N)r1   )r   TIMEOUT_SECONDSr:   _sleep)r   r@   sleepr!   r!   r"   r   b  s    z$AioContainerMetadataFetcher.__init__c                    s   |  | | ||I d H S rk   )Z_validate_allowed_url_retrieve_credentials)r   full_urlrE   r!   r!   r"   retrieve_full_urij  s    
z-AioContainerMetadataFetcher.retrieve_full_uric                    s   |  |}| |I dH S )zRetrieve JSON metadata from ECS metadata.

        :type relative_uri: str
        :param relative_uri: A relative URI, e.g "/foo/bar?id=123"

        :return: The parsed JSON response.

        N)r   r   )r   Zrelative_urir   r!   r!   r"   retrieve_urin  s    	
z(AioContainerMetadataFetcher.retrieve_uric              
      s   ddi}|d k	r| | d}z| ||| jI d H W S  tk
r } z:tjd|dd | | jI d H  |d7 }|| jkr~ W 5 d }~X Y qX qd S )NAcceptzapplication/jsonr   zAReceived error when attempting to retrieve container metadata: %sTrH   r#   )	update_get_responser   r   rY   rZ   r   Z
SLEEP_TIMEZRETRY_ATTEMPTS)r   r   extra_headersrE   attemptsr`   r!   r!   r"   r   z  s(    
  
z1AioContainerMetadataFetcher._retrieve_credentialsc                    s  z| j  4 I d H }tjj}|d||d}|| I d H }|jI d H d}|j	dkrpt
d|j	|f dz t|W W  5 Q I d H R  W S  tk
r   d}	td|	| t
|	dY nX W 5 Q I d H R X W n6 tk
r
 }
 zd	|
 }	t
|	dW 5 d }
~
X Y nX d S )
Nrb   rB   zutf-8rF   z4Received non 200 response (%s) from ECS metadata: %s)	error_msgz8Unable to parse JSON returned from ECS metadata servicesz%s:%sz;Received error when attempting to retrieve ECS metadata: %s)r:   r)   rQ   rR   rS   rU   rV   rs   decoderW   r   r   r   r   rY   rZ   r   )r   r   rE   r1   r@   rS   r]   r_   Zresponse_textr   r`   r!   r!   r"   r     s8      
 $z)AioContainerMetadataFetcher._get_response)N)N)
r*   r+   r,   r$   r   r   r   r   r   r   r!   r!   r!   r"   r   a  s    


r   )-r$   rd   r   loggingZbotocore.awsrequestrQ   Zbotocore.exceptionsr   r   Zbotocore.utilsr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   Zaiobotocore.httpsessionZaiobotocoreZaiobotocore._helpersr   	getLoggerr*   rY   ZhttpsessionZAIOHTTPSessionr   r.   ru   r   r   r   r   r   r!   r!   r!   r"   <module>   s,   P
  H$
  t