
    t                        S r SSKJr  SSKJr  SSKJr  SSK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rSSKJr  SSSS.rSrS rS rS rS rS r " S S\
R:                  5      rS rS r S r!SSSS.r"  S+S  jr#\4S! jr$S" r%S# r&S$ r'S% r(S& r)  S,S' jr* " S( S)\RV                  5      r,\,RZ                  4S* jr.g)-zDConvenience functions and classes for dealing with instances groups.    )absolute_import)division)unicode_literalsN)encoding)
exceptions)lister)path_simplifier)utils)log)
properties)rangez4Lists the named ports for an instance group resourcea  
Named ports are key:value pairs metadata representing
the service name and the port that it's running on. Named ports
can be assigned to an instance group, which indicates that the service
is available on all instances in the group. This information is used
by Application Load Balancers and proxy Network Load Balancers.

*{command}* lists the named ports (name and port tuples)
for an instance group.
z
For example, to list named ports for an instance group:

  $ {command} example-instance-group --zone=us-central1-a

The above example lists named ports assigned to an instance
group named 'example-instance-group' in the ``us-central1-a'' zone.
)briefDESCRIPTIONEXAMPLESi  c                 (    U R                  5       S:H  $ )z#Checks if group reference is zonal.compute.instanceGroups)
Collection)	group_refs    ;lib/googlecloudsdk/api_lib/compute/instance_groups_utils.pyIsZonalGroupr   =   s    				#;	;;    c                     U  Vs/ s H$  o"R                   U:w  d  M  UR                  5       PM&     nn[        U5      (       a)  [        R                  " SSSR                  U5      -  5      egs  snf )a6  Validate if provided list in zone given as parameter.

Args:
  instances: list of instances resources to be validated
  zone: a zone all instances must be in order to pass validation

Raises:
  InvalidArgumentException: If any instance is in different zone
                            than given as parameter.
	instanceszaThe zone of instance must match the instance group zone. Following instances has invalid zone: %sz, N)zoneSelfLinkanycalliope_exceptionsInvalidArgumentExceptionjoin)r   r   instinvalid_instancess       r   ValidateInstanceInZoner"   B   s{     $-C#,4		T0A 't}}#,  C	

6
6 3
))%
&'( ( Cs
   A,A,c              #   J   #    U  H  n[        X!5       H  nUv   M	     M     g7f)zDExtracts items stored in given attribute of instance group response.N)getattr)	responses	attr_nameresponseitems       r   UnwrapResponser)   V   s#     h,j - s   !#c                     U R                   $ )a>  UriFunc for listing instance-group related subresources.

Function returns field with URI for objects being subresources of
instance-groups, with instance fields. Works for list-instances and
instance-configs list commands.

Args:
  resource: instance-group subresource with instance field

Returns:
  URI of instance
)instance)resources    r   $UriFuncForListInstanceRelatedObjectsr-   ]   s     
		r   c                    UR                   nU R                  5       S:X  aF  UR                  nUR                  S5      " U R	                  5       U R
                  U R                  S9nOEUR                  nUR                  S5      " U R	                  5       U R                  U R                  S9nUR                  USU4/S9n[        [        US5      5      $ )z)Gets the request to fetch instance group.r   Get)instanceGroupr   project)r0   regionr1   requests
namedPorts)apitools_clientr   instanceGroupsGetRequestTypeNamer   r1   regionInstanceGroupsr2   MakeRequestslistr)   )r   compute_clientcomputeservicerequestresultss         r   OutputNamedPortsForGrouprB   m   s    **'77$$G$$U+nn&^^!!#G
 **G$$U+nn&!!#G ''7E72K1L'M'	nWl3	44r   c                       \ rS rSrSrSrg)FingerprintFetchException   zBException thrown when there is a problem with getting fingerprint. N)__name__
