
    x[h                        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jV                  e,      Z-dZ.eedge/f      Z0d Z1d Z2de3fdZ4dKde5de6de7ddfdZ8de5ddfdZ9ded   fdZ: G d d      Z; G d de;      Z< G d de;      Z= G d  d!      Z> G d" de?      Z@d# ZAd$e5de6fd%ZBdd&d'e@d(e0dee6   fd)ZCddd d*ddddd+d+ddd,d+d-d,d.d(e0d/e/de>fd0ZD	 dLd1ed2ef   d3e5de3d4ej                  d5ee6   defd6ZF	 	 dMd1ed2ef   d8ee5   d9e6de3deee5   ee>   f   f
d:ZG G d; d<e      ZH e6d=      de-j                  dddddd-d+d7d>d?e6dee6   d@edAee   dBee6   d(e0dCeeee6ge6f      dDe5dEe/dFe6fdGZJ G dH dI      ZK	 dLdJZLy)N    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                 r    t        t        | d            }|d   s|d   r|d   |d<   d|d<   t        |      S )Nhttp)scheme       )listr   r   )url
parsed_urls     6/usr/lib/python3/dist-packages/cloudinit/url_helper.py	_cleanurlr(   1   sC    hs623Ja=Z] #1
1
1j!!    c                 0    d }| }|D ]  } |||      } |S )Nc                     t        t        |             }|d   }|r|j                  d      s|dz  }|t        t	        |      d      z  }||d<   t        |      S )Nr"   /z/:)safe)r$   r   endswithr   strr   )r%   add_on
url_parsedpaths       r'   combine_singlez#combine_url.<locals>.combine_single<   sY    (3-(
!}c*CKDc&k--
1*%%r)    )baseadd_onsr3   r%   r0   s        r'   combine_urlr7   ;   s.    & C *S&)*Jr)   returnc           
      8   t         j                  dt         j                  dt         j                  dt         j                  dt
        di}|j                  t        |             }|s5t        | t              r| j                  }|S t        j                  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codes      r'   "ftp_get_return_code_from_exceptionrM   K   s     	C33C#O tCy)Dc7#99D K	 KKK DKr)   r%   timeoutkwargsFtpResponsec           	      L   t        |       }|j                  st        dt        d|       t	        j
                         5 }|j                  xs d}|j                  xs d}d|j                  k(  rH	 t        j                  t                     }t        j                  d| |       |j                  |j                  ||xs d	
       t        j                  d|       	 |j#                  ||j$                  xs d       t        j                  d       |j'                          	 t        j                  d|j,                         |j/                  d|j,                   |j0                         t3        |j5                         |       t        j                  d       |j7                          cddd       S 	 t        j8                         }
t        j                  d| |       |
j                  |j                  ||xs d	
       t        j                  d|       |
j#                  ||j$                  xs d       t        j                  d|j,                         |
j/                  d|j,                   |j0                         t3        |j5                         |       t        j                  d       |
j7                          cddd       S # t        j                  $ r'}t!        |      }	t        d|  d|	 d|	d|       |d}~ww xY w# t        j(                  $ r*}t        j+                  d       t        ddd|       |d}~ww xY w# t        j                  $ r'}t!        |      }	t        d|  d|	 d|	d|       |d}~ww xY w# t        j                  d       |j7                          w xY w# t        j                  $ r'}t!        |      }	t        d|  d|	 d|	d|       |d}~ww xY w# t        j                  d       
j7                          w xY w# 1 sw Y   yxY w)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causerL   headersr%      	anonymousftps)contextz3Attempting to connect to %s via port [%s] over tls.      @)hostportrN   z1Reading file from server over tls failed for url z []z"Attempting to login with user [%s]r#   )user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.r<   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BytesIOr[   usernamer    r=   FTP_TLSr
   rH   debugconnect
