U
    g                     @   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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 Z2e3dddZ4dMe5e6e7ddddZ8e5ddddZ9ed d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) ZAe5e6d*d+d,ZBdd-e@e0ee6 d.d/d0ZCddd d1ddddd2d2ddd3d2d4d3d5e0e/e>d6d7d8ZDdNed9ef e5e3ejEee6 ed:d;d<ZFdOed9ef ee5 e6e3eee5 ee> f d?d@dAZGG dBdC dCeZHe6dDde-jIdddddd4d2d=dEe6ee6 eee ee6 e0eeee6ge6f  e5e/e6dF
dGdHZJG dIdJ dJZKdPdKdLZLdS )Q    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 s4|d r4|d |d< d|d< t|S )Nhttp)scheme       )listr   r   )urlZ
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/:)Zsafe)r"   r   endswithr   strr   )r#   add_onZ
url_parsedpathr$   r$   r%   combine_single<   s    z#combine_url.<locals>.combine_singler$   )baseZadd_onsr,   r#   r*   r$   r$   r%   combine_url;   s
    	r.   returnc              
   C   sV   t jdt jdt jdt jdtdi}|t| }|sRt| t	rD| j
}n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)ftplibZerror_replyZ
error_temp
error_permZerror_protoEOFErrorgettype
isinstanceOSErrorerrnoLOGwarning)excZftp_error_codescoder$   r$   r%   "ftp_get_return_code_from_exceptionK   s(         
r@         @FtpResponse)r#   timeoutkwargsr0   c                 K   s
  t | }|jstdtd| dt }|jp2d}|jp<d}d|jkrz6t	j
t d}td| | |j|j||pxd	d
 W nL t	jk
r } z,t|}	td|  d|	 d|	d| d|W 5 d}~X Y nX td| z*|j||jpdd td |  W nB t	jk
rF } z td tddd| d|W 5 d}~X Y nX zzFtd|j |jd|j |jd t| | W W `W  5 Q R  S  t	jk
r } z,t|}	td|  d|	 d|	d| d|W 5 d}~X Y nX W 5 td |  X n zzt	 }
td| | |
j|j||p(d	d
 td| |
j||jpJdd td|j |
jd|j |jd t| | W W `W  5 Q R  S  t	jk
r } z,t|}	td|  d|	 d|	d| d|W 5 d}~X Y nX W 5 td |
  X W 5 Q R X 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causer?   headersr#      Z	anonymousftps)contextz3Attempting to connect to %s via port [%s] over tls.rA   )hostportrC   z1Reading file from server over tls failed for url z []z"Attempting to login with user [%s]r!   )userZpasswdzCreating a secure connectionzAttempted 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.r3   zClosing connectionzReading file: %szRETR )callbackz,Reading file from ftp server failed for url z(Attempting to connect to %s via port %s.)r   Zhostnamer   r   ioBytesIOrL   Zusernamer   r4   ZFTP_TLSr	   r<   debugZconnectZ
all_errorsr@   ZloginZpasswordZprot_pr5   r=   closer+   Z
retrbinarywriterB   getvalueZFTP)r#   rC   rD   Z	url_partsbufferrL   rN   Zftp_tlser?   ftpr$   r$   r%   	read_ftpsb   s       


	
	

  

  
 

rY   FileResponse)r+   r0   c              
   K   s   | drtd|  zt| }t|| W S  tk
