
    m                     D   S 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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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r)Sr*Sr+Sr, " S S\RZ                  5      r. " S S\RZ                  5      r/S r0S r1S  r2 " S! S"\35      r4 " S# S$\35      r5 " S% S&\Rl                  5      r7 " S' S(\35      r8 " S) S*\35      r9 " S+ S,\35      r:S- r;S. r<S/ r=g)0z5Utils for Kubernetes Operations for GKE Hub commands.    )absolute_import)division)print_function)unicode_literalsN)api_adapter)
kubeconfig)util)waiter)
exceptions)format_util)gke_util)execution_utils)log)
properties)requests)encoding)files)client)config)urljoini i:  i  c                       \ rS rSrSrSrg)	RBACError4   z,Class for errors raised by GKE Hub commands. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       ;lib/googlecloudsdk/command_lib/container/fleet/kube_util.pyr   r   4   s    4r"   r   c                       \ rS rSrSrSrg)KubectlError8   z5Class for errors raised when shelling out to kubectl.r   Nr   r   r"   r#   r%   r%   8   s    =r"   r%   c                 $    U R                  S5      $ )a6  Gets the UUID of the kube-system namespace.

Args:
  kube_client: A KubernetesClient.

Returns:
  the namespace UID

Raises:
  exceptions.Error: If the UID cannot be acquired.
  calliope_exceptions.MinimumArgumentException: if a kubeconfig file cannot be
    deduced from the command line flags or environment
zkube-system)GetNamespaceUIDkube_clients    r#   GetClusterUUIDr+   <   s     
	$	$]	33r"   c                 "    U R                  5       $ )aR  Gets the UUID of the kube-system namespace.

Args:
  kube_client: A KubernetesClient.

Returns:
  the cluster server version