all_errorsrM   loginpasswordprot_pr@   rI   r2   
retrbinarywriterP   getvaluecloseFTP)r%   rN   rO   	url_partsbufferr[   r]   ftp_tlserL   ftps              r'   	read_ftpsru   b   s      I(y$C
 	
 
 j~~#!!0[Y%%% ..24 		I
 "++#Ns     II:DA$--3   		89 " 		,inn=""INN+,v|| #  #6??#4c: 		./Sj jVjjl		>T "++#Ns  
 		>E		$--3   		,inn=y~~&67&,,O"6??#4c: 		./		Uj j$ $$ 
9!<**-ba9   
& $$ C
 N  	 	. $$ 
9!<++.%r$q:   
 		./( $$ 
9!<++.%r$q:   
 		./		Uj js   1P1AKPAL&A#M	%P9C'N3 %PL	""LL		PM	%MM		PN"NNN		'N00P3O-"O((O--O00'PPP#r2   FileResponsec                 *   |j                  d      rt        j                  d|        	 t        j                  |       }t        ||       S # t        $ r}t        |t        d|       |d}~wt        $ r}t        ||j                  d|       |d}~ww xY 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 %sNrR   )rC   rH   rI   r   load_binary_filerv   FileNotFoundErrorr   r   IOErrorrG   )r2   rO   contentsrs   s       r'   
_read_filer}      s    
 zz&=tDM((.Hd++ OQY$GQN MQQWWdE1LMs#    A
 
	BA''B3BB)rv   UrlResponserP   c                 ^   | j                         } 	 t        |       }|j                  }|dk(  s
| rd| d   k(  rt        |j                  fi |S |dv rt        | fi |S |dv rt        | fi |S t        j                  d|       t        | fi |S # t        $ r}t        ||       |d}~ww xY w)	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.
    )rS   r%   Nfiler,   r   )rt   rW   )r   httpszAttempting unknown protocol %s)lstripr   
