
                         *   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZ dd	lmZ dd
lmZ  G d dej,                        Z G d de      Zej5                          d Zej8                  d        Zy)z+Library for integrating Cloud Run with GKE.    )absolute_import)division)print_function)unicode_literalsN)api_adapter)base)
exceptions)filesc                       e Zd Zy)NoCaCertErrorN)__name__
__module____qualname__     %lib/googlecloudsdk/api_lib/run/gke.pyr   r   $   s    r   r   c                   j    e Zd ZdZdZed        Zed        Zd Ze	j                  d        Zd Zd Zy)	_AddressPatchesz/Singleton class to hold patches on getaddrinfo.Nc                 8    | j                   rJ  |        | _         y N	_instanceclss    r   
Initializez_AddressPatches.Initialize-   s    }}ECMr   c                 6    | j                   sJ | j                   S r   r   r   s    r   Getz_AddressPatches.Get2   s    =====r   c                 n    d | _         d | _        d | _        d | _        t	        j
                         | _        y r   )_host_to_ip_ip_to_host_old_getaddrinfo_old_match_hostname	threadingLock_lock)selfs    r   __init__z_AddressPatches.__init__7   s0    DD D#D!DJr   c              #     K   | j                   5  t        t        d      }| j                  Oi | _        i | _        |r*t        j
                  | _        | j                  t        _        t        j                  | _
        || j                  v rt        dj                  |            || j                  v rt        dj                  |            || j                  |<   || j                  |<   ddd       	 | | j                   5  | j                  |= | j                  |= | j                  s%d| _        d| _        r| j                  t        _        ddd       y# 1 sw Y   oxY w# 1 sw Y   yxY w# | j                   5  | j                  |= | j                  |= | j                  s%d| _        d| _        r| j                  t        _        ddd       w # 1 sw Y   w xY wxY ww)zDChange ssl address checking so the given ip answers to the hostname.match_hostnameNz$Cannot re-patch the same address: {})r%   hasattrsslr   r    r)   r"   _MatchHostnamesocketgetaddrinfor!   
ValueErrorformat)r&   hostnameipmatch_hostname_existss       r   MonkeypatchAddressCheckingz*_AddressPatches.MonkeypatchAddressChecking>   s     
%c+;<				! %(%7%7$
"#22#
 & 2 2	T%%	%299(CE 	E	t	299"=? 	?#%dx %dr# 
$
:h::X&R !$
!$
"!%!9!9C :+ 
* :4::X&R !$
!$
"!%!9!9C ::sg   G CE)G 2E/ 6G AE#	G E G #E,(G /G<AG	GGGG c                     | j                   5  | j                  J || j                  v r| j                  |   }ddd        | j                  |g|i |S # 1 sw Y   xY w)z/Like socket.getaddrinfo, only with translation.N)r%   r   r!   )r&   hostargskwargss       r   _GetAddrInfoz_AddressPatches._GetAddrInfo_   se    	)))	!!	!% 
 !4  7777	 
s   ,AA c                     | j                   5  | j                  J || j                  v r| j                  |   }d d d        | j                  ||      S # 1 sw Y   xY wr   )r%   r    r"   )r&   certr1   s      r   r,   z_AddressPatches._MatchHostnameg   s]    
 
)))	T%%	%##H- 
 ##D(33	 
s   ,AA)r   r   r   __doc__r   classmethodr   r   r'   
contextlibcontextmanagerr4   r9   r,   r   r   r   r   r   (   sZ    7)   " : :@8	4r   r   c                 J    t         j                         j                  | |      S )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   r4   )r1   r2   s     r   r4   r4   u   s     8 
				9	9(B	GGr   c              #   <  K   t        j                         5  t        j                  d      }|j	                  |       }ddd       j
                  }|r|j                  r|j                  }nt        d      t        j                         \  }}t        j                  |       t        j                  |t        j                  |      d       	 |j                   |f t        j"                  |       y# 1 sw Y   xY w# t        j"                  |       w xY ww)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   ClusterConnectionInforZ      s      $$&''-G  -G ' 
		$	d''''G H
II!!#,"h((2,  )4


H
$$IIh% '&$ IIhs4   D'C6BDD  D6C?;DDD)r<   
__future__r   r   r   r   rO   r>   rL   r-   r+   rJ   r#    googlecloudsdk.api_lib.containerr   googlecloudsdk.callioper   rD   googlecloudsdk.corer	   googlecloudsdk.core.utilr
   Errorr   objectr   r   r4   r?   rZ   r   r   r   <module>rb      s    2 &  % '   	  
   8 9 * *J$$ H4f H4T    H>  r   