Raises:
  exceptions.Error: If the cluster server version cannot be acquired.
  calliope_exceptions.MinimumArgumentException: if a kubeconfig file cannot be
    deduced from the command line flags or environment
)GetServerVersionr)   s    r#   GetClusterServerVersionr.   M   s     
	%	%	''r"   c           
         U R                  U5      (       az   [        R                  " [        5       [	        X5      SR                  U5      [        [        [        [        S9u  p#U(       d%  [        R                  " SR                  X5      5      egg! [        R                   a&    [        R                  " SR                  U5      5      ef = f)zDelete a namespace from the cluster.

Args:
  kube_client: The KubernetesClient towards the cluster.
  namespace: the namespace of connect agent deployment.

Raises:
  exceptions.Error: if failed to delete the namespace.
z&Deleting namespace [{}] in the clusterpre_start_sleep_msmax_wait_mswait_ceiling_mssleep_msz-Could not delete namespace [{}] from cluster.z7Could not delete namespace [{}] from cluster. Error: {}N)NamespaceExistsr
   WaitForKubernetesPollerNamespaceDeleteOperationformat"NAMESPACE_DELETION_INITIAL_WAIT_MSNAMESPACE_DELETION_TIMEOUT_MS'NAMESPACE_DELETION_MAX_POLL_INTERVAL_MS+NAMESPACE_DELETION_INITIAL_POLL_INTERVAL_MSTimeoutErrorr   Error)r*   	namespace	succeedederrors       r#   DeleteNamespacerC   ^   s       ++


"9
:
2
9
9)
D?3A>i  
C
J
J  % ,   
9
@
@
K s   AB :Cc                   2    \ rS rSrSrSrSrS rS rS r	Sr
g	)
MembershipCRDCreationOperation   z;An operation that waits for a membership CRD to be created.	unchanged
configuredc                 F    Xl         SU l        SU l        S U l        X l        g NF)r*   donerA   rB   membership_crd_manifest)selfr*   rL   s      r#   __init__'MembershipCRDCreationOperation.__init__   s#    "DIDNDJ#: r"   c                     g)Nz<creating membership CRD>r   rM   s    r#   __str__&MembershipCRDCreationOperation.__str__   s    &r"   c                     U R                   R                  U R                  5      u  pU(       a  SU l        X l        gU R
                  U;   d  U R                  U;   a  SU l        SU l        gg)zBUpdates this operation with the latest membership creation status.TN)r*   CreateMembershipCRDrL   rK   rB   CREATED_KEYWORDCONFIGURED_KEYWORDrA   rM   outerrs      r#   Update%MembershipCRDCreationOperation.Update   se    33$$HC dij 
			$(?(?3(Fdidn )Gr"   )rK   rB   r*   rL   rA   N)r   r   r   r   r    rV   rW   rN   rR   r[   r!   r   r"   r#   rE   rE      s    C/#;'r"   rE   c                   .    \ rS rSrSrS rS rSS jrSrg)	KubeconfigProcessor   z?A helper class that processes kubeconfig and context arguments.c	                     Xl         X l        X0l        X@l        XPl        X`l        Xpl        Xl        [        R                  " 5       (       d  [        R                  " S5      eSU l        SU l        g)a  Constructor for KubeconfigProcessor.

Args:
  api_adapter: the GKE api adapter used for running kubernetes commands
  gke_uri: the URI of the GKE cluster; for example,
    'https://container.googleapis.com/v1/projects/my-project/locations/us-central1-a/clusters/my-cluster'
  gke_cluster: the "location/name" of the GKE cluster. The location can be a
    zone or a region for e.g `us-central1-a/my-cluster`
  kubeconfig: the kubeconfig path
  internal_ip: whether to persist the internal IP of the endpoint.
  cross_connect_subnetwork: full path of the cross connect subnet whose
    endpoint to persist (optional)
  private_endpoint_fqdn: whether to persist the private fqdn.
  context: the context to use

Raises:
  exceptions.Error: if kubectl is not installed
zkubectl not installed.N)r   gke_urigke_clusterr   internal_ipcross_connect_subnetworkprivate_endpoint_fqdncontextc_utilCheckKubectlInstalledr   r?   gke_cluster_self_linkgke_cluster_uri)	rM   r   ra   rb   r   rc   rd   re   rf   s	            r#   rN   KubeconfigProcessor.__init__   sb    < #L" O"$<!!6L''))566!%DDr"   c           
         U R                   (       d  U R                  (       a  SnU R                   (       a$  [        R                  " U R                   5      u  p#nOT[        R
                  R                  R                  R                  5       n[        R                  " U R                  5      u  p4[        R                  " X#U5      u  U l        U l        [        U R                  UUUUU R                  U R                   U R"                  5      S4$ U R$                  (       dU  [&        R(                  " [*        R,                  S5      (       a+  [&        R(                  " [*        R,                  S5      (       a  gU R$                  =(       d.    [&        R(                  " [*        R,                  S5      =(       d    Sn[.        R0                  " U5      nU(       d  [2        R4                  " S/S5      e[6        R8                  R;                  U5      nU R<                  nXR>                  ;  a%  [@        RB                  " S	RE                  X5      5      eXh4$ )
a  Gets the kubeconfig, cluster context and resource link from arguments and defaults.

Args:
  temp_kubeconfig_dir: a TemporaryDirectoryObject.

Returns:
  the kubeconfig filepath and context name

Raises:
  calliope_exceptions.MinimumArgumentException: if a kubeconfig file cannot
    be deduced from the command line flags or environment
  exceptions.Error: if the context does not exist in the deduced kubeconfig
    file
NKUBERNETES_SERVICE_PORTKUBERNETES_SERVICE_HOSTNN
KUBECONFIGz~/.kube/config--kubeconfigzoPlease specify --kubeconfig, set the $KUBECONFIG environment variable, or ensure that $HOME/.kube/config existsz.context [{}] does not exist in kubeconfig [{}])#ra   rb   r   ParseGKEURIr   VALUEScoreproject	GetOrFailParseGKECluster%ConstructGKEClusterResourceLinkAndURIri   rj   _GetGKEKubeconfigr   rc   rd   re   r   r   GetEncodedValueosenvironr   ExpandHomeDircalliope_exceptionsMinimumArgumentExceptionkconfig
KubeconfigLoadFromFilerf   contextsr   r?   r9   )	rM   temp_kubeconfig_dircluster_projectlocationnamekubeconfig_filer   kccontext_names	            r#   GetKubeconfigAndContext+KubeconfigProcessor.GetKubeconfigAndContext   s   " ||t''o	*2*>*>t||*L'4$++0088BBD!11$2B2BC 
8
8 7d $"6 !++((	  ( OO$$RZZ1JKK$$RZZ1JKK 	 	##BJJ=	  $$_5J88
? 
 
			(	(	4B<<L;;&
:
A
A  ##r"   Nc                     Ub)  [         R                  " XS9  [        R                  " 5       $ [         R                  " 5         [        R                  " 5       $ )zGets a client derived from the kubeconfig and context.

Args:
  kubeconfig: path to a kubeconfig file, None if in-cluster config.
  context: the kubeconfig context to use, None if in-cluster config.

Returns:
  kubernetes.client.ApiClient
)config_filerf   )kube_client_configload_kube_configkube_client_lib	ApiClientload_incluster_config)rM   r   rf   s      r#   GetKubeClient!KubeconfigProcessor.GetKubeClient#  sG     ))  &&((..0&&((r"   )
r   rf   rd   rb   ri   rj   ra   rc   r   re   ro   )	r   r   r   r   r    rN   r   r   r!   r   r"   r#   r^   r^      s    G* XP$d)r"   r^   c                   *    \ rS rSrSrS rS rS rSrg)r7   i:  zGAn OperationPoller that polls operations targeting Kubernetes clusters.c                     UR                   $ N)rK   rM   	operations     r#   IsDoneKubernetesPoller.IsDone=  s    >>r"   c                 &    UR                  5         U$ r   )r[   )rM   operation_refs     r#   PollKubernetesPoller.Poll@  s    r"   c                 2    UR                   UR                  4$ r   )rA   rB   r   s     r#   	GetResultKubernetesPoller.GetResultD  s    11r"   r   N)	r   r   r   r   r    r   r   r   r!   r   r"   r#   r7   r7   :  s    O2r"   r7   c                      \ rS rSr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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S r S(S  jr!S(S! jr"S(S" jr#S(S# jr$S)S$ jr%S(S% jr&S&r'g)*KubernetesClientiH  z6A client for accessing a subset of the Kubernetes API.Nc                    SU l         SU l        U(       d  U(       a  [        R                  " 5       U l        [	        UUUUUUUUS9U l        U R
                  R                  U R                  5      u  U l        U l        U	(       d"  U
(       a  U R
                  R                  (       a  gU
(       a6  U R
                  R                  U R                  U R                  5      U l        gg)a  Constructor for KubernetesClient.

Args:
  api_adapter: the GKE api adapter used for running kubernetes commands
  gke_uri: the URI of the GKE cluster; for example,
    'https://container.googleapis.com/v1/projects/my-project/locations/us-central1-a/clusters/my-cluster'
  gke_cluster: the "location/name" of the GKE cluster. The location can be a
    zone or a region for e.g `us-central1-a/my-cluster`
  kubeconfig: the kubeconfig path
  internal_ip: whether to persist the internal IP of the endpoint.
  cross_connect_subnetwork: full path of the cross connect subnet whose
    endpoint to persist (optional)
  private_endpoint_fqdn: whether to persist the private fqdn.
  context: the context to use
  public_issuer_url: the public issuer url
  enable_workload_identity: whether to enable workload identity

Raises:
  exceptions.Error: if the client cannot be configured
  calliope_exceptions.MinimumArgumentException: if a kubeconfig file
    cannot be deduced from the command line flags or environment
20sN)r   ra   rb   r   rc   rd   re   rf   )kubectl_timeoutr   r   TemporaryDirectoryr^   	processorr   r   rf   rj   r   r*   )rM   r   ra   rb   r   rc   rd   re   rf   public_issuer_urlenable_workload_identitys              r#   rN   KubernetesClient.__init__K  s    F !D#D +!&!9!9!;d(!93	DN %)NN$J$J  %!DOT\  T^^%C%C55
//4<<d  r"   c                     U $ r   r   rQ   s    r#   	__enter__KubernetesClient.__enter__  s    Kr"   c                 T    U R                   b  U R                   R                  5         g g r   )r   Close)rM   _s     r#   __exit__KubernetesClient.__exit__  s%    +
$$& ,r"   c                     U R                  / SQS5      u  pU(       a  [        SR                  U5      5      eSU;  a  [        S5      eg)zCheck to see if the user can perform all the actions in any namespace.