r` } zt|td| d|W 5 d}~X Y n6 t	k
r } zt||j
d| d|W 5 d}~X Y nX dS )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 %sNrE   )r7   r<   r=   r   Zload_binary_filerZ   FileNotFoundErrorr   r   IOErrorr;   )r+   rD   contentsrW   r$   r$   r%   
_read_file   s    

"r_   )rZ   UrlResponserB   c              
   K   s   |   } zt| }W n0 tk
rD } zt|| d|W 5 d}~X Y nX |j}|dksd| rrd| d krrt|jf|S |dkrt| f|S |dkrt| f|S t	
d| t| f|S d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.
    )rF   r#   Nfiler'   r   )rX   rI   )r   httpszAttempting unknown protocol %s)lstripr   
ValueErrorr   r   r_   r+   rY   readurlr<   r=   )r#   rD   ZparsedrW   r   r$   r$   r%   read_file_or_url   s    
 rf   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)r?   rG   r^   r#   selfr^   r#   r?   r$   r$   r%   __init__  s    zStringResponse.__init__c                 O   s
   | j dkS )Nrh   r?   rk   argsrD   r$   r$   r%   ok  s    zStringResponse.okc                 C   s   | j dS )Nzutf-8)r^   decoderk   r$   r$   r%   __str__  s    zStringResponse.__str__N)rh   )__name__
__module____qualname__rl   rp   rs   r$   r$   r$   r%   rg     s   
rg   c                       s&   e Zd Zdeed fddZ  ZS )rZ   rh   r^   r#   c                    s   t  j|||d d S )Nrm   superrl   rj   	__class__r$   r%   rl   !  s    zFileResponse.__init__)rh   rt   ru   rv   bytesr)   rl   __classcell__r$   r$   rz   r%   rZ      s   c                       s$   e Zd Zeed fddZ  ZS )rB   rw   c                    s   t  || d S ri   rx   )rk   r^   r#   rz   r$   r%   rl   &  s    zFtpResponse.__init__r|   r$   r$   rz   r%   rB   %  s   c                   @   s   e Zd ZejdddZeedddZee	dddZ
dedd
dZedd ZeedddZdd Zdee eee dddZdS )r`   )responsec                 C   s
   || _ d S ri   )	_response)rk   r   r$   r$   r%   rl   +  s    zUrlResponse.__init__r/   c                 C   s   | j jd krdS | j jS )N    )r   contentrr   r$   r$   r%   r^   .  s    zUrlResponse.contentsc                 C   s   | j jS ri   )r   r#   rr   r$   r$   r%   r#   4  s    zUrlResponse.urlFc                 C   s2   d}|rd}d| j   kr"|k r*n ndS dS d S )Nr1   r2   rh   TFrm   )rk   Zredirects_okupperr$   r$   r%   rp   8  s    zUrlResponse.okc                 C   s   | j jS ri   )r   rG   rr   r$   r$   r%   rG   A  s    zUrlResponse.headersc                 C   s   | j jS ri   )r   status_coderr   r$   r$   r%   r?   E  s    zUrlResponse.codec                 C   s   | j jS ri   )r   textrr   r$   r$   r%   rs   I  s    zUrlResponse.__str__r   )
chunk_sizedecode_unicoder0   c                 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)rk   r   r   r$   r$   r%   r   L  s    zUrlResponse.iter_contentN)F)r   F)rt   ru   rv   requestsZResponserl   propertyr}   r^   r)   r#   boolrp   rG   intr?   rs   r   r   r   r$   r$   r$   r%   r`   *  s$   	
    r`   c                   @   s.   e Zd Zdeee ee ee dddZdS )r   NrE   c                 C   s8   t | t| || _|| _|d kr(i n|| _|| _d S ri   )r]   rl   r)   rF   r?   rG   r#   )rk   rF   r?   rG   r#   r$   r$   r%   rl   \  s
    zUrlError.__init__)NNN)	rt   ru   rv   r
   r   r   r   r)   rl   r$   r$   r$   r%   r   [  s      c                 C   s   i }t | j}|dkr~|r~d|kr8|d r8|d |d< nd|d< d|krfd|krf|d |d g|d< nd|kr~t|d |d< |S )Nrb   Zca_certsZverifyTZ	cert_fileZkey_fileZcert)r   r   r)   )r#   ssl_detailsZssl_argsr   r$   r$   r%   _get_ssl_argsj  s    

r   )retry_afterr0   c                 C   s   zt | }W n~ tk
r   z.t| }|s2tdt t|t  }W n$ tk
rn   td|  d}Y nX |dk rtd d}Y nX |S )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.)floatrd   r   timemktimer<   info)r   Zto_waitZ
time_tupler$   r$   r%   _get_retry_after|  s(    

r   exception_cb)errorr   r0   c                C   s`   |r|| rdS | j rP| j dkrPtd | jrBt| jddS td dS |sXd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  zNEc2 IMDS endpoint returned a 503 error. HTTP endpoint is overloaded. Retrying.zRetry-After1z7Unable to introspect response header. Waiting 1 second.r   )r?   r<   r=   rG   r   r7   r   )r   r   r$   r$   r%   _handle_error  s    
r   r   TFr!   )r[   rC   retriessec_betweenrG   
headers_cbheaders_redactr   check_statusallow_redirectsr   sessioninfinitelog_req_resprequest_methodstream)r   r   r0   c                    s  t | } | |d}|t| | |
|d< |s:|r6dnd}||d< |dk	rpt|tr^||d< ntt|d|d< |dkr|g }d	}|rtt|d	 d	}d
t	  }|dk	r|
 }ni }|r||d< |dkrd}|dkrt }t D ]}|r|| }d|kr
