o
    x[h—˜  ã                   @   sJ  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Z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mZmZmZmZmZmZmZmZ d d	l m!Z!m"Z"m#Z#m$Z$ d dl%Z%d d
l%m&Z& d dl'm(Z(m)Z)m*Z* e +e,¡Z-dZ.eedge/f  Z0dd„ Z1dd„ Z2de3fdd„Z4d[de5de6de7ddfdd„Z8de5ddfdd„Z9ded  fd!d"„Z:G d#d$„ d$ƒZ;G d%d„ de;ƒZ<G d&d„ de;ƒZ=G d'd(„ d(ƒZ>G d)d„ de?ƒZ@d*d+„ ZAd,e5de6fd-d.„ZBdd/œd0e@d1e0dee6 fd2d3„ZCddd d4ddddd5d5ddd6d5d7d6d8œd1e0d9e/de>fd:d;„ZD	d\d<ed=ef d>e5de3d?ejEd@ee6 defdAdB„ZF	C	Dd]d<ed=ef dEee5 dFe6de3deee5 ee> f f
dGdH„ZGG dIdJ„ dJeƒZHe6dKƒde-jIdddddd7d5dCdLœdMe6dee6 dNedOee dPee6 d1e0dQeeee6ge6f  dRe5dSe/dTe6fdUdV„ZJG dWdX„ dXƒZK	d\dYdZ„ZLdS )^é    N)ÚThreadPoolExecutorÚTimeoutErrorÚas_completed)Ú	parsedate)Úpartial)Ú	NOT_FOUND)Úcount)Úcreate_default_context)	ÚAnyÚCallableÚIteratorÚListÚMappingÚ
NamedTupleÚOptionalÚTupleÚUnion)ÚquoteÚurlparseÚurlsplitÚ
urlunparse)Ú
exceptions)ÚperformanceÚutilÚversionÚREDACTEDÚUrlErrorc                 C   s<   t t| dd�ƒ}|d s|d r|d |d< d|d< t|ƒS )NÚhttp)Úschemeé   é   Ú )Úlistr   r   )ÚurlÚ
parsed_url© r%   ú6/usr/lib/python3/dist-packages/cloudinit/url_helper.pyÚ	_cleanurl1   s
   r'   c                 G   s$   dd„ }| }|D ]}|||ƒ}q|S )Nc                 S   sN   t t| ƒƒ}|d }|r| d¡s|d7 }|tt|ƒdd�7 }||d< t|ƒS )Nr    ú/z/:)Úsafe)r"   r   Úendswithr   Ústrr   )r#   Úadd_onÚ