Raises:
  KubectlError: if failing to get check for cluster-admin permissions.
  RBACError: if cluster-admin permissions are not found.
)authzcan-i*r   z--all-namespacesNz2Failed to check if the user is a cluster-admin: {}yesae  Missing cluster-admin RBAC role: The cluster-admin role-based accesscontrol (RBAC) ClusterRole grants you the cluster permissions necessary to connect your clusters back to Google. 
To create a ClusterRoleBinding resource in the cluster, run the following command:

kubectl create clusterrolebinding [BINDING_NAME]  --clusterrole cluster-admin --user [USER])_RunKubectlr%   r9   r   rX   s      r#   CheckClusterAdminPermissions-KubernetesClient.CheckClusterAdminPermissions  s\     7HC 
>
E
Ec
J  C(  r"   c                     U R                  SSUSS/S 5      u  p#U(       a%  [        R                  " SR                  U5      5      eUR	                  SS5      $ )Ngetr@   -ozjsonpath='{.metadata.uid}'z(Failed to get the UID of the cluster: {}' )r   r   r?   r9   replacerM   r@   rY   rZ   s       r#   r(    KubernetesClient.GetNamespaceUID  s_    	Y.JKHC 
4
;
;C
@  ;;sBr"   c                     U R                  / SQS5      u  pU(       a%  [        R                  " SR                  U5      5      e[        R
                  " U5      nUS   S   S-   US   S   -   nU$ )zGet server version of the cluster.

Raises:
  exceptions.Error: if failing to get namespaces.

Returns:
  Server version of the cluster in major.minor format (e.g. 1.21)
)versionr   jsonNz3Failed to get the server version of the cluster: {}serverVersionmajor.minor)r   r   r?   r9   r   loads)rM   rY   rZ   version_strs       r#   r-   !KubernetesClient.GetServerVersion  sz      94@HC

?
F
Fs
K  **S/COW%+c/.B7.KK  r"   c                 t    U R                  SSSU-   S/S5      u  p#U(       a  [        R                  " 5       eU$ )z!Get k8s events for the namespace.r   eventsz--namespace=z--sort-by='{.lastTimestamp}'N)r   r   r?   r   s       r#   	GetEventsKubernetesClient.GetEvents  sH    Y&*		
 	HC Jr"   c                 z   U R                  SSSUSS/S5      u  p#U(       a%  [        R                  " SR                  U5      5      eUS:X  a  / $ U R                  SSSUSS	/S5      u  p#U(       a%  [        R                  " SR                  U5      5      eU(       a  UR	                  5       R                  S