__module____qualname____firstlineno____doc____static_attributes__rF   r   r   rD   rD      s    Jr   rD   c                    U R                   n[        U5      (       aF  UR                  nUR                  R	                  UR
                  UR                  UR                  S9nOEUR                  nUR                  R                  UR
                  UR                  UR                  S9n/ nU R                  USU4/US9nU(       a  [        R                  " U[        SS9  US   R                  $ )z)Gets fingerprint of given instance group.)r1   r   r0   )r1   r2   r0   r/   )r4   errors_to_collectz'Could not set named ports for resource:)error_messager   )r6   r   r7   MESSAGES_MODULEComputeInstanceGroupsGetRequestr1   r   r0   r:   %ComputeRegionInstanceGroupsGetRequestr2   r;   r
   RaiseExceptionrD   fingerprint)r=   r   r>   r?   r@   errors	resourcess          r   _GetGroupFingerprintrW      s    **')$$G%%EE!!^^-- F /G
 **G%%KK!!-- L /G
 &))%)* *  ) 	!?A 
1	!	!!r   c                    U R                   nU R                  n[        X5      n[        U5      (       aP  UR	                  UUS9nUR                  UR                  5       UUR                  UR                  S9UR                  4$ UR                  UUS9nUR                  UR                  5       UUR                  UR                  S9UR                  4$ )a  Returns a request to get named ports and service to send request.

Args:
  compute_client: GCE API client,
  group_ref: reference to instance group (zonal or regional),
  ports: list of named ports to set

Returns:
  request, message to send in order to set named ports on instance group,
  service, service where request should be sent
    - regionInstanceGroups for regional groups
    - instanceGroups for zonal groups
)rT   r5   )r0   "instanceGroupsSetNamedPortsRequestr   r1   )r0   (regionInstanceGroupsSetNamedPortsRequestr2   r1   )r6   messagesrW   r   "InstanceGroupsSetNamedPortsRequest)ComputeInstanceGroupsSetNamedPortsRequestr9   r   r1   r7   (RegionInstanceGroupsSetNamedPortsRequest/ComputeRegionInstanceGroupsSetNamedPortsRequestr2   r:   )r=   r   portsr>   r[   rT   request_bodys          r   GetSetNamedPortsRequestForGrouprb      s     **'$$(
 %^?+)>> ? L ==nn&+7^^!!	 > # %,$:$:	; ; DD E L CCnn&1=!!	 D # %,$@$@	A Ar   c           	      B   / nU H  nUR                  S5      S:w  a  [        R                  " US5      eUR                  S5      u  pEUR	                  5       (       d  [        R                  " US5      eUR                  U R                  U[        U5      S95        M     U$ )zValidates named ports flags.:   z+Named ports should follow NAME:PORT format.)nameport)countr   r   splitisdigitappend	NamedPortint)r[   named_portsr`   
named_porthostrg   s         r   ValidateAndParseNamedPortsArgsrq      s    
%j!88
CE E!!#&JD<<>>88
CE E	LL##CI#>?   
,r   z2Sets the list of named ports for an instance groupa  
Named ports are key:value pairs metadata representing
the service name and the port that it's running on. Named ports
can be assigned to an instance group, which
indicates that the service is available on all instances in the
group. This information is used by Application Load Balancers
and proxy Network Load Balancers.

*{command}* sets the list of named ports for all instances
in an instance group.

Note: Running this command will clear all existing named ports.
a2  
For example, to apply the named ports to an entire instance group:

  $ {command} example-instance-group --named-ports=example-service:1111 --zone=us-central1-a

The above example will assign a name 'example-service' for port 1111
to the instance group called 'example-instance-group' in the
``us-central1-a'' zone. The command removes any named ports that are
already set for this instance group.

To clear named ports from instance group provide empty named ports
list as parameter:

  $ {command} example-instance-group --named-ports="" --zone=us-central1-a