url_parsedÚpathr%   r%   r&   Úcombine_single<   s   z#combine_url.<locals>.combine_singler%   )ÚbaseÚadd_onsr/   r#   r,   r%   r%   r&   Úcombine_url;   s
   	r2   Úreturnc              
   C   sX   t jdt jdt jdt jdtdi}| t| ƒ¡}|s*t| t	ƒr#| j
}|S t d¡ d}|S )z4helper for read_ftps to map return codes to a numberé,  é�  éô  iX  i¼  z9Unexpected exception type while connecting to ftp server.i�ÿÿÿ)ÚftplibÚerror_replyÚ
error_tempÚ
error_permÚerror_protoÚEOFErrorÚgetÚtypeÚ
isinstanceÚOSErrorÚerrnoÚLOGÚwarning)ÚexcÚftp_error_codesÚcoder%   r%   r&   Ú"ftp_get_return_code_from_exceptionK   s    û
üÿrG   ç      @r#   ÚtimeoutÚkwargsÚFtpResponsec                 K   sü  t | ƒ}|jstdtd| d�‚t ¡ ��_}|jpd}|jpd}d|jkrñzt	j
tƒ d�}t d| |¡ |j|j||p;d	d
� W n! t	jy` } zt|ƒ}	td| › d|	› d�|	d| d�|‚d}~ww t d|¡ z|j||jpodd� t d¡ | ¡  W n t	jy— } zt d¡ tddd| d�|‚d}~ww zNz,t d|j¡ |jd|j› �|jd� t| ¡ | ƒW W t d¡ | ¡  W  d  ƒ S  t	jyæ } zt|ƒ}	td| › d|	› d�|	d| d�|‚d}~ww t d¡ | ¡  w zwzTt	 ¡ }
t d| |¡ |
j|j||�pd	d
� t d|¡ |
j||j�pdd� t d|j¡ |
jd|j› �|jd� t| ¡ | ƒW W t d¡ |
 ¡  W  d  ƒ S  t	j�yh } zt|ƒ}	td| › d|	› d�|	d| d�|‚d}~ww t d¡ |
 ¡  w 1 �sww   Y  dS )az  connect to URL using ftp over TLS and read a file

    when using strict mode (ftps://), raise exception in event of failure
    when not using strict mode (ftp://), fall back to using unencrypted ftp

    url: string containing the desination to read a file from. The url is
        parsed with urllib.urlsplit to identify username, password, host,
        path, and port in the following format:
            ftps://[username:password@]host[:port]/[path]
        host is the only required component
    timeout: maximum time for the connection to take
    kwargs: unused, for compatibility with read_url
    returns: UrlResponse
    zInvalid url providedN©ÚcauserF   Úheadersr#   é   Ú	anonymousÚftps)Úcontextz3Attempting to connect to %s via port [%s] over tls.rH   )ÚhostÚportrI   z1Reading file from server over tls failed for url z [ú]z"Attempting to login with user [%s]r!   )ÚuserÚpasswdzCreating a secure connectionzšAttempted to connect to an insecure ftp server but used a scheme of ftps://, which is not allowed. Use ftp:// to allow connecting to insecure ftp servers.r6   zReading file: %szRETR )ÚcallbackzClosing connectionz,Reading file from ftp server failed for url z(Attempting to connect to %s via port %s.)r   Úhostnamer   r   ÚioÚBytesIOrT   Úusernamer   r7   ÚFTP_TLSr	   rB   ÚdebugÚconnectÚ
all_errorsrG   ÚloginÚpasswordÚprot_pr:   rC   r.   Ú
retrbinaryÚwriterK   ÚgetvalueÚcloseÚFTP)r#   rI   rJ   Ú	url_partsÚbufferrT   rV   Úftp_tlsÚerF   Úftpr%   r%   r&   Ú	read_ftpsb   s   ÿ


ÿý
ýÿÿùø€þþ
ÿø	÷€úÿ
·<ÿÿùø€þ

ÿý
þ
–]ÿÿùø€þ

–rn   r.   ÚFileResponsec              
   K   s‚   |  d¡rt d| ¡ zt | ¡}t|| ƒW S  ty+ } z	t|td| d�|‚d}~w t	y@ } z
t||j
d| d�|‚d}~ww )zmread a binary file and return a FileResponse

    matches function signature with read_ftps and read_url
    Údataz'Unable to post data to file resource %sNrL   )r=   rB   rC   r   Úload_binary_filero   ÚFileNotFoundErrorr   r   ÚIOErrorrA   )r.   rJ   Úcontentsrl   r%   r%   r&   Ú
_read_fileä   s   

€€ÿru   )ro   ÚUrlResponserK   c              
   K   s¸   |   ¡ } zt| ƒ}W n ty } zt|| d�|‚d}~ww |j}|dks-| r6d| d kr6t|jfi |¤ŽS |dv rBt| fi |¤ŽS |dv rNt| fi |¤ŽS t	 
d|¡ t| fi |¤ŽS )	a0  Wrapper function around readurl to allow passing a file path as url.

    When url is not a local file path, passthrough any kwargs to readurl.

    In the case of parameter passthrough to readurl, default values for some
    parameters. See: call-signature of readurl in this module for param docs.
    )rM   r#   NÚfiler(   r   )rm   rQ   )r   ÚhttpszAttempting unknown protocol %s)Úlstripr   Ú
ValueErrorr   r   ru   r.   rn   ÚreadurlrB   rC   )r#   rJ   Úparsedrl   r   r%   r%   r&   Úread_file_or_urlô   s    
€ÿr}   c                   @   s&   e Zd Zd	dd„Zdd„ Zdd„ ZdS )
ÚStringResponseéÈ   c                 C   s   || _ i | _|| _|| _d S ©N)rF   rN   rt   r#   ©Úselfrt   r#   rF   r%   r%   r&   Ú__init__  s   
zStringResponse.__init__c                 O   s
   | j dkS )Nr   ©rF   ©r‚   ÚargsrJ   r%   r%   r&   Úok  ó   
zStringResponse.okc                 C   s   | j  d¡S )Nzutf-8)rt   Údecode©r‚   r%   r%   r&   Ú__str__  s   zStringResponse.__str__N©r   )Ú__name__Ú
__module__Ú__qualname__rƒ   r‡   r‹   r%   r%   r%   r&   r~     s    
r~   c                       s(   e Zd Zddedef‡ fdd„Z‡  ZS )ro   r   rt   r#   c                    s   t ƒ j|||d� d S )Nr„   ©Úsuperrƒ   r�   ©Ú	__class__r%   r&   rƒ   !  s   zFileResponse.__init__rŒ   ©r�   rŽ   r�   Úbytesr+   rƒ   Ú__classcell__r%   r%   r’   r&   ro      s     c                       s&   e Zd Zdedef‡ fdd„Z‡  ZS )rK   rt   r#   c                    s   t ƒ  ||¡ d S r€   r�   )r‚   rt   r#   r’   r%   r&   rƒ   &  s   zFtpResponse.__init__r”   r%   r%   r’   r&   rK   %  s    c                   @   s˜   e Zd Zdejfdd„Zedefdd„ƒZede	fdd„ƒZ
ddefd
d„Zedd„ ƒZedefdd„ƒZdd„ Z		ddee dedee fdd„ZdS )rv   Úresponsec                 C   s
   || _ d S r€   )Ú	_response)r‚   r—   r%   r%   r&   rƒ   +  rˆ   zUrlResponse.__init__r3   c                 C   s   | j jd u rdS | j jS )Nó    )r˜   ÚcontentrŠ   r%   r%   r&   rt   .  s   zUrlResponse.contentsc                 C   ó   | j jS r€   )r˜   r#   rŠ   r%   r%   r&   r#   4  ó   zUrlResponse.urlFc                 C   s.   d}|rd}d| j   kr|k rdS  dS dS )Nr4   r5   r   TFr„   )r‚   Úredirects_okÚupperr%   r%   r&   r‡   8  s   ÿzUrlResponse.okc                 C   r›   r€   )r˜   rN   rŠ   r%   r%   r&   rN   A  rœ   zUrlResponse.headersc                 C   r›   r€   )r˜   Ústatus_coderŠ   r%   r%   r&   rF   E  rœ   zUrlResponse.codec                 C   r›   r€   )r˜   ÚtextrŠ   r%   r%   r&   r‹   I  s   zUrlResponse.__str__r   Ú
chunk_sizeÚdecode_unicodec                 c   s   � | j  ||¡E dH  dS )at  Iterates over the response data.

        When stream=True is set on the request, this avoids reading the content
        at once into memory for large responses.

        :param chunk_size: Number of bytes it should read into memory.
        :param decode_unicode: If True, content will be decoded using the best
        available encoding based on the response.
        N)r˜   Úiter_content)r‚   r¡   r¢   r%   r%   r&   r£   L  s   €zUrlResponse.iter_contentN)F)r   F)r�   rŽ   r�   ÚrequestsÚResponserƒ   Úpropertyr•   rt   r+   r#   Úboolr‡   rN   ÚintrF   r‹   r   r   r£   r%   r%   r%   r&   rv   *  s(    	
ÿÿÿþrv   c                
   @   s:   e Zd Z			ddedee dee dee fdd„ZdS )	r   NrM   rF   rN   r#   c                 C   s8   t  | t|ƒ¡ || _|| _|d u ri n|| _|| _d S r€   )rs   rƒ   r+   rM   rF   rN   r#   )r‚   rM   rF   rN   r#   r%   r%   r&   rƒ   \  s
   
zUrlError.__init__)NNN)	r�   rŽ   r�   r
   r   r¨   r   r+   rƒ   r%   r%   r%   r&   r   [  s    ûþýüûc                 C   s„   i }t | ƒj}|dkr@|r@d|v r|d r|d |d< nd|d< d|v r4d|v r4|d |d g|d< |S d|v r@t|d ƒ|d< |S )Nrx   Úca_certsÚverifyTÚ	cert_fileÚkey_fileÚcert)r   r   r+   )r#   Ússl_detailsÚssl_argsr   r%   r%   r&   Ú_get_ssl_argsj  s   
þþr°   Úretry_afterc                 C   s’   zt | ƒ}W |S  tyH   zt| ƒ}|stdƒ‚t t |¡t ¡  ƒ}W n ty6   t d| ¡ d}Y nw |dk rEt d¡ d}Y |S Y |S w )a<  Parse a Retry-After header value into an integer.

    : param retry_after: The value of the Retry-After header.
        https://www.rfc-editor.org/rfc/rfc9110.html#section-10.2.3
        https://www.rfc-editor.org/rfc/rfc2616#section-3.3
    : return: The number of seconds to wait before retrying the request.
    z(Failed to parse Retry-After header valuezGFailed to parse Retry-After header value: %s. Waiting 1 second instead.r   r   zBRetry-After header value is in the past. Waiting 1 second instead.)Úfloatrz   r   ÚtimeÚmktimerB   Úinfo)r±   Úto_waitÚ
time_tupler%   r%   r&   Ú_get_retry_after|  s2   
ëýúÿúër¸   ©Úexception_cbÚerrorrº   c                C   s\   |r|| ƒrdS | j r(| j dkr(t d¡ | jr!t| j dd¡ƒS t d¡ dS |s,dS | ‚)aÖ  Handle exceptions raised during request processing.

    If we have no exception callback or the callback handled the error or we
    got a 503, return with an optional timeout so the request can be retried.
    Otherwise, raise the error.

    :param error: The exception raised during the request.
    :param response: The response object.
    :param exception_cb: Callable to handle the exception.

    :return: Optional time to wait before retrying the request.
    Ni÷  zEEndpoint returned a 503 error. HTTP endpoint is overloaded. Retrying.zRetry-AfterÚ1z7Unable to introspect response header. Waiting 1 second.r   )rF   rB   rC   rN   r¸   r=   rµ   )r»   rº   r%   r%   r&   Ú_handle_errorž  s   ÿ
r½   r   TFr!   )rp   rI   ÚretriesÚsec_betweenrN   Ú
headers_cbÚheaders_redactr®   Úcheck_statusÚallow_redirectsrº   ÚsessionÚinfiniteÚlog_req_respÚrequest_methodÚstreamrÈ   c                    sø  t | ƒ} | |dœ}| t| |ƒ¡ |
|d< |s|rdnd}||d< |dur8t|tƒr/||d< n	tt|ƒdƒ|d< |du r>g }d	}|rKtt|ƒd	 d	ƒ}d
t 	¡  }|durZ| 
¡ }ni }|rb||d< |du rhd}|du rpt ¡ }tƒ D �]}|r||| ƒ}d|vr„||d< ||d< i }| ¡ D ]1\}‰ |dkr—qŽ|dkr»|r»‡ fdd„|D ƒ}|rºt
 ˆ ¡||< |D ]}t|| |< q±qŽˆ ||< qŽz3|rÐt d||rËdn|| |¡ |jdi |¤Ž}|	rÞ| ¡  t d| |jt|jƒ|d	 ¡ t|ƒW   S  tj�y } zt|| d�|‚d}~w tj�y) } zt||jj|jj| d�}|}W Y d}~n"d}~w tj�yF } zt|| d�}|}d}W Y d}~nd}~ww t ||d�}|�s_|�pX|d	 |k }|�s_||‚|�pc|}|dk�rw|�rrt d|¡ t! "|¡ qst#dƒ‚)a`  Wrapper around requests.Session to read the url and retry if necessary

    :param url: Mandatory url to request.
    :param data: Optional form data to post the URL. Will set request_method
        to 'POST' if present.
    :param timeout: Timeout in seconds to wait for a response. May be a tuple
        if specifying (connection timeout, read timeout).
    :param retries: Number of times to retry on exception if exception_cb is
        None or exception_cb returns True for the exception caught. Default is
        to fail with 0 retries on exception.
    :param sec_between: Default 1: amount of seconds passed to time.sleep
        between retries. None or -1 means don't sleep.
    :param headers: Optional dict of headers to send during request
    :param headers_cb: Optional callable returning a dict of values to send as
        headers during request
    :param headers_redact: Optional list of header names to redact from the log
    :param ssl_details: Optional dict providing key_file, ca_certs, and
        cert_file keys for use on in ssl connections.
    :param check_status: Optional boolean set True to raise when HTTPError
        occurs. Default: True.
    :param allow_redirects: Optional boolean passed straight to Session.request
        as 'allow_redirects'. Default: True.
    :param exception_cb: Optional callable to handle exception and returns
        True if retries are permitted.
    :param session: Optional exiting requests.Session instance to reuse.
    :param infinite: Bool, set True to retry indefinitely. Default: False.
    :param log_req_resp: Set False to turn off verbose debug messages.
    :param request_method: String passed as 'method' to Session.request.
        Typically GET, or POST. Default: POST if data is provided, GET
        otherwise.
    :param stream: if False, the response content will be immediately
    downloaded.
    )r#   rÈ   rÃ   ÚPOSTÚGETÚmethodNrI   r   r   zCloud-Init/%srp   éÿÿÿÿz