5      $ / $ )zGet the Connect Agent namespace by label.

Args:
  label: the label used for namespace selection

Raises:
  exceptions.Error: if failing to get namespaces.

Returns:
  The first namespace with the label selector.
r   
namespacesz
--selectorr   zjsonpath={.items}Nz,Failed to list namespaces in the cluster: {}z[]z"jsonpath={.items[0].metadata.name} )r   r   r?   r9   stripsplit)rM   labelrY   rZ   s       r#   NamespacesWithLabelSelector,KubernetesClient.NamespacesWithLabelSelector  s     	lE49LMHC 
8
?
?
D  d{i0	
 	
HC 
8
?
?
D  &)399;S!0b0r"   c                 0    U R                  / SQ5      u  pU$ )N)delete
membershipr   r   rM   r   rZ   s      r#   DeleteMembership!KubernetesClient.DeleteMembership  s    DEFAJr"   c                    [         R                  " S5      n[         R                  " S5      nUR                  UR                  5       5      (       aF  U R	                  SSUSS/5      u  pVU(       a%  [
        R                  " SR                  U5      5      eU$ UR                  UR                  5       5      (       aF  U R	                  SSUSS/5      u  pVU(       a%  [
        R                  " SR                  U5      5      eU$ g	)
)Get the RBAC cluster role binding policy.^clusterrole/^role/r   clusterrolebindingr   yaml Error retrieving RBAC policy: {}rolebindingN)recompilematchlowerr   r   r?   r9   )rM   rbac_policy_namerolecluster_patternnamespace_patternrY   rB   s          r#   GetRbacPermissionPolicy(KubernetesClient.GetRbacPermissionPolicy  s    jj1O

8,TZZ\**##&(8$
Gjc 
.556FG
 	
 jtzz|,,##-!14
@jc 
.556FG
 	
 j -r"   c                 v   U H  nUS   nUS   nU R                  SX4/S5      u  pVU(       a[  SU;   a0  [        R                  R                  SR	                  X45      5        M`  [
        R                  " SR	                  U5      5      e[        R                  R                  SR	                  U5      5        M     g	)
z.Clean up the RBAC cluster role binding policy.r      r   NNotFoundz!{} for RBAC policy: {} not exist.zError deleting RBAC policy: {}z{}T)r   r   statusPrintr9   r   r?   )rM   rbac_to_checkrbac_policy_pair	rbac_type	rbac_namerY   rZ   s          r#   CleanUpRbacPolicy"KubernetesClient.CleanUpRbacPolicy-  s    )"1%i"1%i!!8Y"BDIhc	
**

188N   !A!H!H!MN
N

