
    1                        S r SSKJr  SSKJr  SSKJr  SSKrSSKJr  SSKJ	r
  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSKJr  S \
R2                  \
R4                  \
R4                  \
R6                  S \
R8                  S.rS)S jrS rS r S r!S r"S r#S r$S r%S r&S r'S r(S r)S  r*S! r+\RX                  RZ                  4S" jr.S# r/S$ r0S% r1S& r2S' r3S( r4g)*zUtilities for `gcloud app deploy <queue|cron>.yaml` deployments.

Functions defined here are used to migrate away from soon to be deprecated
admin-console-hr superapp. Instead we will be using Cloud Tasks APIs.
    )absolute_import)division)unicode_literalsN)util)task_queues_convertors)base)parser_extensions)app)	constants)flags)parsers)
exceptions)
properties)urllibc           	      @    [        S[        S[        U 5      5      5      $ )Ni     )minmaxintxs    =lib/googlecloudsdk/api_lib/tasks/app_deploy_migration_util.py<lambda>r   .   s    T3q#a&>)B    c                     [        U 5      S-   $ )Nr   )r   r   s    r   r   r   3   s    3q6A:r   )max_concurrent_requestsratez$retry_parameters.min_backoff_secondsz$retry_parameters.max_backoff_secondszretry_parameters.task_age_limitz!retry_parameters.task_retry_limittargetc           
      t    [        X-
  5      [        U[        [        U 5      [        U5      5      -  U5      :*  $ )a  Checks if two numerical values are same or almost the same.

This function is only created to provides backwards compatability for python2
which does not support 'math.isclose(...)' function. The output of this
function mimicks exactly the behavior of math.isclose.

Args:
  a: One of the values to be tested for relative closeness.
  b: One of the values to be tested for relative closeness.
  rel_tol: Relative tolerance allowed. Default value is set so that the two
    values must be equivalent to 9 decimal digits.
  abs_tol: The minimum absoulute tolerance difference. Useful for
    comparisons near zero.

Returns:
  True if the attribute needs to be updated to the new value, False otherwise.
)absr   )abrel_tolabs_tols       r   IsCloser%   8   s0    $ 
QSS3s1vs1v#66@	@@r   c                    [         R                  " U5      n[        U S5      (       a2  [        U R                  U5      (       a  [	        U R                  U5      nO3[        U R
                  U5      (       a  [	        U R
                  U5      nOgXB:X  a  gUc2  US:w  a,  U[        R                  ;   a  U[        R                  U   :X  a  gUS:X  a  U(       d  gUb  Uc  g[         R                  " U5      n[         R                  " U5      n[        U[        5      (       a%  [        U[        5      (       a  [        XB5      (       + $ XB:g  $ )a  Checks whether the attribute & value provided need to be updated.

Note: We only check if the attribute exists in `queue.rateLimits` and
`queue.retryConfig` since those are the only attributes we verify here. The
only attribute we do not verify here is app-engine routing override which we
handle separately.

Args:
  cur_queue_state: apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue,
    The Queue instance fetched from the backend.
  attribute: Snake case representation of the CT API attribute name. One
    example is 'max_burst_size'.
  new_value: The value we are trying to set this attribute to.

Returns:
  True if the attribute needs to be updated to the new value, False otherwise.

rateLimitsTFmax_concurrent_dispatchesmax_dispatches_per_second)
convertorsConvertStringToCamelCasehasattrr'   getattrretryConfigr   %PUSH_QUEUES_APP_DEPLOY_DEFAULT_VALUES(CheckAndConvertStringToFloatIfApplicable
isinstancefloatr%   )cur_queue_state	attribute	new_valueproto_attribute_name	old_values        r   _DoesAttributeNeedToBeUpdatedr8   M   s    $ $<<YGo|,,o((*>??224HII**,@AA335IJI ..9BBB9BB9MM--i )+AA)L)AA)L)E""E""y,,,		r   c                      X R                   U'   g)a  Sets the specified key, value pair in the namespace provided.

The main reason to have this function is to centralize all the protected
access to _specified_args

Args:
  cloud_task_args: argparse.Namespace, A placeholder args namespace built to
    pass on forwards to Cloud Tasks API.
  key: The attribute key we are trying to set.
  value: The attribute value we are trying to set.
N_specified_args)cloud_task_argskeyvalues      r   _SetSpecifiedArgr?      s     */!!#&r   c                     U R                   U	 g)zDeletes the specified key in the namespace provided.

Args:
  cloud_task_args: argparse.Namespace, A placeholder args namespace built to
    pass on forwards to Cloud Tasks API.
  key: The attribute key we are trying to set.
Nr:   )r<   r=   s     r   _DeleteSpecifiedArgrA      s     %%c*r   c                    U R                   S:X  a  g[        R                  " U R                  5      n[        R                  " U R                  5      nX4:  a\  U(       a+  UnU R                  U l        [        U SU R                  5        O*UnU R                  U l        [        U SU R                  5        U(       a  UR                  (       a  [        R                  " UR                  R                  5      n[        R                  " UR                  R                  5      nXF:X  a-  X5:X  a'  [        U S5        SU l        [        U S5        SU l        ggggg)a!  Checks min and max backoff values and updates the other value if needed.

When uploading via queue.yaml files, if only one of the backoff values is
specified, the other value will automatically be updated to the default
value. If the default value does not satisfy the condition
min_backoff <= max_backoff, then it is set equal to the other backoff value.

Args:
  cloud_task_args: argparse.Namespace, A placeholder args namespace built to
    pass on forwards to Cloud Tasks API.
  used_default_value_for_min_backoff: A boolean value telling us if we used
    a default value for min_backoff or if it was specified explicitly in the
    YAML file.
  cur_queue_state: apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue,
    The Queue instance fetched from the backend if it exists, None otherwise.
pullNmin_backoffmax_backoff)
typer*   r0   rD   rE   r?   r.   
minBackoff
maxBackoffrA   )r<   "used_default_value_for_min_backoffr3   rD   rE   old_min_backoffold_max_backoffs          r   _PostProcessMinMaxBackoffrL      s.   $ V#
CC!!#+CC!!#+)k$3$?$?o!
=/*E*EG  k$3$?$?o!
=/*E*EG 44 II##..0O II##..0O%+*H/=9$(o!/=9$(o!	 +I% 5_r   c                 L    UR                   R                  R                  nU R	                  S5      (       a  / nSU R
                  ;   a  UR                  U R
                  S   5        SU R
                  ;   a  UR                  U R
                  S   5        SR                  U5      nSR                  U[        R                  R                  R                  R                  5       5      nUR                  U5      (       a  U R                  S	 SU l        ggg! [         a     gf = f)a;  Checks if service and target values need to be updated for host URL.

An app engine host URL may have optionally version_dot_service appended to
the URL if specified via 'routing_override'. Here we check the existing URL
and make sure the service & target values are only updated when need be.

Args:
  cloud_task_args: argparse.Namespace, A placeholder args namespace built to
    pass on forwards to Cloud Tasks API.
  cur_queue_state: apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue,
    The Queue instance fetched from the backend if it exists, None otherwise.
Nrouting_overrideversionservice.z{}.{}.)appEngineHttpQueueappEngineRoutingOverridehostAttributeErrorIsSpecifiedrN   appendjoinformatr   VALUEScoreprojectGet
startswithr;   )r<   r3   host_urltargetstargets_sub_urltargets_sub_url_and_projects         r   _PostProcessRoutingOverriderc      s   11JJOOH   !344GO444nn_55i@AO444nn_55i@Ahhw'O"*//**//77;;=#?677

)
)*<
=)-o& 8 5 
 
s    D 
D#"D#c                    [         R                  " 5       nU H  n[        X4S5        M     Sn[        R                  R                  5        GH  u  pgUR                  S5      nU n	U H"  n
[        X5      (       d  Sn	  O[        X5      n	M$     U	(       d	  U	bJ  US;   aD  U[        ;   a  [        U   " U	5      n	U(       a  US;   d  [        XU	5      (       a  [        X7U	5        OzU R                  [        R                  :X  a  [        R                  nO[        R                  nX{;   a6  US:X  a  SnX   n	U(       a  US;   d  [        XU	5      (       a  [        X7U	5        [        X7U	5        GM     [!        X5U5        [#        X15        U$ )	a  Builds placeholder command line args to pass on to Cloud Tasks API.

Most of Cloud Tasks functions use args passed in during CLI invocation. To
reuse those functions without extensive rework on their implementation, we
recreate the args in the format that those functions expect.

Args:
  queue: third_party.appengine.api.queueinfo.QueueEntry, The QueueEntry
    instance generated from the parsed YAML file.
  cur_queue_state: apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue,
    The Queue instance fetched from the backend if it exists, None otherwise.
  ct_expected_args: A list of expected args that we need to initialize before
    forwarding to Cloud Tasks APIs.

Returns:
  argparse.Namespace, A placeholder args namespace built to pass on forwards
  to Cloud Tasks API.
NFrQ   )max_attempts)namerF   rD   rE   rD   T)rD   rE   )r	   	Namespacesetattrr   APP_TO_TASKS_ATTRIBUTES_MAPPINGitemssplitr,   r-   CONVERSION_FUNCTIONSr8   r?   mode
PULL_QUEUE%PULL_QUEUES_APP_DEPLOY_DEFAULT_VALUESr/   rL   rc   )queuer3   ct_expected_argsr<   	task_flagrI   old_argnew_argold_arg_listr>   old_arg_subdefault_valuess               r   _PopulateCloudTasksArgsrx      sh   ( &//1/#iO- $ (-$#CCIIKg==%LE#U((e)e	 $ "w2C'C	(	($W-e4
C
C
'%
H
H
 	59 
y++	+"HH"HH		"m#/3
,'55)/EJJ
?U
;Oe,O LP ?Lo?	r   c                 h    U R                    Vs/ s H  oS;  d  M
  UPM     nnU(       a  S$ S$ s  snf )a8  Check whether the queue has any changed attributes based on args provided.

Args:
  args: argparse.Namespace, A placeholder args namespace built to pass on
    forwards to Cloud Tasks API.

Returns:
  True if any of the queue attributes have changed from the attributes stored
  in the backend, False otherwise.
)rf   rF   TFr:   )argsr   modifiable_argss      r   _AnyUpdatableFieldsr|   8  sB     %%D%A2B)Ba%  D +e+Ds   	//c                    Sn[         R                  R                  S[        R                  R
                  R                  USS5      n[        R                  " U 5      n [        R                  " [        R                  " X S95        g)aj  Raises an HTTP exception with status code 400.

This function is used to raise the same exceptions generated by the older
implementation of `gcloud app delpoy queue.yaml` when it communicated with
the Zeus backend over HTTP.

Args:
  msg_body: A string providing more information about the error being raised.

Raises:
  HTTPError: Based on the inputs provided.
z&Bad Request Unexpected HTTP status 400N)body)r   error	HTTPErrorsixmoveshttp_clientBAD_REQUESTensure_binaryr   reraiser   RPCError)msg_bodyexc_msgr   s      r   _RaiseHTTPExceptionr   I  s_     5'
,,
 
 syy'<'<'H'H!($6%x((T]]589r   c                     U R                   R                  (       a'  U R                   R                  S:  a  [        S5        ggg)a  Validates task retry limit input values for both queues in the YAML file.

Args:
  queue: third_party.appengine.api.queueinfo.QueueEntry, The QueueEntry
    instance generated from the parsed YAML file.

Raises:
  HTTPError: Based on the inputs provided if value specified is negative.
r   zIInvalid queue configuration. Task retry limit must not be less than zero.N)retry_parameterstask_retry_limitr   )rp   s    r   _ValidateTaskRetryLimitr   ]  s>     ----1	 2 .r   c                    U R                   nUR                  (       d  gUR                   GHI  nUR                  (       d  M  UR                  R                  (       aH  UR                  R                  S:  a.  [	        SR                  UR                  R                  5      5        UR                  R                  (       aB  [        [        R                  " UR                  R                  5      5      S::  a  [	        S5        UR                  R                  c  M  UR                  R                  c  GM
  UR                  R                  nUR                  R                  nXC:  d  GM>  [	        S5        GML     g)aJ  Validates jobs configuration parameters in the cron YAML file.

The purpose of this function is to mimick the behaviour of the old
implementation of `gcloud app deploy cron.yaml` before migrating away
from console-admin-hr. The errors generated are the same as the ones
previously seen when gcloud sent the batch-request for updating jobs to the
Zeus backend.

Args:
   config: A yaml_parsing.ConfigYamlInfo object for the parsed YAML file we
    are going to process.

Raises:
  HTTPError: Various different scenarios defined in the function can cause
    this exception to be raised.
N   z[Invalid Cron retry parameters: Cannot set retry limit to more than 5 (currently set to {}).r   zOInvalid Cron retry parameters: Job age limit must be greater than zero seconds.z]Invalid Cron retry parameters: Min backoff sec must not be greater than than max backoff sec.)parsedcronr   job_retry_limitr   rY   job_age_limitr   r*   r0   min_backoff_secondsmax_backoff_seconds)config	cron_yamljobrD   rE   s        r   ValidateCronYamlFileConfigr   p  s&   " mm)	
^^c  


.
.



.
.
2,,2F$$44-6	7 


,
,
jAA""002 3678 	!	" 


2
2
>



2
2
>**>>**>>$
34C r   c                 h   U R                   nUR                  (       d  gUR                   GH  nUR                  (       a  UR                  [        R                  :X  Ga  UR
                  (       d  [        S5        O][        R                  " UR
                  5      nU[        R                  :  a)  [        SR                  [        R                  U5      5        UR                  (       Ga  [        U5        UR                  R                  (       aB  [        [        R                  " UR                  R                  5      5      S::  a  [        S5        UR                  R                   (       a%  UR                  R                   S:  a  [        S5        UR                  R"                  (       a%  UR                  R"                  S:  a  [        S5        UR                  R$                  (       a%  UR                  R$                  S:  a  [        S5        UR                  R                   bS  UR                  R"                  b<  UR                  R                   nUR                  R"                  nXT:  a  [        S	5        UR&                  (       a  UR&                  S:  a'  [        S
R                  UR(                  5      5        GM  UR&                  [        R*                  :  a6  [        SR                  UR(                  [        R*                  5      5        GM  GM  GM  UR
                  (       a  [        S5        UR                  (       a  [        U5        UR                  R                  b  [        S5        UR                  R                   b  [        S5        UR                  R"                  b  [        S5        UR                  R$                  b  [        S5        UR,                  b  [        S5        UR&                  b  [        S5        UR.                  (       d  GM  [        S5        GM     g)aO  Validates queue configuration parameters in the queue YAML file.

The purpose of this function is to mimick the behaviour of the old
implementation of `gcloud app deploy queue.yaml` before migrating away
from console-admin-hr. The errors generated are the same as the ones
previously seen when gcloud sent the batch-request for updating queues to the
Zeus backend.

Args:
   config: A yaml_parsing.ConfigYamlInfo object for the parsed YAML file we
    are going to process.

Raises:
  HTTPError: Various different scenarios defined in the function can cause
    this exception to be raised.
NzPInvalid queue configuration. Refill rate must be specified for push-based queue.zSInvalid queue configuration. Refill rate must not exceed {} per second (is {:.1f}).r   zFInvalid queue configuration. Task age limit must be greater than zero.zLInvalid queue configuration. Min backoff seconds must not be less than zero.zLInvalid queue configuration. Max backoff seconds must not be less than zero.zFInvalid queue configuration. Max doublings must not be less than zero.z[Invalid queue configuration. Min backoff sec must not be greater than than max backoff sec.z5Error updating queue "{}": The queue rate is invalid.z5Error updating queue "{}": Maximum bucket size is {}.zTInvalid queue configuration. Refill rate must not be specified for pull-based queue.zKInvalid queue configuration. Can't specify task_age_limit for a pull queue.zPInvalid queue configuration. Can't specify min_backoff_seconds for a pull queue.zPInvalid queue configuration. Can't specify max_backoff_seconds for a pull queue.zJInvalid queue configuration. Can't specify max_doublings for a pull queue.z`Invalid queue configuration. Max concurrent requests must not be specified for pull-based queue.zTInvalid queue configuration. Bucket size must not be specified for pull-based queue.zOInvalid queue configuration. Target must not be specified for pull-based queue.)r   rp   rm   r   
PUSH_QUEUEr   r   r*   ConvertRateMAX_RATErY   r   r   task_age_limitr   r0   r   r   max_doublingsbucket_sizerf   MAX_BUCKET_SIZEr   r   )r   
queue_yamlrp   rate_in_secondsrD   rE   s         r   ValidateQueueYamlFileConfigr     sg   " }}*			
e::y';';; ZZ 	! %00<Y///
++16$$o,78 
			& ""11
CC&&557 8;<=  ""66""66:
 ! ""66""66:
 ! ""00""0014
 ""66B""66B..BB+..BB+&56
 
		q 
ELL** !:!::
ELL**i779: ; 
 
$	%
 
		& !!00<
"#
 !!55A
"#
 !!55A
"#
 !!//;
"#
 
	&	&	21	2
 
			&$	%
 
 	!K  r   c                 8   U R                   n[        R                  " [        R                  " 5       5      n[        R
                  " U5      nUR                  U5       Vs0 s H-  n[        R                  R                  UR                  5      U_M/     nnU$ s  snf )aO  Fetches the current queues data stored in the database.

Args:
  tasks_api: api_lib.tasks.<Alpha|Beta|GA>ApiAdapter, Cloud Tasks API needed
    for doing queue based operations.

Returns:
  A dictionary with queue names as keys and corresponding protobuf Queue
  objects as values apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue
)queuesr
   ResolveAppLocationr   ParseProjectParseLocationListospathbasenamerf   )	tasks_apiqueues_clientapp_location
region_refr   all_queues_in_db_dicts         r   FetchCurrentQueuesDatar   H  s     ""-''(<(<(>?,$$\2*+8+=+=j+I+Iabggqvv!+I   
s   4Bc                    U R                   n[        R                  " [        R                  " 5       U R
                  S9n[        R                  " U5      R                  5       n[        S UR                  U5       5       5      $ )zFetches the current jobs data stored in the database.

Args:
  scheduler_api: api_lib.scheduler.<Alpha|Beta|GA>ApiAdapter, Cloud Scheduler
    API needed for doing jobs based operations.

Returns:
  A list of currently existing jobs in the backend.
locations_clientc              3   $   #    U  H  ov   M     g 7f)N ).0r   s     r   	<genexpr>'FetchCurrentJobsData.<locals>.<genexpr>j  s     65Aa5s   )
jobsr
   r   r   r   	locationsr   RelativeNamelistr   )scheduler_apijobs_clientr   r   s       r   FetchCurrentJobsDatar   \  si     ""+''}/F/FH,$$\2??A*	6))*56	66r   c                     " S S5      nUR                   nUR                  S:g  nU R                  n[        UR	                  5       5      n[
        R                  " S5      n	U	R                  5       SS n
[        R                  " US9nUR                  [        R                  " S[        S	S
95        / nU HG  nUR                  S   SS R                  SS5      nUR!                  USR#                  U5      45        MI     / nUR$                  c  / Ul        UR$                   GH  nUR&                  U;   a  UR)                  UR&                  5        U" SR#                  U
UR&                  5      5      n	UR+                  UR&                  S5      n[-        UUU5      nUR/                  S5      nU(       ax  U(       aq  U(       d  UR0                  [2        R4                  :X  aL  UR6                  UR6                  R8                  UR6                  R:                  4;   a  UR=                  U	5        OcU(       a\  U(       dU  UR6                  UR6                  R>                  :X  a1  UR0                  S[2        R@                  4;   a  URC                  U	5        [E        U5      (       d  GM  [
        RF                  " U[2        R@                  U RH                  USS9n[
        RJ                  " U[2        R@                  US9nU(       d  UR!                  SS/5        URL                  b  URL                  RN                  OSnURQ                  U	UURR                  URT                  UU(       d  [2        RV                  OSU(       d  [2        RX                  OSURZ                  S9nUR                  U5        U(       a  GM  U(       a  GM  UR0                  [2        R@                  :X  d  GM  URC                  U	5        GM     U Hu  nUS:X  a  M  UU   nUR6                  UR6                  R:                  UR6                  R8                  4;   a  ML  U" SR#                  U
U5      5      n	URC                  U	5        Mw     U$ )a  Perform a deployment based on the parsed 'queue.yaml' file.

Args:
  tasks_api: api_lib.tasks.<Alpha|Beta|GA>ApiAdapter, Cloud Tasks API needed
    for doing queue based operations.
  config: A yaml_parsing.ConfigYamlInfo object for the parsed YAML file we
    are going to process.
  all_queues_in_db_dict: A dictionary with queue names as keys and
    corresponding apis.cloudtasks.<ver>.cloudtasks_<ver>_messages.Queue
    objects as values
  ct_api_version: The Cloud Tasks API version we want to use.

Returns:
  A list of responses received from the Cloud Tasks APIs representing queue
  states for every call made to modify the attributes of a queue.
c                   $    \ rS rSrSrS rS rSrg)2DeployQueuesYamlFile.<locals>._PlaceholderQueueRefi  a  A placeholder class to simulate queue_ref resource objects used in CT APIs.

This class simulates the behaviour of the resource object returned by
tasks.parsers.ParseQueue(...) function. We use this placeholder class
instead of creating an actual resource instance because otherwise it takes
roughly 2 minutes to create resource instances for a 1000 queues.

Attributes:
  _relative_path: A string representing the full path for a queue in the
    format: 'projects/<project>/locations/<location>/queues/<queue>'
c                     Xl         g)z4Initializes the instance and sets the relative path.N_relative_path)selfrelative_paths     r   __init__;DeployQueuesYamlFile.<locals>._PlaceholderQueueRef.__init__  s    )r   c                     U R                   $ )a(  Gets the string representing the full path for a queue.

This is the only function we are currently using in CT APIs for the
queue_ref resource object.

Returns:
  A string representing the full path for a queue in the following
  format: 'projects/<project>/locations/<location>/queues/<queue>'
r   )r   s    r   r   ?DeployQueuesYamlFile.<locals>._PlaceholderQueueRef.RelativeName  s        r   r   N)__name__
__module____qualname____firstlineno____doc__r   r   __static_attributes__r   r   r   _PlaceholderQueueRefr     s    
*
!r   r   Falser!   N)release_trackz--max_burst_size )rF   helpr      -_zclear_{}z{}{}r)   F)r   
http_queuetaskTtltombstoneTtl)retry_configrate_limitsapp_engine_routing_overridetask_ttltask_tombstone_ttl
queue_typedefault).r   resume_paused_queuesr   setkeysr   
ParseQueuer   r   _PushQueueFlagsrW   r   Argumentr   rz   replaceextendrY   rp   rf   removegetrx   GetValuerm   r   rn   stateDISABLEDPAUSEDResumeRUNNINGr   Pauser|   ParseCreateOrUpdateQueueArgsmessagesGetSpecifiedFieldsMaskrR   rS   Patchr.   r'   MAX_TASK_TTLMAX_TASK_TOMBSTONE_TTLrF   )r   r   r   ct_api_versionr   r   r   r   queues_not_present_in_yaml	queue_refqueue_ref_stub	task_argsexpected_argsrr   rt   	responsesrp   cur_queue_objectr<   rate_to_setqueue_configupdated_fieldsr   response
queue_names                            r   DeployQueuesYamlFiler  m  s   .! !: }}*#88GC""-"#8#=#=#?@   %)))+CR0. ##.A) 4==!3#BGH-innQ#++C5G':#4#4W#=>?  )Jezz// ''

3$V]]>5::%NOI,00TB-e5E.;=O!**+FGK 		

i&:&::#3#9#9#B#B#3#9#9#@#@#B 	B
 9%"2"8"8"@"@@

tY1122)$//77 	$L 33--^MN
 Y78 **6 	''@@<@   ""!-- ++$?/?''T4DI,,$$$ # 
H X K

i*** )$M  P /j Y!*-E{{u{{))5;;+?+?@@$V]]>:%NOI	" / 
r   c                    U R                   U R                  U R                  R                  U R                  U R
                  (       a*  [        R                  " U R
                  R                  5      OSU R
                  (       a*  [        R                  " U R
                  R                  5      OSU R
                  (       a  U R
                  R                  OSU R
                  (       a*  [        R                  " U R
                  R                  5      OSU R
                  (       a  U R
                  R                  OS[        R                  " X5      4
$ )zCreates a key from the proto job instance's attributes passed as input.

Args:
  job: An instance of job fetched from the backend.
  project: The base name of the project.
Returns:
  A tuple of attributes used as a key to identify this job.
N)scheduletimeZoneappEngineHttpTargetrelativeUridescriptionr.   r*   r0   minBackoffDurationmaxBackoffDurationmaxDoublingsmaxRetryDuration
retryCountr   !ExtractTargetFromAppEngineHostUrl)r   r\   s     r   !_CreateUniqueJobKeyForExistingJobr    s     
ll	ll	))	oo14 99
//
,
,.FJ14 99
//
,
,.FJ&)oocoo""4/2 99
//
*
*,DH$'OOcoo  //=
 r   c                 X   [         R                  nU R                  nU(       Ga  UR                  c"  UR                  c  US   Ul        US   Ul        OUR                  b  UR                  c  UR                  (       d
  US   Ul        UR                  (       a%  [        UR                  UR                  5      Ul        UR                  c
  US   Ul        [        UR                  UR                  5      Ul        UR                  c
  US   Ul        UR                  c  US   Ul        ggg)a  Replaces default values for retry parameters.

Retry parameters are set to their default values if not already user defined.
These values are only set if the user has defined at least one retry
parameter. Also we are limiting min_backoff to a minimum value of 5.0s since
the new scheduler API does not support setting a lower value than this.
Modifies input `job` argument directly.

Args:
  job: An instance of a parsed YAML job object.
NrD   rE   r   max_retry_duration)	r   CRON_JOB_LEGACY_DEFAULT_VALUESr   r   r   r   r   r   r   )r   defaults
retry_datas      r   $_ReplaceDefaultRetryParamsForYamlJobr   (  s%    55(##* 	&&.&&. (0'>j$'/'>j$&&.&&. ++)1-)@
&		'	'),Z-K-K-7-K-K*M
&		'	'	/)1-)@
&'*:+I+I+5+I+I(Kj$ '!)/!:j '!)*>!?j (C r   c           
         U R                   nU R                  U R                  (       a  U R                  OSU R                  U R                  U(       a  UR
                  OSU(       a  UR                  OSU(       a  UR                  OSU(       a   [        R                  " UR                  5      OSU(       a  UR                  U R                  4
$ SU R                  4
$ )zCreates a key from the YAML job instance's attributes passed as input.

Args:
  job: An instance of a parsed YAML job object.
Returns:
  A tuple of attributes used as a key to identify this job.
UTCN)r   r  timezoneurlr  r   r   r   r*   r0   r   r   r   )r   retry_paramss     r   _CreateUniqueJobKeyForYamlJobr&  [  s     %%,	llllcll	gg	oo*6l&&D*6l&&D$0l  d)5 99

$
$&;?&2l""	jj
  9=	jj
 r   c                 j    0 nU  H*  n[        X15      nXB;  a  / X$'   X$   R                  U5        M,     U$ )av  Builds a dictionary of unique jobs by attributes.

Each key is in this dictionary is based on all the existing attributes of a
job. Multiple jobs can map to the same key if all their attributes (schedule,
url, timezone, description, etc.) match.

Args:
  existing_jobs: A list of jobs that already exist in the backend. Each job
    maps to an apis.cloudscheduler.<ver>.cloudscheduler<ver>_messages.Job
    instance.
  project: The base name of the project.
Returns:
  A dictionary where a key is built based on a all the job attributes and the
  value is an apis.cloudscheduler.<ver>.cloudscheduler<ver>_messages.Job
  instance.
)r  rW   )existing_jobsr\   jobs_indexed_dictr   r=   s        r   _BuildJobsMappingDictr*  s  sF    " c
+C
9C
#!!!#&	 
 
r   c           
         U R                   nUR                  (       a  UR                  [        R                  " UR                  R
                  5      UR                  R                  [        R                  " UR                  R                  5      [        R                  " UR                  R                  5      UR                  R                  S9nOSnUR                  UR                  UR                  R                  R                  UR                  UR!                  UR"                  S9S9UUR$                  U R&                  R(                  UR*                  UR,                  (       a  UR,                  S9$ SS9$ )a^  Build a proto format job instance  matching the input YAML based job.

Args:
  scheduler_api: api_lib.scheduler.<Alpha|Beta|GA>ApiAdapter, Cloud Scheduler
    API needed for doing jobs based operations.
  yaml_job: A parsed yaml_job entry read from the 'cron.yaml' file.
Returns:
  An cloudscheduler.<ver>.cloudscheduler_<ver>_messages.Job instance.
)r  r  r  r  r  N)rP   )
httpMethodr  appEngineRoutingr"  )r  r.   r  legacyAppEngineCronr  r  )r   r   RetryConfigr*   ConvertBackoffSecondsr   r   ConvertTaskAgeLimitr   r   r   JobAppEngineHttpTargetHttpMethodValueValuesEnumGETr$  AppEngineRoutingr   r  r   legacy_cronr  r#  )r   yaml_jobr   r   s       r   CreateJobInstancer9    sT    ##(''%;;%%99;..<<#77%%335%;;%%99;,,<< ( 	L L	"6611KKOOll#44X__4M 7 O &&',,88  $,$5$5x   
 	
B 	B <A 
 	
B 	Br   c                    UR                   nU R                  n[        R                  " [        R
                  " 5       U R                  S9n[        R                  " U5      R                  5       n[        R                  R                  [        [        R
                  " 5       5      5      n[        X'5      n/ n	UR                  (       av  UR                   Hf  n
[        U
5        [!        U
5      nX;   a  X   (       a  X   R#                  5         M;  [%        X
5      nU	R'                  UR)                  Xl5      5        Mh     UR+                  5        H'  nU H  n
UR-                  U
R.                  5        M      M)     U	$ )a  Perform a deployment based on the parsed 'cron.yaml' file.

For every job defined in the cron.yaml file, we will create a new cron job
for any job that did not already exist in our backend. We will also delete
those jobs which are not present in the YAML file but exist in our backend.
Note: We do not update any jobs. The only operations are Create and Delete.
So if we modify any attribute of an existing job in the YAML file, the old
job gets deleted and a new job is created based on the new attributes.

Args:
  scheduler_api: api_lib.scheduler.<Alpha|Beta|GA>ApiAdapter, Cloud Scheduler
    API needed for doing jobs based operations.
  config: A yaml_parsing.ConfigYamlInfo object for the parsed YAML file we
    are going to process.
 existing_jobs: A list of jobs that already exist in the backend. Each job
    maps to an apis.cloudscheduler.<ver>.cloudscheduler<ver>_messages.Job
    instance.
Returns:
  A list of responses received from the Cloud Scheduler APIs representing job
  states for every call made to create a job.
r   )r   r   r
   r   r   r   r   r   r   r   r   r   strr*  r   r   r&  popr9  rW   CreatevaluesDeleterf   )r   r   r(  r   r   r   r   r\   existing_jobs_dictr  r8  job_keyr   	jobs_lists                 r   DeployCronYamlFilerC    s-   , mm)""+''}/F/FH,$$\2??A*GGS!5!5!789',]D )^^NN*84-h7g		&+=+F 	#'')m6c{))*:; # &,,.i'  / 
r   )g&.>g        )5r   
__future__r   r   r   r   googlecloudsdk.api_lib.appr   googlecloudsdk.api_lib.tasksr   r*   googlecloudsdk.callioper   r	    googlecloudsdk.command_lib.tasksr
   r   r   r   googlecloudsdk.corer   r   r   	six.movesr   r   r0  r1  ConvertTargetrl   r%   r8   r?   rA   rL   rc   rx   r|   r   r   r   r   r   r   ReleaseTrackBETAr  r  r   r&  r*  r9  rC  r   r   r   <module>rN     s    '  ' 	 + M ( 5 0 6 2 4 * * 
   C"",6,L,L,6,L,L'1'E'E)=&& A*3 l/ 	+.)b.BDN,":(&74t[!|(7* $$))	^B40@f04!BH5r   