||d< ||d< i }| D ]p\} |dkr4q|dkr|r fdd|D }|rt
 ||< |D ]}t|| |< qnn ||< qzh|rtd||rdn|| | |jf |}|	r|  td| |jt|j|d	  t|W   S  tjk
r, } zt|| d|W 5 d}~X Y nz tjk
rl } z t||jj|jj| d}|}W 5 d}~X Y n: tjk
r } zt|| d}|}d}W 5 d}~X Y nX t ||d}|s|p|d	 |k }|s|||p|}|dkr|rtd| t!"| qt#ddS )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   ZPOSTZGETmethodNrC   r   r   zCloud-Init/%sr[   z
User-AgentrG   c                    s   g | ]}  |r|qS r$   )r7   ).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#   r?   rG   r#   r   1Please wait %s seconds while we wait to try againz"This path should be unreachable...)$r&   updater   r9   tuplemaxr   r   r   Zversion_stringcopyr   ZSessionr   itemsdeepcopyr   r<   rR   Zrequestraise_for_statusr   lenr   r`   r   ZSSLErrorr   	HTTPErrorr   rG   ZRequestExceptionr   r   sleepRuntimeError) r#   r[   rC   r   r   rG   r   r   r   r   r   r   r   r   r   r   r   Zreq_argsZmanual_triesZ
user_agentiZfiltered_req_argsr   Zmatched_headerskeyr   rW   Z	url_errorZraised_exceptionZresponse_sleep_timeZ
will_retry
sleep_timer$   r   r%   re     s    5






re   .)funcaddrrC   eventdelayr0   c                 C   s   |r|j |drdS | ||S )z Execute func with optional delayrC   Nwaitr   r   rC   r   r   r$   r$   r%   _run_func_with_delayp  s    r   333333?
   )r   	addressesstagger_delayrC   r0   c                    s$  d}d}d}g }t  tt|d zz fddt|D }t|dD ]N}	||	 }|	 }
|
r||
}|| qT|		 }|rT
  ||f  W W nS qT|rtd|| |ntd	| td
W n6 tk
r   tdd|dtt| Y nX W 5  jdd X ||fS )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)Zmax_workersFr   c              
      s,   i | ]$\}} j t|| d |qS )r   )Zsubmitr   )r   r   r   Zexecutorr   Zis_doner   rC   r$   r%   