S)* * r"   c                 6    U R                  SSU/S 5      u  p#X#4$ )Ndiff-f)_RunKubectlDiff)rM   rbac_policy_filerY   rZ   s       r#   GetRbacPolicyDiff"KubernetesClient.GetRbacPolicyDiff?  s%    ##VT3C$DdKHC8Or"   c                     SnU HX  nUS   nUS   nU R                  SXE/5      u  pgU(       a/  SU;   a  SnM3  [        R                  " SR                  U5      5      e  g   U(       a  gg)	r   Fr   r   r   r   Tr   Nr   r   r?   r9   )rM   r   	not_foundr   r   r   r   rZ   s           r#   GetRbacPolicyKubernetesClient.GetRbacPolicyE  sz    I)"1%i"1%i	 =>fa	)  !C!J!J3!OP
P *  r"   c                    [         R                  " S5      n[         R                  " S5      n/ n	U(       aC  U	R                  S[        R                  " SX1XE5      4S[        R                  " SX1XE5      4/5        U(       a+  U	R                  S[        R                  " SX1XE5      45        U	$ UR                  UR                  5       5      (       a+  U	R                  S[        R                  " SX1XE5      45        U	$ UR                  UR                  5       5      (       a)  U	R                  S[        R                  " SX1XE5      45        U	$ )	z$Get the formatted RBAC policy names.r   r   clusterroleimpersonater   anthos
permissionr   )r   r   extendr   RbacPolicyNameappendr   r   )
rM   r   r   
project_ididentityis_useranthos_supportr   r   r   s
             r#   GetRBACForOperations%KubernetesClient.GetRBACForOperationsV  sH    jj1O

8,M(( #(( 	 


$
$
 	.  
		tzz|	,	,


$
$JH 	  
	 	 	.	.


$
$JH 	 r"   c                     U R                  / SQS5      u  pU(       a,  SU;   a  g[        R                  " SR                  U5      5      eg)z:Returns a boolean indicating if the Membership CRD exists.)r   .customresourcedefinitions.apiextensions.k8s.iomemberships.hub.gke.ioNr   Fz#Error retrieving Membership CRD: {}Tr  r   s      r#   MembershipCRDExists$KubernetesClient.MembershipCRDExists  sN    	

 	FA 	s	BII#NOOr"   c                     U R                  / SQS5      u  pU(       a,  SU;   a  g[        R                  " SR                  U5      5      eU$ )z1Get the YAML representation of the Membership CR.)r   r   r   r   r   Nr   r   z"Error retrieving membership CR: {}r  rX   s      r#   GetMembershipCR KubernetesClient.GetMembershipCR  sK    94HC 	s	AHHMNNJr"   c                     U R                  / SQS5      u  pU(       a,  SU;   a  g[        R                  " SR                  U5      5      eU$ )z2Get the YAML representation of the Membership CRD.)r   r  r  r   r   Nr   r   z#Error retrieving membership CRD: {}r  rX   s      r#   GetMembershipCRD!KubernetesClient.GetMembershipCRD  sP    	
 		HC 	s	BII#NOOJr"   c                     U R                  5       (       d  gU R                  / SQS5      u  pU(       a,  SU;   a  g[        R                  " SR	                  U5      5      eU$ )z7Looks up the owner id field in the Membership resource.N)r   r   r   r   zjsonpath={.spec.owner.id}r   z"Error retrieving membership id: {})r  r   r   r?   r9   rX   s      r#   GetMembershipOwnerID%KubernetesClient.GetMembershipOwnerID  s^    ##%%NHC 	s	AHHMNNJr"   c                 $    U R                  U5      $ r   )Apply)rM   rL   s     r#   rU   $KubernetesClient.CreateMembershipCRD  s    ::-..r"   c           	      p   U(       ah  [         R                  " [        5       [        X5      [        [
        [        [        S9u  p4U(       a%  [        R                  " SR                  U5      5      eU(       a@  U R                  U5      u  p5U(       a%  [        R                  " SR                  U5      5      egg)zApply membership resources.r0   z.Membership CRD creation failed to complete: {}z,Failed to apply Membership CR to cluster: {}N)r
   r6   r7   rE   r:   r;   r<   r=   r   r?   r9   r(  )rM   rL   membership_cr_manifestr   rB   rZ   s         r#   ApplyMembership KubernetesClient.ApplyMembership  s    


(
G?3A>ha 
<CCEJ
 	
 zz01fa	:AA#F
 	
 
 r"   c                     U R                  U5      u  p#U(       a%  [        R                  " SR                  U5      5      eg)z Applying RBAC policy to Cluster.z/Failed to apply rbac policy file to cluster: {}N)	ApplyRbacr   r?   r9   )rM   r  r   rZ   s       r#   ApplyRbacPolicy KubernetesClient.ApplyRbacPolicy  s<    ^^,-FA

;
B
B3
G  r"   c                 6    U R                  SSU/5      u  p#US L $ )Nr   r@   r   rM   r@   r   rZ   s       r#   r5    KubernetesClient.NamespaceExists  s%    uk9=>FA$;r"   c                 0    U R                  SSU/SS9u  p#U$ )Nr   r@   z	--timeout)timeout_flagr   r3  s       r#   rC    KubernetesClient.DeleteNamespace  s,    	;	*  FA Jr"   c                     U(       a  SU/O/ nUR                  SUSSR                  U5      /5        U R                  U5      $ )a  Returns the value of a field on a Kubernetes resource.

Args:
  namespace: the namespace of the resource, or None if this resource is
    cluster-scoped
  resource: the resource, in the format <resourceType>/<name>; e.g.,
    'configmap/foo', or <resourceType> for a list of resources
  json_path: the JSONPath expression to filter with

Returns:
  The field value (which could be empty if there is no such field), or
  the error printed by the command if there is an error.
-nr   r   zjsonpath={{{}}})r  r9   r   )rM   r@   resource	json_pathcmds        r#   GetResourceField!KubernetesClient.GetResourceField  sD      )4
bCJJx'8'?'?	'JKLC  r"   c                 6    U R                  SSU/S 5      u  p#X#4$ )Napplyr  r   )rM   rbac_policyrY   rZ   s       r#   r/  KubernetesClient.ApplyRbac  s$    $ <dCHC8Or"   c                 0    U R                  / SQUS9u  p#X#4$ )N)r@  r  -stdinr   )rM   manifestrY   rZ   s       r#   r(  KubernetesClient.Apply  s!     4HEHC8Or"   c                 .    U R                  / SQUS9u  p#U$ )N)r   r  rD  rE  r   )rM   rG  r   rZ   s       r#   DeleteKubernetesClient.Delete	  s    38DFAJr"   c                 *    U R                  SSX/5      $ )a#  Gets logs from a workload in the cluster.

Args:
  namespace: the namespace from which to collect logs.
  log_target: the target for the logs command. Any target supported by
    'kubectl logs' is supported here.

Returns:
  The logs, or an error if there was an error gathering these logs.
logsr9  r   )rM   r@   
log_targets      r#   LogsKubernetesClient.Logs  s     VT9ABBr"   c                     [         R                  " 5       R                  XUS9nUR                  nUS:  a/  [        R
                  " SR                  XTR                  5      5      eUR                  $ )zInternal method to make requests against web URLs.

