a )g@sdZddlmZmZmZeZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mmmZdddZdddZddd Zdd d Zdd dZdddZddZdddZdS)a This module adds shared support for generic api modules In order to use this module, include it as part of a custom module as shown below. The 'api' module provides the following common argument specs: * rate limit spec - rate: number of requests per time unit (int) - rate_limit: time window in which the limit is applied in seconds * retry spec - retries: number of attempts - retry_pause: delay between attempts in seconds )absolute_importdivisionprint_functionNcCs*ttddtddd}|r&|||S)z7Creates an argument spec for working with rate limitinginttype)rate rate_limitdictupdatespecZarg_specrttddtdddtddtdddd}|r:|||S)NstrrT)rZno_logboolr)Z api_usernameZ api_passwordZapi_urlZvalidate_certsr r rrrbasic_auth_argument_spec=s   rcs4d|dur$|dur$t|t|fdd}|S)zrate limiting decoratorNcsdgfdd}|S)Ngcsdtjdkrtj}ntj}durR|d}|}|dkrHt||d<|i|}|S)N)r)sys version_infotime process_timeZclocksleep)argskwargsZ real_timeelapsedleftret)flastminraterr ratelimitedRs   z0rate_limit..wrapper..ratelimitedr)r)r,r+)r)r*rwrapperOszrate_limit..wrapper)r)rr r.rr-rr Is  r rcsfdd}|S)zRetry decoratorcsfdd}|S)Ncsld}durhd}|d7}|kr,tdz|i|}WntyPYn0|rXqdtq|SdS)NrrzRetry limit exceeded: %d) Exceptionr!r#)r$r%Z retry_countr()r)rrrrretriedhs   z'retry..wrapper..retriedr)r)r0r)r)rr.fszretry..wrapperr)rrr.rrrretrydsr1 r<c cs0td|D] }tdt||d|Vq dS)aDThe "Full Jitter" backoff strategy. Ref: https://www.awsarchitectureblog.com/2015/03/backoff.html :param retries: The number of delays to generate. :param delay_base: The base time in seconds used to calculate the exponential backoff. :param delay_threshold: The maximum time in seconds for any delay. rN)rangerandomZrandintmin)rZ delay_baseZdelay_thresholdr1rrrgenerate_jittered_backoff}s r8cCsdS)NFr)Zexception_or_resultrrr retry_neversr9cs0dd}||~durtfdd}|S)zGeneric retry decorator. :param backoff_iterator: An iterable of delays in seconds. :param should_retry_error: A callable that takes an exception of the decorated function and decides whether to retry or not (returns a bool). css&t|\}}|Vt|VqdS)N) itertoolsteecopy)Zoriginal_iteratorZ_copiable_iteratorZ_first_iterator_copyrrr_emit_isolated_iterator_copiesszGretry_with_delays_and_condition.._emit_isolated_iterator_copiesNcstfdd}|S)Nc srtjg|Ri|}tD]J}z |WSty^}z|sJWYd}~n d}~00t|q |S)zThis assumes the function has not already been called. If backoff_iterator is empty, we should still run the function a single time with no delay. N) functoolspartialnextr/r!r#)r$r%Zcall_retryable_functionZdelaye)backoff_iterator_generatorfunctionshould_retry_errorrr run_functions   zOretry_with_delays_and_condition..function_wrapper..run_function)r>wraps)rCrErBrD)rCrfunction_wrappersz9retry_with_delays_and_condition..function_wrapper)r9)Zbackoff_iteratorrDr=rHrrGrretry_with_delays_and_conditionsrI)N)N)N)NN)Nr)r2rr3)N)__doc__Z __future__rrrrZ __metaclass__r<r>r:r6rr!Z"ansible.module_utils.compat.typingZ module_utilscompattypingtrrrr r1r8r9rIrrrr s"