ValueErrorr   r    r}   r2   ru   readurlrH   rI   )r%   rO   parsedrs   r    s        r'   read_file_or_urlr      s     **,C0# ]]FCC3q6M&++000	?	"'''	$	$s%f%%4f=s%f%%  0QC(a/0s   B 	B,B''B,c                        e Zd ZddZd Zd Zy)StringResponsec                 <    || _         i | _        || _        || _        y N)rL   rT   r|   r%   )selfr|   r%   rL   s       r'   __init__zStringResponse.__init__  s    	 r)   c                      | j                   dk(  S )N   rL   r   argsrO   s      r'   okzStringResponse.ok  s    yyCr)   c                 8    | j                   j                  d      S )Nzutf-8)r|   decoder   s    r'   __str__zStringResponse.__str__  s    }}##G,,r)   Nr   )__name__
__module____qualname__r   r   r   r4   r)   r'   r   r     s     -r)   r   c                   *     e Zd Zddedef fdZ xZS )rv   r|   r%   c                 *    t         |   |||       y )Nr   superr   )r   r|   r%   rL   	__class__s       r'   r   zFileResponse.__init__!  s    3T2r)   r   r   r   r   bytesr/   r   __classcell__r   s   @r'   rv   rv      s    3 3S 3 3r)   c                   (     e Zd Zdedef fdZ xZS )rP   r|   r%   c                 &    t         |   ||       y r   r   )r   r|   r%   r   s      r'   r   zFtpResponse.__init__&  s    3'r)   r   r   s   @r'   rP   rP   %  s    ( (S ( (r)   c                       e Zd Zdej                  fdZedefd       Zede	fd       Z
ddefdZed        Zedefd       Zd	 Z	 dd
ee   dedee   fdZy)r~   responsec                     || _         y r   )	_response)r   r   s     r'   r   zUrlResponse.__init__+  s	    !r)   r8   c                 \    | j                   j                  y| j                   j                  S )Nr)   )r   contentr   s    r'   r|   zUrlResponse.contents.  s%    >>!!)~~%%%r)   c                 .    | j                   j                  S r   )r   r%   r   s    r'   r%   zUrlResponse.url4  s    ~~!!!r)   c                 @    d}|rd}d| j                   cxk  r|k  ry yy)Nr:   r;   r   TFr   )r   redirects_okuppers      r'   r   zUrlResponse.ok8  s-    E$))#e# $ r)   c                 .    | j                   j                  S r   )r   rT   r   s    r'   rT   zUrlResponse.headersA  s    ~~%%%r)   c                 .    | j                   j                  S r   )r   status_coder   s    r'   rL   zUrlResponse.codeE  s    ~~)))r)   c                 .    | j                   j                  S r   )r   textr   s    r'   r   zUrlResponse.__str__I  s    ~~"""r)   
chunk_sizedecode_unicodec              #   X   K   | j                   j                  ||      E d{    y7 w)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   s      r'   r   zUrlResponse.iter_contentL  s"      >>..z>JJJs    *(*N)F)r!   F)r   r   r   requestsResponser   propertyr   r|   r/   r%   boolr   rT   intrL   r   r   r   r   r4   r)   r'   r~   r~   *  s    "!2!2 " &% & &
 "S " "  & & *c * *# EJK"3-K=AK	%Kr)   r~   c            
       >    e Zd Z	 	 	 ddedee   dee   dee   fdZy)r   NrS   rL   rT   r%   c                     t         j                  | t        |             || _        || _        |i n|| _        || _        y r   )r{   r   r/   rS   rL   rT   r%   )r   rS   rL   rT   r%   s        r'   r   zUrlError.__init__\  s:     	s5z*
	&-o7r)   )NNN)	r   r   r   r   r   r   r   r/   r   r4   r)   r'   r   r   [  sE     #%)! sm '"	
 c]r)   c                     i }t        |       j                  }|dk(  rE|rCd|v r|d   r	|d   |d<   nd|d<   d|v rd|v r|d   |d   g|d<   |S d|v rt        |d         |d<   |S )Nr   ca_certsverifyT	cert_filekey_filecert)r   r    r/   )r%   ssl_detailsssl_argsr    s       r'   _get_ssl_argsr   j  s    Hc]!!F[$Z)@!,Z!8HX!%HX+%**CK(J' HV O K'";{#;<HVOr)   retry_afterc                 ^   	 t        |       }|S # t        $ r 	 t        |       }|st        d      t        t        j                  |      t        j                         z
        }n'# t        $ r t
        j                  d|        d}Y nw xY w|dk  rt
        j                  d       d}Y |S w xY 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.)floatr   r   timemktimerH   info)r   to_wait
time_tuples      r'   _get_retry_afterr   |  s    $, N+  	";/J !KLLDKK
3diikABG 	HH,
 G	 Q;HH, GN+s3    	B,AA%$B,%!B	B,B		B,+B,exception_cberrorr   c                   |r	 ||       ry| j                   rk| j                   dk(  r\t        j                  d       | j                  r%t	        | j                  j                  dd            S t        j                  d       y|sy| )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!   )rL   rH   rI   rT   r   rC   r   )r   r   s     r'   _handle_errorr     st    " U+zzejjC'5	
 ==#EMM$5$5mS$IJJJK