Args:
  method: request method, e.g. GET
  url: request URL
  headers: dictionary of request headers

Returns:
  Response body as a string

Raises:
  Error: If the response has a status code >= 400.
headersi  zstatus: {}, reason: {})	r   
GetSessionrequeststatus_coder   r?   r9   reasoncontent)rM   methodurlrS  rr   s         r#   _WebRequestKubernetesClient._WebRequest  s]     	%%f7%CA]]F}5<<VXXNOO99r"   c                     Uc  0 nU R                   R                  USS/S9  [        U R                   R                  R                  U5      nU R                   R
                  R                  XUS9nUR                  $ )a&  Internal method to make requests against the target cluster.

Args:
  method: request method, e.g. GET
  api_path: path to request against the API server
  headers: dictionary of request headers

Returns:
  Response body as a string.

Raises:
  Error: If the response has a status code >= 400.
NBearerToken)rS  querysauth_settingsrR  )r*   update_params_for_authr   configurationhostrest_clientrU  data)rM   rY  api_pathrS  rZ  r[  s         r#   _ClusterRequest KubernetesClient._ClusterRequest.  s|     g 	++]O ,  $""0055x
@C$$,,V',JA66Mr"   c                     SS0nSn Ub$  UR                  S5      S-   nU R                  SX2S9$ SnU R                  SX2S9$ ! [         a*  n[        R
                  " SR                  X45      5      eSnAff = f)	a!  Get the OpenID Provider Configuration for the K8s API server.

Args:
  issuer_url: string, the issuer URL to query for the OpenID Provider
    Configuration. If None, queries the custer's built-in endpoint.

Returns:
  The JSON response as a string.

Raises:
  Error: If the query failed.
Content-Typezapplication/jsonN/z!/.well-known/openid-configurationGETrR  z7Failed to get OpenID Provider Configuration from {}: {})rstripr\  rh  	Exceptionr   r?   r9   )rM   
issuer_urlrS  rZ  es        r#   GetOpenIDConfiguration'KubernetesClient.GetOpenIDConfigurationN  s     	*G C		$'JJs<<1##E3#@@ 
C
J
J s   &A A 
A5%A00A5c                     SS0nSn Ub  UnU R                  SX2S9$ SnU R                  SX2S9$ ! [         a*  n[        R                  " SR                  X45      5      eSnAff = f)a  Get the JSON Web Key Set for the K8s API server.

Args:
  jwks_uri: string, the JWKS URI to query for the JSON Web Key Set. If None,
    queries the cluster's built-in endpoint.

Returns:
  The JSON response as a string.

Raises:
  Error: If the query failed.
rk  zapplication/jwk-set+jsonNrm  rR  z/openid/v1/jwksz*Failed to get JSON Web Key Set from {}: {})r\  rh  ro  r   r?   r9   )rM   jwks_urirS  rZ  rq  s        r#   GetOpenIDKeyset KubernetesClient.GetOpenIDKeysetm  s     	2G C
		s<<##E3#@@ 