User-AgentrN   c                    s   g | ]	}ˆ   |¡r|‘qS r%   )r=   )Ú.0Úk©Úvr%   r&   Ú
<listcomp>'  s    zreadurl.<locals>.<listcomp>z'[%s/%s] open '%s' with %s configurationrÅ   z(Read from %s (%s, %sb) after %s attempts©r#   ©rF   rN   r#   r¹   ú1Please wait %s seconds while we wait to try againz"This path should be unreachable...r%   )$r'   Úupdater°   r?   ÚtupleÚmaxr²   r¨   r   Úversion_stringÚcopyr¤   ÚSessionr   ÚitemsÚdeepcopyr   rB   r^   ÚrequestÚraise_for_statusrŸ   Úlenrš   rv   r   ÚSSLErrorr   Ú	HTTPErrorr—   rN   ÚRequestExceptionr½   r³   ÚsleepÚRuntimeError) r#   rp   rI   r¾   r¿   rN   rÀ   rÁ   r®   rÂ   rÃ   rº   rÄ   rÅ   rÆ   rÇ   rÈ   Úreq_argsÚmanual_triesÚ
user_agentÚiÚfiltered_req_argsrÎ   Úmatched_headersÚkeyr—   rl   Ú	url_errorÚraised_exceptionÚresponse_sleep_timeÚ
will_retryÚ
sleep_timer%   rÏ   r&   r{   À  sÌ   5þ


€

ûû
€ü€€ýþ

þ
€r{   Úfunc.ÚaddrÚeventÚdelayc                 C   s   |r
|j |d�r
dS | ||ƒS )z Execute func with optional delay©rI   N©Úwait©rñ   rò   rI   ró   rô   r%   r%   r&   Ú_run_func_with_delayp  s   
rù   ç333333Ã?é
   Ú	addressesÚstagger_delayc                    s.  d}d}d}g }t  ¡ ‰tt|ƒd�‰ z|zW‡ ‡‡‡‡fdd„t|ƒD ƒ}t|ˆd�D ],}	||	 }|	 ¡ }