Kr)   r!   TFr#   )rx   rN   retriessec_betweenrT   
headers_cbheaders_redactr   check_statusallow_redirectsr   sessioninfinitelog_req_resprequest_methodstreamr   c          	      :   t        |       } | |d}|j                  t        | |             |
|d<   |s|rdnd}||d<   |.t        |t              r||d<   nt        t        |      d      |d<   |g }d	}|rt        t        |      d	z   d	      }d
t        j                         z  }||j                         }ni }|r||d<   |d}|t        j                         }t               D ]  }|r ||       }d|vr||d<   ||d<   i }|j                         D ]g  \  }}|dk(  r|dk(  rR|rP|D cg c]  }|j                  |      s| }}|s7t        j                   |      |<   |D ]  }t"        ||   |<    c|||<   i 	 |rt$        j'                  d||rdn|| |        |j(                  di |}|	r|j+                          t$        j'                  d| |j,                  t/        |j0                        |d	z          t3        |      c S  tI        d      c c}w # t4        j6                  $ r}t9        ||       |d}~wt4        j:                  $ rC}t9        ||j<                  j,                  |j<                  j>                  |       }|}Y d}~n4d}~wt4        j@                  $ r}t9        ||       }|}d}Y d}~nd}~ww xY wtC        ||      }|s|xs |d	z   |k  }|s|||xs |} |dkD  s	|rt$        j'                  d|       tE        jF                  |        8)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methodNrN   r   r!   zCloud-Init/%srx   z
User-AgentrT   z'[%s/%s] open '%s' with %s configurationr   z(Read from %s (%s, %sb) after %s attempts)r%   rL   rT   r%   r   1Please wait %s seconds while we wait to try againz"This path should be unreachable...r4   )%r(   updater   rE   tuplemaxr   r   r   version_stringcopyr   Sessionr	   itemsrC   deepcopyr   rH   re   requestraise_for_statusr   lenr   r~   r   SSLErrorr   	HTTPErrorr   rT   RequestExceptionr   r   sleepRuntimeError)!r%   rx   rN   r   r   rT   r   r   r   r   r   r   r   r   r   r   r   req_argsmanual_tries
user_agentifiltered_req_argskvmatched_headerskeyr   rs   	url_errorraised_exceptionresponse_sleep_time
will_retry
sleep_times!                                    r'   r   r     sg   j C.CH OOM#{34"1H#'U'HXgu%")HY"%eGna"8HYL3w<!+Q/ G$:$:$<=J,,.""$ W Q# oGw&$.GL!%NN$ 
	)DAqF{I~..<"Ia1"I"I"+/==+;%a(. =4<)!,S1= ()!!$
	)(			="*J% 'w22H))+II:$$H$$%Q x(([Q#f ;
<<M #JB "" 	. 1#&A-## 	! ZZ++

**	I  !** 	 ,I H	
 ,%
 #!;a!el&:J%55(7K
?		G JJz"s=   *HH>BHJ>+H99J>9JJ>#J99J>func.addreventdelayc                 >    |r|j                  |      ry | ||      S )z Execute func with optional delayrN   Nwaitr  r	  rN   r
  r  s        r'   _run_func_with_delayr  p  s'     
 ::e:$gr)   333333?	addressesstagger_delayc                 N   d}d}d}g }t        j                         }t        t        |            }		 t	        |      D 
ci c]$  \  }
}|	j                  t        | ||||
|z        |& }}
}t        ||      D ]h  }||   }|j                         }|r|} |j                  |       /|j                         }|sB|j                          ||fc |	j                  d       S  |rt        j                  d||       |t        j                  d|       t!        d	      c c}}
w # t"        $ rF t        j                  d
dj%                  |      dj%                  t'        t(        |                   Y nw xY w	 |	j                  d       ||fS # |	j                  d       w xY 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_workersr  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   	enumeratesubmitr  r   	exceptionappendresultsetshutdownrH   re   r   r   r   joinmapr/   )r  r  r  rN   return_resultreturned_addresslast_exceptionr   is_doneexecutorr   r	  futuresfuturereturn_exceptions                  r'   
dual_stackr+    s    M.2NJooG "c)n=H5& %Y/

 4 OO$=(   

 

 #7G< 	=F&v%//1!1!
!!.1 &  KKM,m<<2 	u%O	=$ II- 	 ! II35EF122S

X  
		4HHYHHSj)*		

	
 	u%m,, 	u%s>   D' )D!*AD' <D' $AD' 'AE63F 5E66F F$c                   >    e Zd ZU ee   ed<   ee   ed<   ee   ed<   y)HandledResponser%   r   	wait_timeN)r   r   r   r   r/   __annotations__r~   r   r4   r)   r'   r-  r-    s#    	#{## r)   r-  inf)max_waitrN   	status_cbr   r   r  r   sleep_time_cbr   connect_synchronouslyasync_delayr1  r2  r   r  r3  r   r4  r5  c                T   	 dt         dt        ffd}ddt        dt        dt        fdd	t        t           d