6
=
=c
E s   / / 
A#%AA#c                    [         R                  " 5       /nU R                  (       a  UR                  SU R                  /5        U R                  (       a  UR                  SU R                  /5        UR                  X0R
                  /5        UR                  U5        [        R                  " 5       n[        R                  " 5       n[        R                  " USUR                  UR                  US9nUS:w  a5  UR                  5       (       d   UR                  SR                  U5      5        US:X  a  UR                  5       OSUS:w  a  UR                  5       4$ S4$ )a_  Runs a kubectl command with the cluster referenced by this client.

Args:
  args: command line arguments to pass to kubectl
  stdin: text to be passed to kubectl via stdin
  timeout_flag: kubectl command flag used to set timeout

Returns:
  The contents of stdout if the return code is 0, stderr (or a fabricated
  error if stderr is empty) otherwise
	--contextrq   Tno_exitout_funcerr_funcin_strr   z"kubectl exited with return code {}N)rg   rh   rf   r  r   r   ioStringIOr   Execwritegetvaluer9   )rM   argsrF  r6  r<  rY   rZ   
returncodes           r#   r   KubernetesClient._RunKubectl  s    '')
*C||	jj+t||,-	jj.$//23JJ2234JJt
++-C
++-C %%TCII		%J Qs||~~	ii4;;JGH %/t$/ /3 r"   c                 P   [         R                  " 5       /nU R                  (       a  UR                  SU R                  /5        U R                  (       a  UR                  SU R                  /5        UR                  SU R
                  /5        UR                  U5        [        R                  " 5       n[        R                  " 5       n[        R                  " USUR                  UR                  US9nUS:X  a  UR                  5       OSUS:  a  UR                  5       4$ S4$ )a  Runs a kubectl diff command with the specified args.

Args:
  args: command line arguments to pass to kubectl
  stdin: text to be passed to kubectl via stdin

Returns:
  The contents of stdout if the return code is 1, stderr (or a fabricated
  error if stderr is empty) otherwise
ry  rq   --request-timeoutTrz  r   N)rg   rh   rf   r  r   r   r  r  r   r  r  r  )rM   r  rF  r<  rY   rZ   r  s          r#   r   KubernetesClient._RunKubectlDiff  s     '')
*C||	jj+t||,-	jj.$//23JJ#T%9%9:;JJt
++-C
++-C %%TCII		%J %/t$q. .2 r"   )rf   r*   r   r   r   r   )
NNNNFNNNNFr   )Nr  )(r   r   r   r   r    rN   r   r   r   r(   r-   r   r   r   r   r   r  r	  r  r  r  r"  r%  rU   r,  r0  r5   rC   r=  r/  r(  rJ  rO  r\  rh  rr  rv  r   r  r!   r   r"   r#   r   r   H  s    > # $HT'
4	 .&1P
0$"0d 	$/
,!$C(@>:!Fr"   r   c                   *    \ rS rSrSrS rS rS rSrg) DeploymentPodsAvailableOperationi  zGAn operation that tracks whether a Deployment's Pods are all available.c                 ^    Xl         X l        X0l        X@l        SU l        SU l        S U l        g rJ   )r@   deployment_nameimager*   rK   rA   rB   )rM   r@   r  r  r*   s        r#   rN   )DeploymentPodsAvailableOperation.__init__  s-    N*J"DIDNDJr"   c                 N    SR                  U R                  U R                  5      $ )Nz<Pod availability for {}/{}>)r9   r@   r  rQ   s    r#   rR   (DeploymentPodsAvailableOperation.__str__  s$    )00,, r"   c                   ^  SR                  T R                  5      nU 4S jnT R                  R                  T R                  US5      u  p4U(       a	  U" U5        gUT R
                  :w  a  gT R                  R                  T R                  US5      u  pTU(       a	  U" U5        gT R                  R                  T R                  US5      u  pdU(       a	  U" U5        gT R                  R                  T R                  US5      u  ptU(       a	  U" U5        gT R                  R                  T R                  US5      u  pU(       a	  U" U5        gX:  a  gXh:  a  gXx:  a  gS	T l        S	T l        g)
zFUpdates this operation with the latest Deployment availability status.zdeployment/{}c                 >   > SU ;   a  gSTl         STl        U Tl        g)z-Updates the operation for the provided error.r   NTF)rK   rA   rB   )rZ   rM   s    r#   
_HandleErr;DeploymentPodsAvailableOperation.Update.<locals>._HandleErr  s'     
s	 didndjr"   z'.spec.template.spec.containers[0].imageNz.spec.replicasz.status.replicasz.status.availableReplicasz.status.updatedReplicasT)r9   r  r*   r=  r@   r  rA   rK   )	rM   deployment_resourcer  deployment_imagerZ   spec_replicasstatus_replicasavailable_replicasupdated_replicass	   `        r#   r[   'DeploymentPodsAvailableOperation.Update  sg   )001E1EF	 !,,==1
 o4::%))::+-=M o++<<+-?O o"..??+-H o ,,==+-F o
 '),DNDIr"   )r  rK   rB   r  r*   r@   rA   N	r   r   r   r   r    rN   rR   r[   r!   r   r"   r#   r  r    s    O
Er"   r  c                   *    \ rS rSrSrS rS rS rSrg)r8   i(  z6An operation that waits for a namespace to be deleted.c                 F    Xl         X l        SU l        SU l        S U l        g rJ   )r@   r*   rK   rA   rB   )rM   r@   r*   s      r#   rN   !NamespaceDeleteOperation.__init__+  s"    N"DIDNDJr"   c                 8    SR                  U R                  5      $ )Nz<deleting namespace {}>)r9   r@   rQ   s    r#   rR    NamespaceDeleteOperation.__str__2  s    $++DNN;;r"   c                     U R                   R                  U R                  5      nU(       d  gSU;   a  SU l        SU l        gXl        g)zAUpdates this operation with the latest namespace deletion status.Nr   T)r*   rC   r@   rK   rA   rB   )rM   rZ   s     r#   r[   NamespaceDeleteOperation.Update5  sA    