c                 `   [         R                  " SSS/5      n/ nU Vs/ s H  n[        R                  " U5      PM     n	nUR	                  5       S:X  aW  U	 HO  n
U R                  U
UR                  UR                  S.SS9nUR                  U" U
UR                  5       S95        MQ     U$ UR	                  5       S	:X  GaA  UR                  R                  nUR                  S
5      " UR                  5       UR                  UR                  S9n0 nUR                  US
U4/S9 H  nUR                  (       dX  U(       d"  [!        SR#                  UR$                  S95      eUc  / nUR                  SR#                  UR$                  S95        Ml  UR                  U[        R                  " UR                  5      '   M     U	 H8  n
X;   a  UR                  U" U
X   S95        M"  UR                  U" U
SS95        M:     U$ [!        SR#                  UR	                  5       5      5      es  snf )a  Creates reference to instances in instance group (zonal or regional).

Args:
  resources: Resources parser for the client.
  compute_client: Client for the current release track.
  igm_ref: URL to the target IGM.
  instance_names_or_urls: names or full URLs of target instances.
  skip_instances_on_validation_error: If true, skip instances that are not yet
    allocated to any zone. This can happen when the instance is being created
    in a regional IGM by a resize-request and is still in a queue.
  warnings: A list to collect warnings for skipped instances if
    skip_instances_on_validation_error is true.

Returns:
  A dict where instance names are keys, and corresponding references are
  values. Unresolved names are present in dict with value None.
InstanceNameWithReferenceinstance_nameinstance_referencecompute.instanceGroupManagers)r1   r   zcompute.instancesparams
collection)rt   ru   #compute.regionInstanceGroupManagersListManagedInstances)instanceGroupManagerr2   r1   r3   zPCannot perform action on instance {name} as it is not yet allocated to any zone.)rf   NzTSkipped performing action on instance {name} as it is not yet allocated to any zone.Unknown reference type {0})collections
namedtupler	   r9   r   Parser1   r   rk   r   r6   regionInstanceGroupManagersr8   r2   r;   r+   
ValueErrorformatrf   )rV   r=   igm_refinstance_names_or_urls"skip_instances_on_validation_errorwarnings_InstanceNameWithReferenceinstance_referencesname_or_urlnames_to_resolvert   instance_refr?   r@   resolved_referencess                  r   CreateInstanceReferencesr      si   2  +55!O5I#J L 0/+ ;'/   <<)__
 ll ) % *l   
$)!-!6!6!8:; * DD,,HHG$$%;<$\\^~~!G &332G<= 4 ?""1,,2F#(( -3 -  H
//,,2F#(( -3 - $0$9$9 /..


! ")?, *		-""&+#6#EG	H
 	""&+F	G * 
1889K9K9MN
OOws    H+c                     / n[        X5      R                  =(       d    / n[        U5      n[        SXR5       H@  n[        R
                  " U 5      n[        Xq5      nXFXb-    Ul        UR                  U5        MB     U$ )a  Split request into parts according to max_length limit.

Example:
  requests = SplitInstancesInRequest(
        self.messages.
        ComputeInstanceGroupManagersAbandonInstancesRequest(
            instanceGroupManager=igm_ref.Name(),
            instanceGroupManagersAbandonInstancesRequest=(
                self.messages.InstanceGroupManagersAbandonInstancesRequest(
                    instances=instances,
                )
            ),
            project=igm_ref.project,
            zone=igm_ref.zone,
        ), 'instanceGroupManagersAbandonInstancesRequest')

Then:
  return client.MakeRequests(LiftRequestsList(service, method, requests))

Args:
  request: _messages.Message, request to split
  request_field: str, name of property inside request holding instances field
  max_length: int, max_length of instances property

Returns:
  List of requests with instances field length limited by max_length.
r   )r$   r   lenr   r   CopyProtoMessagerk   )	r@   request_field
max_lengthresultall_instancesnirequest_partfields	            r   SplitInstancesInRequestr   U  st    < &'1;;Ar-	-!A"a,,W5LL0E#al3EO
MM,	 #
 
-r   c              #   *   #    U H	  nXU4v   M     g7f)z(a, b, [c]) -> [(a, b, c)].NrF   )r?   methodr4   r@   s       r   GenerateRequestTuplesr   ~  s     gG
$$ s   c                 R   / nU H@  u  pVn/ nU R                  XVU4/U5        UR                  Xx45        UR                  U5        MB     / n	U HV  u  pxU(       a  Sn
OSn
[        Xr5      R                   H,  nU	R                  U[
        R                  " U5      U
S.5        M.     MX     U	$ )a  Make *-instances requests with feedback per instance.

Args:
  client: Compute client.
  requests: [(service, method, request)].
  instances_holder_field: name of field inside request holding list of
    instances.
  errors_to_collect: A list for capturing errors. If any response contains an
    error, it is added to this list.

Returns:
  A list of request statuses per instance. Requests status is a dictionary
  object, see SendInstancesRequestsAndPostProcessOutputs for details.
FAILSUCCESSselfLinkinstanceNamestatus)r;   rk   extendr$   r   r	   r9   )clientr4   instances_holder_fieldrN   request_resultsr?   r   r@   rU   status_per_instanceinstance_statusr+   s               r   #MakeRequestsAndGetStatusPerInstancer     s    & /"*gwF
'734f=G,-V$	 #+ (ogo!oG<FF  )..x8#" 	 G ) 
r   c                    [        5       nU R                  =(       d    /  H  nUR                  UR                  R                  :w  a  UR                  UR                  5        MD  SnSnUR                  =(       d    /  HC  nUR                  S:X  a  UR                  nUR                  S:X  d  UR                  S:X  d  MA  SnME     U(       a  U(       a  UR                  X$'   M  UR                  UR                  5        M     U$ )a  Extract from operation instances skipped due to graceful validation.

Args:
  operation: Operation containing warnings.
  warnings_to_collect: A list to collect warnings unrelated to graceful
    validation.

Returns:
  Dict from resource path of a skipped instance to validation error.
NFr+   validation_errorvalidation_outcomeT)
dictr   codeCodeValueValuesEnumNOT_CRITICAL_ERRORrk   messagedatakeyvalue)	operationwarnings_to_collectskipped_instanceswarningskipped_instance_pathis_graceful_validation_warningwarning_metadatas          r   .ExtractSkippedInstancesAndCollectOtherWarningsr     s     f##)r)g ||w22EEE  1 %*" $LL.B.				+ 0 6 6#55#77)-& / &*?18.   1) ** 
r   c           	         / nU HP  u  pgn/ n	U R                  XgU4/U	SSSS9n
U
=(       d    S/u  nUR                  XU	45        UR                  U	5        MR     / nU GH  u  pn	U	(       aG  [        X5      R                   H,  nUR                  U[
        R                  " U5      SS.5        M.     MU  UR                  (       a8  [        R                  R                  SR                  UR                  5      5        [        X5      n[        X5      R                   HS  nXR                  S5      S	-   S nSnX;   a  S
nX   nOSnUR                  U[
        R                  " U5      UUS.5        MU     GM     U$ )a  Make *-instances requests with feedback per instance.

Specialized version of MakeRequestsAndGetStatusPerInstance. Checks operations
for warnings presence to evaluate statuses per instance. Gracefully validated
requests may produce warnings on operations, indicating instances skipped.
It would be merged with MakeRequestsAndGetStatusPerInstance after we see
there's no issues with this implementation.

Args:
  client: Compute client.
  requests: [(service, method, request)].
  instances_holder_field: name of field inside request holding list of
    instances.
  warnings_to_collect: A list for capturing warnings. If any completed
    operation will contain skipped instances, function will append warning
    suggesting how to find additional details on the operation, warnings
    unrelated to graceful validation will be collected as is.
  errors_to_collect: A list for capturing errors. If any response contains an
    error, it is added to this list.

Returns:
  See MakeRequestsAndGetStatusPerInstance.
FT)log_warningsno_followupalways_return_operationNr   r   zUpdated [{0}].
z
/projects/re   SKIPPEDr   )r   r   r   validationError)r;   rk   r   r$   r   r	   r9   
targetLinkr   r   writer   r   find)r   r4   r   r   rN   r   r?   r   r@   rU   
operationsr   r   r+   r   instance_pathr   r   s                     r   0MakeRequestsAndGetStatusPerInstanceFromOperationr     s   : /"*gwF$$w&@%A%+2715=A	 % CJ &KYG78V$ #+ $3 g&g>HH("" +00:$
 	 I 
		

+2293G3GHIH
* g>HH( !|!<q!@!AB-%/.=
%/"" +00:%/	$
 	 I# %4B 
r   c                    U R                   nUR                  5       S:X  a  UR                  R                  nOSUR                  5       S:X  a  UR                  R                  nO([        SR                  UR                  5       5      5      eS[        X#5      l        / nUR                  XaU4/U5        U(       a  [        R                  " U5      e/ $ )a  Prepare *-instances request with --all-instances flag and format output.

Args:
  api_holder: Compute API holder.
  method_name: Name of the (region) instance groups managers service method to
    call.
  request_template: Partially filled *-instances request (no instances).
  all_instances_holder_field: Name of the field inside request holding
    allInstances field.
  igm_ref: URL to the target IGM.

Returns:
  Empty list (for consistency with a command version using list of instances).
rv   rz   r}   T)r   r   r6   instanceGroupManagersr   r   r   r$   allInstancesr;   r
   RaiseToolException)
api_holdermethod_namerequest_templateall_instances_holder_fieldr   r   r?   rU   s           r   SendAllInstancesRequestr   '  s      &<<$$::GDD$$@@G
1889K9K9MN
OOGK'
7D&.>?@&I

"
"6
** 
)r   c           
   #     #    U R                   nUR                  5       S:X  a  UR                  R                  n	OSUR                  5       S:X  a  UR                  R                  n	O([        SR                  UR                  5       5      5      e/ n
/ n[        U R                  UUUUU5      nU Vs/ s H"  nUR                  (       d  M  UR                  PM$     nnU[        UU5      l        [        X#5      n[        XU5      n/ nU(       a  UR                  [        UUX;U
5      5        OUR                  [!        UUUU
5      5        U Vs/ s H"  nUR                  (       a  M  UR"                  PM$     nnUR                  U Vs/ s H  n[%        USS9PM     sn5        U H  nUv   M	     U(       a+  [&        R(                  " [*        R,                  " SU5      5        U
(       a  [*        R.                  " U
5      egs  snf s  snf s  snf 7f)a8  Make *-instances requests and format output.

Method resolves instance references, splits them to make batch of requests,
adds to results statuses for unresolved instances, and yields all statuses
raising errors, if any, in the end.

Args:
  api_holder: Compute API holder.
  method_name: Name of the (region) instance groups managers service method to
    call.
  request_template: Partially filled *-instances request (no instances).
  instances_holder_field: Name of the field inside request holding instances
    field.
  igm_ref: URL to the target IGM.
  instances: A list of names of the instances to apply method to.
  per_instance_status_enabled: Enable functionality parsing resulting
    operation for graceful validation related warnings to allow per-instance
    status output. The plan is to gradually enable this for all per-instance
    commands in GA (even where graceful validation is not available / not
    used).
  skip_instances_on_validation_error: If true, skip instances that are not yet
    allocated to any zone. This can happen when the instance is being created
    in a regional IGM by a resize-request and is still in a queue.

Yields:
  A list of request statuses per instance. Requests status is a dictionary
  object with link to an instance keyed with 'selfLink', instance name keyed
  with 'instanceName', and status indicating if operation succeeded for
  instance keyed with 'status'. Status might be 'FAIL', 'SUCCESS', 'SKIPPED'
  in case of graceful validation, or 'MEMBER_NOT_FOUND' (in case of regional
  MIGs, when instance name cannot be resolved).
rv   rz   r}   MEMBER_NOT_FOUND)r   r   z!Some requests generated warnings:N)r   r   r6   r   r   r   r   r   rV   ru   r$   r   r   r   r   r   r   rt   r   r   r   r
   ConstructListr   )r   r   r   r   r   r   per_instance_status_enabledr   r   r?   rN   r   instances_with_referencesr+   r   r4   request_tuplesrequest_status_per_instanceunresolved_instance_namesrf   r   s                        r   *SendInstancesRequestsAndPostProcessOutputsr   L  s     R &<<$$::GDD$$@@G
1889K9K9MN
OO6( 0/(		$	$ "h!!/   /B 


 ""+$%5N((xH. " &&8N$:	 
  &&+FN,B,=	?@ 0/((( h/  
 $$+&+$ %78+& 
 ,f
L , KK?/	12 

"
"#4
55 O,
&s8   B-H/G<G<A2H
H#H3HHA3Hc                   $    \ rS rSrSrSrSrSrSrg)InstanceGroupFilteringModei  z?Filtering mode for Instance Groups based on dynamic properties.re         rF   N)	rG   rH   rI   rJ   rK   
ALL_GROUPSONLY_MANAGED_GROUPSONLY_UNMANAGED_GROUPSrL   rF   r   r   r   r     s    G*r   r   c                 V   U R                   nU R                  n/ n[        U5      n[        U Vs/ s H  nSU;   d  M  US   PM     sn5      n0 nU H  n	UR	                  U	S[
        R                  R                  R                  R                  0SS9n
U
R                  U;  a  [        5       XR                  '   XR                     R                  U
R                  5        M     / n[        R                  " U5       H`  u  pUR                  [        R                   " UR"                  R$                  UUSUR"                  R&                  UR(                  US95        Mb     / n[+        UR"                  S5      (       Ga  [        U Vs/ s H  nSU;   d  M  US   PM     sn5      n0 nU Hb  nUR	                  US	S
9nUR                  U;  a  [        5       UUR                  '   UUR                     R                  UR,                  5        Md     [        R                  " U5       Ha  u  nnUR                  [        R.                  " UR"                  R0                  UUSUR"                  R&                  UR(                  US95        Mc     [        U5      [        U5      -   n[        U Vs/ s H#  n[2        R4                  " UR6                  5      PM%     sn5      nU(       a  [8        R:                  " U5        / nU H  nUS   nUR=                  SS5      n[2        R4                  " U5      nUU;   nU(       a  U[>        R@                  :X  a  MR  U(       d  U[>        RB                  :X  a  Mo  U(       a  SOSUS'   U(       a  UUS'   URE                  U5        M     U$ s  snf s  snf s  snf )a-  Add information if instance group is managed.

Args:
  compute_holder: ComputeApiHolder, The compute API holder
  items: list of instance group messages,
  filter_mode: InstanceGroupFilteringMode, managed/unmanaged filtering options
Returns:
  list of instance groups with computed dynamic properties
r   r1   zcompute.zonesrw   N)r?   r1   requested_zonesfilter_exprhttp	batch_urlrU   r:   r2   zcompute.regions)ry   )r?   r1   requested_regionsr   r   r   rU   r   z/instanceGroups/z/instanceGroupManagers/YesNo	isManagedinstanceGroupManagerUri)#r   rV   r<   setr   r   VALUEScorer1   	GetOrFailaddr   six	iteritemsr   r   GetZonalResourcesr6   r   r   r   hasattrr2   GetRegionalResourcesr   r	   ScopedSuffixr   r
   r   replacer   r   r   rk   )compute_holderitemsfilter_moder   rV   rU   ig