t        t           dt
        t        t           t        f   f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
t        dt         dt        f	fddt        f fd}dt        f fd}t        j                         }r|rt        d      |
r|n|}|xs |}dd}	  |||||      }d|j                   r"|j"                  |j                   j$                  fS |j&                  r't        j(                  |j&                         dz   do ||      } ||      r	 ydz   t*        j-                  d|       t        j(                  |       t        j                         }|r||z   |z   kD  r||z
  z
  }|dk  r	 y)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_numberr8   c                     S |dz  dz   S )N   r!   r4   )_r7  r  s     r'   default_sleep_timez(wait_for_url.<locals>.default_sleep_time  s    '3zM9IA9MMr)   r   r1  
start_timer  c                 j    | t        d      dfv ry| dk  xs t        j                         |z
  |z   | kD  S )z4Check if time is up based on start time and max waitr0  NFr   )r   r   	monotonic)r1  r<  r  s      r'   timeupzwait_for_url.<locals>.timeup  s@    ed++A 
NNz)J6A	
r)   r   r%   c                    d}d}| r|sd}t        t        |            }||fS 	 | j                  j                          | j                  s?d| j                  z  }t        t        |      | j                  | j                  |      }||fS | j                         s;d| j                  z  }t        t        |      | j                  | j                  |      }||fS # t        j
                  j                  $ rN}t        ||j                  j                  |j                  j                  |      }|t        |      fcY d}~S d}~ww xY w)z?Map requests response code/contents to internal "UrlError" typer#   NzRequest timed outr   zempty response [%s]zbad status code [%s])r   r   r   r   r   r   r   r   r   rT   r/   r|   rL   r   )r   r%   reasonurl_excrs   s        r'   handle_url_responsez)wait_for_url.<locals>.handle_url_response  s8    S(Fz&12GF?"	# //1   *hmm<F6"]] ((	G    +x}}=F6"]] ((	G   3 "",, 	#ZZ++

**	G CF?"	#s   C E5AD>8E>Eurl_reader_cburlsexc_cblog_cbc                    d}d}	  | |      \  }} ||      \  }}|st        ||d      S 	 t        t	        j
                         |z
        }
rdz  nd}d|xs t        |d	d	      d
|
d|d|} ||       t        ddt        |t              rt        ||            S d      S # t        $ r}	d|	z  }|	}Y d}	~	d}	~	wt        $ r}	d|	z  }|	}Y d}	~	d}	~	ww xY w)z:Execute request, handle response, optionally log exceptionr#   N)r.  zrequest error [%s]zunexpected error [%s]z%ss	unlimitedz	Calling 'r%   z
' failed [r,   z]: r   r%   r   r.  )	r-  r   	Exceptionr   r   r>  getattrrE   r   )rD  rE  r<  rF  rG  rA  r%   r   rB  rs   
time_takenmax_wait_str
status_msgrC  r1  s                r'   read_url_handle_exceptionsz0wait_for_url.<locals>.read_url_handle_exceptionsA  s    
	)$/MC1(C@OGV&sHEE  )J67
+3ux'177E511	

 	z gx0 gF;	
 	
 
 	
!  	)A-FG 	,q0FG	s#   &B- -	C6CCCCrN   c                 :    t        | i n |       |d      S )NF)rT   r   rN   r   r   )r   )r%   rN   r   r   r   s     r'   read_url_cbz!wait_for_url.<locals>.read_url_cbm  s-    $,B*S/))
 	
r)   c                    dt         ffd}g }D ]  }t        j                         }
dk7  r;s9 |       rt        ddd      c S r|z   | z   kD  rt	        | z   |z
         ||| ||      }|j
                  r|c S |j                  s|j                  |j                          |rt        |      nd}	t        dd|	      S )z|iterate over list of urls, request each one and handle responses
        and thrown exceptions individually per url
        r%   c                     |  |       fS r   r4   )r%   rR  rN   s    r'   url_reader_serialz@wait_for_url.<locals>.read_url_serial.<locals>.url_reader_serial~  s    S'233r)   r   NrJ  )	r/   r   r>  r-  r   r   r.  r  r   )r<  rN   rF  rG  rU  