<dictcomp>  s   	zdual_stack.<locals>.<dictcomp>r   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   Zshutdown	enumerater   	exceptionappendresultsetr<   r=   r   rd   r   joinmapr)   )r   r   r   rC   Zreturn_resultZreturned_addressZlast_exceptionr   ZfuturesZfutureZreturn_exceptionr$   r   r%   
dual_stack  sJ    	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)rt   ru   rv   r   r)   __annotations__r`   r   r$   r$   r$   r%   r     s   
r   inf)max_waitrC   	status_cbr   r   r   r   sleep_time_cbr   connect_synchronouslyasync_delay)
r   rC   r   r   r   r   r   r   r   r   c                   s  t td
fdd}dtttdddtt tt ttt tf dd	d
ttgttt tt f f t	tt
t f t tttdfddtt td	fddtdfdd}td fdd}t }
r|rtd|
r|n|}|p|}dd}|||||}d|jrB|j|jjfS |jrft|j d dq||}||rqވd td| t| t }|r|| | kr||  }|dkrqސqdS )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_numberr0   c                    s    d k	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krdS | dkp.t | | | kS )z4Check if time is up based on start time and max waitr   NFr   )r   r   	monotonicr   r$   r$   r%   timeup  s
    zwait_for_url.<locals>.timeup)r   r#   r0   c              
   S   s   d}d}| r|s(d}t t|}||fS z| j  W nN tjjk
r } z,t ||jj|jj	|d}|t
|f W Y S d}~X Y nX | jsd| j }t t|| j| j	|d}n*|  sd| 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   rd   r   r   r   r   r   r   r   rG   r)   r^   r?   rp   )r   r#   reasonurl_excrW   r$   r$   r%   handle_url_response  sB    "

z)wait_for_url.<locals>.handle_url_response)url_reader_cburlsr   exc_cblog_cbr0   c              
      s   d}d}z2| |\}} ||\}}|s8t ||ddW S W nZ tk
rh }	 zd|	 }|	}W 5 d}	~	X Y n. tk
r }	 zd|	 }|	}W 5 d}	~	X Y nX tt | }
rd nd}d|pt|d	d	|
||f }|| t ddt|trt||d
nddS )z:Execute request, handle response, optionally log exceptionr!   N)r   zrequest error [%s]zunexpected error [%s]z%ssZ	unlimitedzCalling '%s' failed [%s/%s]: %sr#   r   r#   r   r   )	r   r   	Exceptionr   r   r   getattrr9   r   )r   r   r   r   r   r   r#   r   r   rW   Z
time_takenZmax_wait_strZ
status_msg)r   r   r$   r%   read_url_handle_exceptionsA  s:    
z0wait_for_url.<locals>.read_url_handle_exceptions)r#   rC   r0   c                    s$   t |  d kri n | |ddS )NF)rG   r   rC   r   r   )re   )r#   rC   )r   r   r   r$   r%   read_url_cbm  s    z!wait_for_url.<locals>.read_url_cbr/   c           
         s   t d fdd}g }D ]}t }dkr|s|| rPtdddd  S dk	r| r||  |  kr|t|  |  ||| ||}|jr|  S |jr||j q|rt|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 ri   r$   r   )r   rC   r$   r%   url_reader_serial~  s    z@wait_for_url.<locals>.read_url_serial.<locals>.url_reader_serialr   Nr   )	r)   r   r   r   r   r   r   r   r   )
r   rC   r   r   r   Z
wait_timesr#   Znowoutr   )loop_nr   must_try_againr   r   r   r   r   r%   read_url_serialw  s>    
  
    z%wait_for_url.<locals>.read_url_serialc                    s    t t |d}|| ||S )zpass list of urls to dual_stack which sends requests in parallel
        handle response and exceptions of the first endpoint to respond
        )r   rC   )r   r   )r   rC   r   r   Zurl_reader_parallel)r   r   r   r   r$   r%   read_url_parallel  s        z'wait_for_url.<locals>.read_url_parallelz3sleep_time and sleep_time_cb are mutually exclusiveNFr   Tr   )FN)r   )r   r   r   r`   r)   r   r   r   r
   r   r   ExceptionCallbackr   r   r   rd   r   r#   r^   r   r   r<   rR   )r   r   rC   r   r   r   r   r   r   r   r   r   r   r   r   r   Zdo_read_urlZcalculate_sleep_timer   ZrespZcurrent_sleep_timeZcurrent_timer$   )r   r   r   r   r   r   r   r   r   r   r   r   r   r%   wait_for_url  sh    /	 *,&



r   c                   @   s^   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|sNd| _nt|s^t	d| 
 }|pli | _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allrd   read_skew_file	skew_data)rk   r   r   r  r   r  Zrequiredoldr$   r$   r%   rl     s     