|
r>|
}| |¡ q*|	 ¡ }|rVˆ 	¡  ||f  W W ˆ j
dd� S q*|rbt d||¡ |‚t d	|¡ td
ƒ‚ ty„   t dd |¡d tt|ƒ¡¡ Y nw W ˆ j
dd� ||fS ˆ j
dd� w )a  execute multiple callbacks in parallel

    Run blocking func against two different addresses staggered with a
    delay. The first call to return successfully is returned from this
    function and remaining unfinished calls are cancelled if they have not
    yet started
    N)Úmax_workersc              
      s,   i | ]\}}ˆ j tˆ|ˆˆ|ˆ d �|“qS )rø   )Úsubmitrù   )rÍ   rè   rò   ©Úexecutorrñ   Úis_donerý   rI   r%   r&   Ú
<dictcomp>œ  s    	øúøzdual_stack.<locals>.<dictcomp>rõ   Frö   z<Exception(s) %s during request to %s, raising last exceptionzEmpty result for address %szNo result returnedzJTimed out waiting for addresses: %s, exception(s) raised while waiting: %sú )Ú	threadingÚEventr   rß   Ú	enumerater   Ú	exceptionÚappendÚresultÚsetÚshutdownrB   r^   r»   rz   r   ÚjoinÚmapr+   )rñ   rü   rý   rI   Úreturn_resultÚreturned_addressÚlast_exceptionr   ÚfuturesÚfutureÚreturn_exceptionr%   r   r&   Ú
dual_stack‚  sT   	÷â	üüÿþr  c                   @   s2   e Zd ZU ee ed< ee ed< ee ed< dS )ÚHandledResponser#   r—   Ú	wait_timeN)r�   rŽ   r�   r   r+   Ú__annotations__rv   r²   r%   r%   r%   r&   r  Õ  s   
 r  Úinf)Úmax_waitrI   Ú	status_cbrÀ   rÁ   rð   rº   Úsleep_time_cbrÇ   Úconnect_synchronouslyÚasync_delayr  r  rÀ   rð   r  rÇ   r  r  c                   sè  dt dtf‡