wait_timesr%   nowoutr.  loop_nr1  must_try_againrR  rP  r?  rE  s    `        r'   read_url_serialz%wait_for_url.<locals>.read_url_serialw  s    	43 	4 
 	1C.."C{>(J/* 44  (w*x*?@ ":#8C"?@G,!3
FFC ||
!!#--0+	1, (2C
Ot	4$)LLr)   c                 B    t        t        |      } || ||      S )zpass list of urls to dual_stack which sends requests in parallel
        handle response and exceptions of the first endpoint to respond
        )r  rN   )r   r+  )	r<  rN   rF  rG  url_reader_parallelr5  rR  rP  rE  s	        r'   read_url_parallelz'wait_for_url.<locals>.read_url_parallel  s6     &%	
 *z66
 	
r)   z3sleep_time and sleep_time_cb are mutually exclusiveNTFr!   r   )FN)r   )r   r   r   r~   r/   r   r   r   r   r   r   ExceptionCallbackr-  r   r>  r   r   r%   r|   r.  r   rH   re   )rE  r1  rN   r2  r   r   r  r   r3  r   r4  r5  r;  r[  r^  r<  do_read_urlcalculate_sleep_timer   respcurrent_sleep_timecurrent_timerC  rY  rZ  rR  rP  r?  s   ``  ```  ` `          @@@@@@r'   wait_for_urlre    sS   ^N3 N5 N
 
E 
u 
'!;''!.6sm'!	x!3&	''!R*
E5#(==>>
*
 CcN#	*

 *
 "*
 *
 
*
X
 
s 
{ 
"M	"M "MH
	
 
  !JmNOO 16G  )>,>FH
:wiH==88T]]3333^^JJt~~&aZF!N1(FC(J(:;"  !		?	
 	

%& ~~'|g-
X0EE,";<G!|= r)   c                   T    e Zd Z	 	 	 	 	 ddZd Zd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zy)OauthUrlHelperNc                 <   || _         |xs d| _        || _        || _        || _        d| _        d| _        | j                  | j                  | j                   f}t        |      sd| _        nt        |      st        d      | j                         }|xs i | _        y )Nr#   Tr9  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allr   read_skew_file	skew_data)r   ri  rk  rl  rj  rm  requiredolds           r'   r   zOauthUrlHelper.__init__  s     ).4""(,!"NND$5$5t7H7HI8}"DNX* 
 !!#r)   c                 t   | j                   rt        j                  j                  | j                         rbt	        j
                  d| j                          5  t        | j                   d      5 }t        j                  |      cd d d        cd d d        S y # 1 sw Y   nxY wd d d        y # 1 sw Y   y xY w)NzReading rmode)	rm  osr2   isfiler   Timedopenjsonload)r   fps     r'   rr  zOauthUrlHelper.read_skew_file  s    277>>$2E2E#F""Xd.A.A-B#CD %d###G %yy}% % % 	% % % 	% s$   B.0B	B.B"	B..B7c                 ^   | j                   sy | j                         }|i }|||<   t        j                  d| j                          5  t	        | j                   d      5 }|j                  t        j                  |             d d d        d d d        y # 1 sw Y   xY w# 1 sw Y   y xY w)NzWriting wrx  )rm  rr  r   r|  r}  rl   r~  dumps)r   rZ   valuecurr  s        r'   update_skew_filezOauthUrlHelper.update_skew_file  s    ""!!#;CD	$*=*=)>?@ 	&$cC
 	&HHTZZ_%	& 	& 	& 	& 	& 	&s$   	B#!%BB#B 	B##B,c                    t        |t              r|j                  dk(  s|j                  dk(  sy d|j                  vr!t        j                  d|j                         y |j                  d   }	 t        j                  t        |            }t        |t        j                         z
        }t        |j                        j                  }| j                  j                  |d      }t!        ||z
        | j"                  kD  r)| j%                  ||       t        j                  d||       || j                  |<   y # t        $ r!}t        j                  d||       Y d }~y d }~ww xY w)Ni  i  datez$Missing header 'date' in %s responsez#Failed to convert datetime '%s': %sr   z$Setting oauth clockskew for %s to %d)rE   r   rL   rT   rH   rI   r   r   r   rK  r   r   r%   netlocrs  rC   absro  r  )r   r  r  remote_timers   skewrZ   old_skews           r'   r   zOauthUrlHelper.exception_cb  s!   y(+3&)..C*?***KK>	O  (	++io6K
 ;,-	&-->>%%dA.x$$"8"88!!$-KK>dK#t  	KK=tQG	s   /D< <	E&E!!E&c                 L   | j                   si S d }t        |      j                  }| j                  r;|| j                  v r-t	        t        j
                               | j                  |   z   }t        || j                  | j                  | j                  | j                  |      S )N)r%   ri  rk  rl  rj  	timestamp)rn  r   r  rs  r   r   oauth_headersri  rk  rl  rj  )r   r%   r  rZ   s       r'   r   zOauthUrlHelper.headers_cb*  s    ~~I	}##>>ddnn4DIIK(4>>$+??I**nn** 00
 	
