
                         *   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
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\R,                  5      r " S S\5      r\R5                  5         S r\R8                  S 5       rg)z+Library for integrating Cloud Run with GKE.    )absolute_import)division)print_function)unicode_literalsN)api_adapter)base)
exceptions)filesc                       \ rS rSrSrg)NoCaCertError$    N)__name__
__module____qualname____firstlineno____static_attributes__r       %lib/googlecloudsdk/api_lib/run/gke.pyr   r   $   s    r   r   c                   r    \ rS rSrSrSr\S 5       r\S 5       rS r	\
R                  S 5       rS rS	 rS
rg)_AddressPatches(   z/Singleton class to hold patches on getaddrinfo.Nc                 B    U R                   (       a   eU " 5       U l         g N	_instanceclss    r   
Initialize_AddressPatches.Initialize-   s    }}ECMr   c                 @    U R                   (       d   eU R                   $ r   r   r   s    r   Get_AddressPatches.Get2   s    =====r   c                 p    S U l         S U l        S U l        S U l        [        R
                  " 5       U l        g r   )_host_to_ip_ip_to_host_old_getaddrinfo_old_match_hostname	threadingLock_lock)selfs    r   __init___AddressPatches.__init__7   s0    DD D#D!DJr   c              #     #    U R                      [        [        S5      nU R                  cT  0 U l        0 U l        U(       a*  [        R
                  U l        U R                  [        l        [        R                  U l
        XR                  ;   a  [        SR                  U5      5      eX R                  ;   a  [        SR                  U5      5      eX R                  U'   XR                  U'   SSS5         Uv   U R                      U R                  U	 U R                  U	 U R                  (       d*  SU l        SU l        W(       a  U R                  [        l        SSS5        g! , (       d  f       N~= f! , (       d  f       g= f! U R                      U R                  U	 U R                  U	 U R                  (       d*  SU l        SU l        W(       a  U R                  [        l        SSS5        f ! , (       d  f       f = f= f7f)zDChange ssl address checking so the given ip answers to the hostname.match_hostnameNz$Cannot re-patch the same address: {})r+   hasattrsslr%   r&   r0   r(   _MatchHostnamesocketgetaddrinfor'   
ValueErrorformat)r,   hostnameipmatch_hostname_existss       r   MonkeypatchAddressChecking*_AddressPatches.MonkeypatchAddressChecking>   s     
%c+;<				! %(%7%7$
"#22#
 & 2 2	%%	%299(CE 	E		299"=? 	?#%x %r# 
$
:h::X&R !$
!$
"!%!9!9C :+ 
* :4::X&R !$
!$
"!%!9!9C ::sg   H	C E'/H	8F	 <H	AE8	H	'
E51H	8
FH		HAG5,	H5
H?HH	c                     U R                      U R                  c   eXR                  ;   a  U R                  U   nSSS5        U R                  " U/UQ70 UD6$ ! , (       d  f       N$= f)z/Like socket.getaddrinfo, only with translation.N)r+   r%   r'   )r,   hostargskwargss       r   _GetAddrInfo_AddressPatches._GetAddrInfo_   sa    	)))	!!	!% 
   7777	 
s   .A
A'c                     U R                      U R                  c   eX R                  ;   a  U R                  U   nS S S 5        U R                  X5      $ ! , (       d  f       N= fr   )r+   r&   r(   )r,   certr8   s      r   r3   _AddressPatches._MatchHostnameg   sY    
 
)))	%%	%##H- 
 ##D33	 
s   .A
A")r%   r&   r+   r'   r(   )r   r   r   r   __doc__r   classmethodr   r"   r-   
contextlibcontextmanagerr;   rA   r3   r   r   r   r   r   r   (   sZ    7)   " : :@8	4r   r   c                 H    [         R                  5       R                  X5      $ )a  Manipulate SSL address checking so we can talk to GKE.

GKE provides an IP address for talking to the k8s control plane, and a
ca_certs that signs the tls certificate the control plane provides.
Unfortunately, that tls certificate is for `kubernetes`, `kubernetes.default`,
`kubernetes.default.svc`, or `kubernetes.default.svc.cluster.local`.

In Python 3, we do this by patching ssl.match_hostname to allow the
`kubernetes.default` when we connect to the given IP address.

In Python 2, httplib2 does its own hosname checking so this isn't available.
Instead, we change getaddrinfo to allow a "fake /etc/hosts" effect.
This allows us to use `kubernetes.default` as the hostname while still
connecting to the ip address we know is the kubernetes server.

This is all ok, because we got the ca_cert that it'll use directly from the
gke api.  Calls to `getaddrinfo` that specifically ask for a given hostname
can be redirected to the ip address we provide for the hostname, as if we had
edited /etc/hosts, without editing /etc/hosts.

Arguments:
  hostname: hostname to replace
  ip: ip address to replace the hostname with
Returns:
  A context manager that patches an internal function for its duration, and
  yields the endpoint to actually connect to.
)r   r"   r;   )r8   r9   s     r   r;   r;   u   s    8 
				9	9(	GGr   c              #   b  #    [         R                  " 5          [        R                  " S5      nUR	                  U 5      nSSS5        WR
                  nU(       a  UR                  (       a  UR                  nO[        S5      e[        R                  " 5       u  pV[        R                  " U5        [        R                  " U[        R                  " U5      SS9   UR                   U4v   [        R"                  " U5        g! , (       d  f       N= f! [        R"                  " U5        f = f7f)a  Get the info we need to use to connect to a GKE cluster.

Arguments:
  cluster_ref: reference to the cluster to connect to.
Yields:
  A tuple of (endpoint, ca_certs), where endpoint is the ip address
  of the GKE control plane, and ca_certs is the absolute path of a temporary
  file (lasting the life of the python process) holding the ca_certs to
  connect to the GKE cluster.
Raises:
  NoCaCertError: if the cluster is missing certificate authority data.
v1Nz.Cluster is missing certificate authority data.T)private)calliope_baseWithLegacyQuotar   NewAPIAdapter
GetCluster
masterAuthclusterCaCertificater   tempfilemkstemposcloser
   WriteBinaryFileContentsbase64	b64decodeendpointremove)cluster_refadapterclusterauthca_datafdfilenames          r   ClusterConnectionInford      s      $$&''-G  -G ' 
		$	d''''G H
II!!#,"((2,  )4


H
$$IIh% '&$ IIhs5   D/(D BD/D ,D/
DD/D,,D/)rF   
__future__r   r   r   r   rY   rH   rV   r4   r2   rT   r)    googlecloudsdk.api_lib.containerr   googlecloudsdk.callioper   rN   googlecloudsdk.corer	   googlecloudsdk.core.utilr
   Errorr   objectr   r   r;   rI   rd   r   r   r   <module>rl      s    2 &  % '   	  
   8 9 * *J$$ H4f H4T    H>  r   