fdd„}d#dtdtdtfd	d
„‰dtt dtt dttt tf fdd„‰dttgttt tt f f dt	tt
t f dt dtdtdtf‡‡fdd„‰dtdt dtf‡‡‡	fdd„‰dtf‡‡‡‡‡‡‡fdd„}dtf‡ ‡‡‡fdd„}t ¡ }ˆ
r‰|r‰tdƒ‚|
r�|n|}|p’|}d‰d}	 |||||ƒ}d‰|jr«|j|jjfS |jr»t |j¡ ˆd  ‰d‰q—||ˆƒ}ˆˆ||ƒrÉ	 d"S ˆd  ‰t d!|¡ t |¡ t ¡ }|ró|| |ˆ króˆ||  }|dkró	 d"S q˜)$a  Wait for a response from one of the urls provided.

    :param urls: List of urls to try
    :param max_wait: Roughly the maximum time to wait before giving up
        The max time is *actually* len(urls)*timeout as each url will
        be tried once and given the timeout provided.
        a number <= 0 will always result in only one try
    :param timeout: Timeout provided to urlopen
    :param status_cb: Callable with string message when a url is not available
    :param headers_cb: Callable with single argument of url to get headers
        for request.
    :param headers_redact: List of header names to redact from the log
    :param sleep_time: Amount of time to sleep between retries. If this and
        sleep_time_cb are None, the default sleep time defaults to 1 second
        and increases by 1 seconds every 5 tries. Cannot be specified along
        with `sleep_time_cb`.
    :param exception_cb: Callable to handle exception and returns True if
        retries are permitted.
    :param sleep_time_cb: Callable with 2 arguments (response, loop_n) that
        generates the next sleep time. Cannot be specified
        along with 'sleep_time`.
    :param request_method: Indicates the type of HTTP request:
        GET, PUT, or POST
    :param connect_synchronously: If false, enables executing requests
        in parallel
    :param async_delay: Delay before parallel metadata requests, see RFC 6555

    :return: tuple of (url, response contents), on failure, (False, None)

    :raises: UrlError on unrecoverable error
    Úloop_numberr3   c                    s   ˆ d urˆ S |d d S )Né   r   r%   )Ú_r  )rð   r%   r&   Údefault_sleep_time  s   z(wait_for_url.<locals>.default_sleep_timer   r  Ú
start_timerð   c                 S   s0   | t dƒdfv r
dS | dkpt ¡ | | | kS )z4Check if time is up based on start time and max waitr  NFr   )r²   r³   Ú	monotonic)r  r#  rð   r%   r%   r&   Útimeup  s
   ÿzwait_for_url.<locals>.timeupr—   r#   c              
   S   sæ   d}d}| r|sd}t t|ƒƒ}||fS z| j ¡  W n& tjjyA } zt ||jj|jj	|d�}|t