r)   c                     t        | j                  |j                  d            |d<   t        | j                  |j                  d            |d<    ||i |S )Nr   r   )r   _headers_cbrC   _exception_cb)r   wrapped_funcr   rO   s       r'   _wrappedzOauthUrlHelper._wrapped<  s\    &fjj6 
| ")

> :"
~ T,V,,r)   c                 0    | j                  t        ||      S r   )r  re  r   s      r'   re  zOauthUrlHelper.wait_for_urlE  s    }}\488r)   c                 0    | j                  t        ||      S r   )r  r   r   s      r'   r   zOauthUrlHelper.readurlH  s    }}WdF33r)   c                 n    d}	 |r ||      }| j                  |       |S # | j                  |       w xY w)NTr   )r   extra_exception_cbr  rets       r'   r  zOauthUrlHelper._exception_cbK  s>    	)!(3i(
 i(s   
! 4c                 ^    i }|r ||      }|j                  | j                  |             |S r   )r   r   )r   extra_headers_cbr%   rT   s       r'   r  zOauthUrlHelper._headers_cbT  s.    &s+Gts+,r)   )NNNNz/run/oauth_skew.json)r   r   r   r   rr  r  r   r   r  re  r   r  r  r4   r)   r'   rg  rg    sE     -#6&8
$-94r)   rg  c                     	 dd l m} |rt	        |      }nd }|j                  |||||j                  |      }|j                  |       \  }	}
}|
S # t        $ r}t        d      |d }~ww xY w)Nr   zoauth support is not available)client_secretresource_owner_keyresource_owner_secretsignature_methodr  )oauthlib.oauth1oauth1ImportErrorNotImplementedErrorr/   ClientSIGNATURE_PLAINTEXTsign)r%   ri  rk  rl  rj  r  r  rs   client_urisigned_headers_bodys               r'   r  r  \  s    K( 	N		]]%$*33  F #)++c"2D.%#  K!"BCJKs   A 	A*A%%A*)rY   r   )r  
   )Mr   r=   ra   r~  loggingrz  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   rH   r   r   r_  r(   r7   r   rM   r/   r   dictru   r}   r   r   rv   rP   r~   r{   r   r   r   r   r   r  r  r+  r-  re   re  rg  r  r4   r)   r'   <module>r     s^     	   	   M M !  !  &
 
 
 ? >   0 0g!XzlD&89: " s .3    DMS M~ M &
78&<- -3> 3
(. (
.K .Kbw $# % J '+ $ e_	J 
&*%m= $m=$ %m=& 'm=j "
38

  ??	
 E? 	* !	P-
38
P-CyP- P- 	P-
 8C=(;//0P-fj  El#))%)"&&*=A"&| | e_	|
 | "| | $| Hc5\5%89:| |  | |~| |@ LPr)   