zone_linksproject_to_zonesr   zone_refzonal_instance_group_managersr1   zones regional_instance_group_managersregion_linksproject_to_regionsr2   
region_refregionsinstance_group_managersigminstance_group_managers_refsrA   r(   	self_linkigm_self_linkscoped_suffix
is_manageds                                r   %ComputeInstanceGroupManagerMembershipr    sn      &&&)&
u+%?2&B,JBvJ?@*dz((--55??
 #  $H //+.5''(%%&**8==9  #%&67ng!(()A)A&&<<##((""*  8 &("V##%;<<uGuB8uGHL??66G?Hj			#5	514:--.++,001B1BC	 
  MM*<=&--f.I.I((DD#%%**$$/  > ()-./  "%(&*(# ""3<<0(&* "+ 	V$'dZ I%%57M#00?M">>J1GGG
3GG
G",$D(5d$%NN4# & 
.W @8 H(&*s   
N	N
N!	N!**N&)FN)FF)/rK   
__future__r   r   r   r~   enumapitools.base.pyr   googlecloudsdk.api_lib.computer   r   r	   r
   googlecloudsdk.callioper   googlecloudsdk.corer   r   r   	six.movesr   +INSTANCE_GROUP_GET_NAMED_PORT_DETAILED_HELPINSTANCES_MAX_LENGTHr   r"   r)   r-   rB   ErrorrD   rW   rb   rq   SET_NAMED_PORTS_HELPr   r   r   r   r   r   r   r   Enumr   r   r  rF   r   r   <module>r     s   K &  '   % 5 1 : 0 E # * 
  D	/ +.  <
(( 5&K
 0 0 K":&AR  B L (-XPz (<&R%)X"JNb"X !&',d6N  (B'L'L[r   