|ƒfW  Y d}~S d}~ww | jsZd| j }t t|ƒ| j| j	|d�}||fS |  ¡ sod| j }t t|ƒ| j| j	|d�}||fS )z?Map requests response code/contents to internal "UrlError" typer!   NzRequest timed outrÓ   zempty response [%s]zbad status code [%s])r   rz   r˜   rÞ   r¤   r   rá   r—   rŸ   rN   r+   rt   rF   r‡   )r—   r#   ÚreasonÚurl_excrl   r%   r%   r&   Úhandle_url_response  sH   ü€ù
ü÷
üz)wait_for_url.<locals>.handle_url_responseÚurl_reader_cbÚurlsÚexc_cbÚlog_cbc              
      s  d}d}z| |ƒ\}}ˆ ||ƒ\}}|st ||dd�W S W n/ ty5 }	 zd|	 }|	}W Y d}	~	nd}	~	w tyL }	 zd|	 }|	}W Y d}	~	nd}	~	ww tt ¡ | ƒ}
ˆr[dˆ nd}d|pet|d	d	ƒ|
||f }||ƒ t ddt|tƒrt||d
�d�S dd�S )z:Execute request, handle response, optionally log exceptionr!   N)r  zrequest error [%s]zunexpected error [%s]z%ssÚ	unlimitedzCalling '%s' failed [%s/%s]: %sr#   r¹   ©r#   r—   r  )	r  r   Ú	Exceptionr¨   r³   r$  Úgetattrr?   r½   )r)  r*  r#  r+  r,  r&  r#   r—   r'  rl   Ú
time_takenÚmax_wait_strÚ
status_msg)r(  r  r%   r&   Úread_url_handle_exceptionsA  sD   
ÿ€€þüÿüúz0wait_for_url.<locals>.read_url_handle_exceptionsrI   c                    s$   t | ˆ d u ri nˆ | ƒˆ|dˆd�S )NF)rN   rÁ   rI   rÂ   rÇ   )r{   )r#   rI   )rÀ   rÁ   rÇ   r%   r&   Úread_url_cbm  s   úz!wait_for_url.<locals>.read_url_cbc           
         sÌ   dt f‡‡ fdd„}g }ˆD ]H}t ¡ }ˆdkr>ˆs>ˆˆ| ƒr(tdddd�  S ˆdur>ˆ r>|ˆ  | ˆ kr>t| ˆ | ƒ‰ ˆ||| ||ƒ}|jrM|  S |jrV| |j¡ q|r]t|ƒnd}	tdd|	d�S )z|iterate over list of urls, request each one and handle responses
        and thrown exceptions individually per url
        r#   c                    s   | ˆ | ˆƒfS r€   r%   rÒ   )r5  rI   r%   r&   Úurl_reader_serial~  ó   z@wait_for_url.<locals>.read_url_serial.<locals>.url_reader_serialr   Nr.  )	r+   r³   r$  r  r¨   r—   r  r	  r×   )