zOauthUrlHelper.__init__c                 C   sn   | j rjtj| j rjtd| j  > t| j dd$}t|W  5 Q R  W  5 Q R  S Q R X W 5 Q R X d S )NzReading rmode)	r  osr+   isfiler   Timedopenjsonload)rk   fpr$   r$   r%   r    s     2zOauthUrlHelper.read_skew_filec              
   C   sr   | j s
d S |  }|d kri }|||< td| j  0 t| j dd}|t| W 5 Q R X W 5 Q R X d S )NzWriting wr  )r  r  r   r  r  rT   r  dumps)rk   rK   valueZcurr  r$   r$   r%   update_skew_file  s     zOauthUrlHelper.update_skew_filec              
   C   s   t |tr|jdks"|jdks"d S d|jkr>td|j d S |jd }ztt|}W n6 t	k
r } ztd|| W Y d S d }~X Y nX t
|t  }t|jj}| j|d}t|| | jkr| || 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)r9   r   r?   rG   r<   r=   r   r   r   r   r   r   r#   netlocr  r7   absr  r  )rk   r   r  Zremote_timerW   ZskewrK   Zold_skewr$   r$   r%   r     s0    


zOauthUrlHelper.exception_cbc                 C   sZ   | j s
i S d }t|j}| jr>|| jkr>tt | j|  }t|| j| j| j	| j
|dS )N)r#   r   r   r  r   	timestamp)r  r   r  r  r   r   oauth_headersr   r   r  r   )rk   r#   r  rK   r$   r$   r%   r   *  s    
zOauthUrlHelper.headers_cbc                 C   s6   t | j|d|d< t | j|d|d< |||S )Nr   r   )r   _headers_cbr7   _exception_cb)rk   Zwrapped_funcro   rD   r$   r$   r%   _wrapped<  s      zOauthUrlHelper._wrappedc                 O   s   |  t||S ri   )r  r   rn   r$   r$   r%   r   E  s    zOauthUrlHelper.wait_for_urlc                 O   s   |  t||S ri   )r  re   rn   r$   r$   r%   re   H  s    zOauthUrlHelper.readurlc              	   C   s&   d }z|r||}W 5 |  | X |S ri   r   )rk   Zextra_exception_cbr   Zretr$   r$   r%   r  K  s    zOauthUrlHelper._exception_cbc                 C   s$   i }|r||}| | | |S ri   )r   r   )rk   Zextra_headers_cbr#   rG   r$   r$   r%   r  T  s
    zOauthUrlHelper._headers_cb)NNNNr   )rt   ru   rv   rl   r  r  r   r   r  r   re   r  r  r$   r$   r$   r%   r     s        
		r   c              
   C   s|   zdd l m} W n, tk
r< } ztd|W 5 d }~X Y nX |rLt|}nd }|j|||||j|d}|| \}	}
}|
S )Nr   zoauth support is not available)Zclient_secretZresource_owner_keyZresource_owner_secretZsignature_methodr  )Zoauthlib.oauth1oauth1ImportErrorNotImplementedErrorr)   ZClientZSIGNATURE_PLAINTEXTZsign)r#   r   r   r  r   r  r   rW   ZclientZ_uriZsigned_headersZ_bodyr$   r$   r%   r  \  s"    
r  )rA   )N)r   r   )N)Mr   r4   rP   r  Zloggingr  r   r   Zconcurrent.futuresr   r   r   Zemail.utilsr   	functoolsr   Zhttp.clientr   	itertoolsr   Zsslr	   typingr
   r   r   r   r   r   r   r   r   Zurllib.parser   r   r   r   r   r   Z	cloudinitr   r   r   Z	getLoggerrt   r<   r   r   r   r&   r.   r   r@   r)   r   dictrY   r_   rf   rg   rZ   rB   r`   r]   r   r   r   r   re   r   r   r   r   rR   r   r   r  r$   r$   r$   r%   <module>   s   ,

 1%% 6 
  
S    