*
*4>>
:C  Sdidnjr"   )rK   rB   r*   r@   rA   Nr  r   r"   r#   r8   r8   (  s    ><r"   r8   c                    [         R                  R                  UR                  S5      n[        R                  " [         R
                  S5      n	 [        R                  " [         R
                  SU5        U c  [        R                  " S5      n U R                  X2U5      n
U R                  U
5      nUR                  nU=(       a    UR                  =(       a    UR                  nU(       dR  [        R                  R!                  5       (       d/  [        R"                  " SR%                  U
R&                  5      5      e[        R                  R)                  UU
R&                  UUU5        U	(       a(  [        R                  " [         R
                  SU	5        U$ [         R
                  S	  U$ ! U	(       a'  [        R                  " [         R
                  SU	5        f [         R
                  S	 f = f)a  The kubeconfig of GKE Cluster is fetched using the GKE APIs.

The 'KUBECONFIG' value in `os.environ` will be temporarily updated with
the temporary kubeconfig's path if the kubeconfig arg is not None.
Consequently, subprocesses started with
googlecloudsdk.core.execution_utils.Exec will see the temporary KUBECONFIG
environment variable.

Using GKE APIs the GKE cluster is validated, and the ClusterConfig object, is
persisted in the temporarily updated 'KUBECONFIG'.

Args:
  api_adapter: the GKE api adapter used for running kubernetes commands
  project: string, the project id of the cluster for which kube config is to
    be fetched
  location_id: string, the id of the location to which the cluster belongs
  cluster_id: string, the id of the cluster
  temp_kubeconfig_dir: TemporaryDirectory object
  internal_ip: whether to persist the internal IP of the endpoint.
  cross_connect_subnetwork: full path of the cross connect subnet whose
    endpoint to persist (optional)
  private_endpoint_fqdn: whether to persist the private fqdn.

Raises:
  Error: If unable to get credentials for kubernetes cluster.

Returns:
  the path to the kubeconfig file
r   rp   v1zGUnable to get cluster credentials. User must have edit permission on {})r{   pathjoinr   rz   r|   SetEncodedValuegke_api_adapterNewAPIAdapterParseCluster
GetCluster
masterAuthclientCertificate	clientKeyrg   ClusterConfigUseGCPAuthProviderr?   r9   	projectIdPersist)r   ru   location_id
cluster_idr   rc   rd   re   r   old_kubeconfigcluster_refclusterr   valid_credss                 r#   ry   ry   F  sw   N ww||/44lC*++BJJE.#RZZzB#11$7k**:GLK$$[1GDD411DdnnK v33FFHHLL#VK$9$9:      rzz<H 
 **\
"		 rzz<H
**\
"s   DF0 0AG1c                 6   [        U 5      nUR                  (       a  U(       a  [        R                  " SS5      eUR                  (       a  U(       d  [        R                  " SS5      eUR
                  (       a  U(       d  [        R                  " SS5      egg)ae  Validates if --gke-cluster | --gke-uri is supplied for GKE cluster, and --context for non GKE clusters.

Args:
  kube_client: A Kubernetes client for the cluster to be registered.
  args: An argparse namespace. All arguments that were provided to this
    command invocation.

Raises:
  calliope_exceptions.ConflictingArgumentsException: --context, --gke-uri,
  --gke-cluster are conflicting arguments.
  calliope_exceptions.ConflictingArgumentsException is raised if more than
  one of these arguments is set.

  calliope_exceptions.InvalidArgumentException is raised if --context is set
  for non GKE clusters.
ry  z]--context cannot be used for GKE clusters. Either --gke-uri | --gke-cluster must be specifiedz	--gke-uriz#use --context for non GKE clusters.z--gke-clusterN)IsGKEClusterrf   r~   InvalidArgumentExceptionra   rb   )r*   r  is_gke_clusters      r#   ValidateClusterIdentifierFlagsr    s    "  ,.	\\n

6
6	=  
\\.

6
6:  
n

6
6>  -r"   c                     U R                   (       a  U R                   R                  (       a  gU R                  SSS5      u  pU(       a%  [        R                  " SR                  U5      5      eU(       d  gg)a  Returns true if the cluster to be registered is a GKE cluster.

There is no straightforward way to obtain this information from the cluster
API server directly. This method uses metadata on the Kubernetes nodes to
determine the instance ID. The instance ID field is unique to GKE clusters:
Kubernetes-on-GCE clusters do not have this field. This test doesn't work in
identifing a GKE cluster with zero nodes.

Args:
  kube_client: A Kubernetes client for the cluster to be registered.

Raises:
    exceptions.Error: if failing there's a permission error or for invalid
    command.

Returns:
  bool: True if kubeclient communicates with a GKE Cluster, false otherwise.
TNnodeszE.items[*].metadata.annotations.container\.googleapis\.com/instance_idz)kubectl returned non-zero status code: {}F)r   ri   r=  r   r?   r9   )r*   vm_instance_idrZ   s      r#   r  r    sk    , {44JJ#44
O. 	


3::3?  
	r"   )>r    
__future__r   r   r   r   r  r   r{   r    googlecloudsdk.api_lib.containerr   r  r   r   r	   rg   googlecloudsdk.api_lib.utilr
   googlecloudsdk.callioper   r~   *googlecloudsdk.command_lib.container.fleetr   6googlecloudsdk.command_lib.container.fleet.membershipsr   googlecloudsdk.corer   r   r   r   googlecloudsdk.core.utilr   r   
kubernetesr   r   r   r   six.moves.urllib.parser   r:   r;   r<   r=   r?   r   r%   r+   r.   rC   objectrE   r^   OperationPollerr7   r   r  r8   ry   r  r  r   r"   r#   <module>r     s   < &  % ' 	  	 	 K B ; . E B K * / # * ( - * 0 3 * &' " - *3 '.6 +5
   5>:## >4"("!HV @U)& U)p2v-- 2D
v D
NVv Vrv <DN!H&r"   