r#  rI   r+  r,  r6  Ú
wait_timesr#   ÚnowÚoutr  )Úloop_nr  Úmust_try_againr5  r4  r%  r*  rõ   r&   Úread_url_serialw  s0   

ÿÿ
ÿ€z%wait_for_url.<locals>.read_url_serialc                    s    t tˆˆ |d�}ˆ|ˆ| ||ƒS )z‘pass list of urls to dual_stack which sends requests in parallel
        handle response and exceptions of the first endpoint to respond
        )rý   rI   )r   r  )r#  rI   r+  r,  Úurl_reader_parallel)r  r5  r4  r*  r%   r&   Úread_url_parallel›  s   ü
ÿz'wait_for_url.<locals>.read_url_parallelz3sleep_time and sleep_time_cb are mutually exclusiveNTFr   rÔ   )FN)r   )r¨   r²   r   rv   r+   r   r   r   r
   r   r   ÚExceptionCallbackr  r³   r$  rz   r—   r#   rt   r  rã   rB   r^   )r*  r  rI   r  rÀ   rÁ   rð   rº   r  rÇ   r  r  r"  r=  r?  r#  Údo_read_urlÚcalculate_sleep_timer—   ÚrespÚcurrent_sleep_timeÚcurrent_timer%   )r  r(  rÀ   rÁ   r;  r  r<  r5  r4  rÇ   rð   r%  r*  r&   Úwait_for_urlÞ  s„   /ÿÿ
þ)ÿÿüûúùø,
þ$þ
ÿ
ñþ
ârF  c                   @   sh   e Zd Z					ddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )ÚOauthUrlHelperNú/run/oauth_skew.jsonc                 C   st   || _ |pd| _|| _|| _|| _d| _d| _| j| j| j f}t|ƒs'd| _nt|ƒs/t	dƒ‚|  
¡ }|p6i | _d S )Nr!   Tr   FzBall or none of token_key, token_secret, or consumer_key can be set)Úconsumer_keyÚconsumer_secretÚ	token_keyÚtoken_secretÚskew_data_fileÚ	_do_oauthÚskew_change_limitÚanyÚallrz   Úread_skew_fileÚ	skew_data)r‚   rI  rK  rL  rJ  rM  ÚrequiredÚoldr%   r%   r&   rƒ   Þ  s    
ÿzOauthUrlHelper.__init__c              	   C   s’   | j rGtj | j ¡rGt d| j › �¡�, t| j dd��}t |¡W  d   ƒ W  d   ƒ S 1 s2w   Y  W d   ƒ d S 1 sBw   Y  d S )NzReading Úr©Úmode)	rM  Úosr.   Úisfiler   ÚTimedÚopenÚjsonÚload)r‚   Úfpr%   r%   r&   rR  ù  s   ÿ:ýüzOauthUrlHelper.read_skew_filec              	   C   s¬   | j sd S |  ¡ }|d u ri }|||< t d| j › �¡�0 t| j dd��}| t |¡¡ W d   ƒ n1 s7w   Y  W d   ƒ d S W d   ƒ d S 1 sOw   Y  d S )NzWriting ÚwrW  )rM  rR  r   r[  r\  re   r]  Údumps)r‚   rS   ÚvalueÚcurr_  r%   r%   r&   Úupdate_skew_file  s   ÿPýzOauthUrlHelper.update_skew_filec              
   C   sô   t |tƒr|jdks|jdksd S d|jvrt d|j¡ d S |jd }z	t t|ƒ¡}W n t	yG } zt d||¡ W Y d }~d S d }~ww t
|t ¡  ƒ}t|jƒj}| j |d¡}t|| ƒ| jkrs|  ||¡ t d||¡ || j|< d S )Ni“  i‘  Údatez$Missing header 'date' in %s responsez#Failed to convert datetime '%s': %sr   z$Setting oauth clockskew for %s to %d)r?   r   rF   rN   rB   rC   r³   r´   r   r/  r¨   r   r#   ÚnetlocrS  r=   ÚabsrO  rd  )r‚   r  re  Úremote_timerl   ÚskewrS   Úold_skewr%   r%   r&   rº     s.   ÿ

€þ
zOauthUrlHelper.exception_cbc                 C   sZ   | j si S d }t|ƒj}| jr|| jv rtt ¡ ƒ| j|  }t|| j| j| j	| j
|d�S )N)r#   rI  rK  rL  rJ  Ú	timestamp)rN  r   rf  rS  r¨   r³   Úoauth_headersrI  rK  rL  rJ  )r‚   r#   rk  rS   r%   r%   r&   rÀ   *  s   
úzOauthUrlHelper.headers_cbc                 C   s:   t | j| d¡ƒ|d< t | j| d¡ƒ|d< ||i |¤ŽS )NrÀ   rº   )r   Ú_headers_cbr=   Ú_exception_cb)r‚   Úwrapped_funcr†   rJ   r%   r%   r&   Ú_wrapped<  s   ÿÿzOauthUrlHelper._wrappedc                 O   ó   |   t||¡S r€   )rp  rF  r…   r%   r%   r&   rF  E  r7  zOauthUrlHelper.wait_for_urlc                 O   rq  r€   )rp  r{   r…   r%   r%   r&   r{   H  r7  zOauthUrlHelper.readurlc              	   C   s>   d}z|r||ƒ}W |   |¡ |S W |   |¡ |S |   |¡ w )NTr¹   )r‚   Úextra_exception_cbr  Úretr%   r%   r&   rn  K  s   

ü
ÿzOauthUrlHelper._exception_cbc                 C   s$   i }|r||ƒ}|  |  |¡¡ |S r€   )rÕ   rÀ   )r‚   Úextra_headers_cbr#   rN   r%   r%   r&   rm  T  s
   zOauthUrlHelper._headers_cb)NNNNrH  )r�   rŽ   r�   rƒ   rR  rd  rº   rÀ   rp  rF  r{   rn  rm  r%   r%   r%   r&   rG  Ý  s     
ú		rG  c              
   C   sr   zdd l m} W n ty } ztdƒ|‚d }~ww |r!t|ƒ}nd }|j|||||j|d�}| | ¡\}	}
}|
S )Nr   zoauth support is not available)Úclient_secretÚresource_owner_keyÚresource_owner_secretÚsignature_methodrk  )Úoauthlib.oauth1Úoauth1ÚImportErrorÚNotImplementedErrorr+   ÚClientÚSIGNATURE_PLAINTEXTÚsign)r#   rI  rK  rL  rJ  rk  rz  rl   ÚclientÚ_uriÚsigned_headersÚ_bodyr%   r%   r&   rl  \  s&   
€ÿ
úrl  )rH   r€   )rú   rû   )MrÙ   r7   rZ   r]  ÚloggingrY  r  r³   Úconcurrent.futuresr   r   r   Úemail.utilsr   Ú	functoolsr   Úhttp.clientr   Ú	itertoolsr   Ússlr	   Útypingr
   r   r   r   r   r   r   r   r   Úurllib.parser   r   r   r   r¤   r   Ú	cloudinitr   r   r   Ú	getLoggerr�   rB   r   r§   r@  r'   r2   r¨   rG   r+   r²   Údictrn   ru   r}   r~   ro   rK   rv   rs   r   r°   r¸   r½   r{   r  rù   r  r  r^   rF  rG  rl  r%   r%   r%   r&   Ú<module>   s  
,

 
þ1%ýÿý
ü%îóî
í 6û
ÿþýüû
úü
ÿþýü
ûSóýüûúø	÷
öõô
ó   ÿ