
    ZK                     p   d 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mZ ddlm	Z
 ddlmZ dd	lm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 G d de      ZdZ G d de      Zd"dZ	 	 	 	 	 	 	 	 	 	 	 	 d#dZd ZdZdZdez   Zd$dZ	 d%dZ d Z!d  Z"d! Z#y)&z-Utilities for loading and parsing kubeconfig.    )absolute_import)division)unicode_literalsN)config)
exceptions)log)
properties)yaml)encoding)files)	platformsc                       e Zd ZdZy)Errorz0Class for errors raised by kubeconfig utilities.N__name__
__module____qualname____doc__     2lib/googlecloudsdk/api_lib/container/kubeconfig.pyr   r   #   s    8r   r   c                       e Zd ZdZy)MissingEnvVarErrorzDAn exception raised when required environment variables are missing.Nr   r   r   r   r   r   '   s    Lr   r   c                   "     e Zd ZdZ fdZ xZS )2DNSEndpointOrUseApplicationDefaultCredentialsErrorz<Error for retrieving DNSEndpoint of a cluster that has none.c                 ,    t         t        |   d       y )NzZOnly one of --dns-endpoint or USE_APPLICATION_DEFAULT_CREDENTIALS should be set at a time.)superr   __init__)self	__class__s    r   r   z;DNSEndpointOrUseApplicationDefaultCredentialsError.__init__.   s    	
<dL	$r   )r   r   r   r   r   __classcell__)r    s   @r   r   r   +   s    D r   r   gke_gcloud_auth_plugin_cachec                       e Zd ZdZd Zed        Zed        Zd Zd Z	d Z
ed        Zed	        Zed
        Zed        Zed        Zd Zy)
Kubeconfigz1Interface for interacting with a kubeconfig file.c                    || _         || _        i | _        i | _        i | _        d }	 | j                  d   D ]  }|}|| j                  |d   <    | j                  d   D ]  }|}|| j                  |d   <    | j                  d   D ]  }|}|| j                  |d   <    y # t
        $ r }t        dj                  ||            d }~ww xY w)Nclustersnameuserscontextsz(expected key {0} not found for entry {1})	_filename_datar&   r(   r)   KeyErrorr   format)r   raw_datafilenameentryclusterusercontexterrors           r   r   zKubeconfig.__init__;   s    DNDJDMDJDMEZZ
+')0gfo& , **W%$#'

4<  & ZZ
+')0gfo& ,  
4
;
;E5
I s   A8B   	C	)CC	c                      | j                   d   S Ncurrent-contextr+   r   s    r   current_contextzKubeconfig.current_contextT   s    ::'((r   c                     | j                   S N)r*   r9   s    r   r/   zKubeconfig.filenameX   s    >>r   c                    | j                   j                  |d        | j                  j                  |d        | j                  j                  |d        | j                  j                  d      |k(  rd| j                  d<   y y )Nr7    )r)   popr&   r(   r+   get)r   keys     r   ClearzKubeconfig.Clear\   sf    MMc4 MMc4 JJNN3zz~~'(C/&(djj"# 0r   c                    t        | j                  j                               | j                  d<   t        | j                  j                               | j                  d<   t        | j
                  j                               | j                  d<   t        j                  | j                  d      5 }t        j                  | j                  |       ddd       t        j                  j                  | j                        }t        j                  j                  |t              }t        j                  j!                  |      rt        j"                  |d       yy# 1 sw Y   xY w)zzSave kubeconfig to file.

    Raises:
      Error: don't have the permission to open kubeconfig or plugin cache file.
    r&   r(   r)   T)privateNr>   )listr&   valuesr+   r(   r)   
file_utils
FileWriterr*   r
   dumpospathdirnamejoin&GKE_GCLOUD_AUTH_PLUGIN_CACHE_FILE_NAMEexistsWriteFileAtomically)r   fprL    gke_gcloud_auth_plugin_file_paths       r   
SaveToFilezKubeconfig.SaveToFilec   s     "$--"6"6"89DJJztzz0023DJJw!$--"6"6"89DJJz			t~~t	<
ii

B 
= ggoodnn-G')ww||7($ 
ww~~67$$%ErJ 8 
=	<s   2!EE(c                 "    || j                   d<   y r6   r8   )r   r3   s     r   SetCurrentContextzKubeconfig.SetCurrentContextz   s    $+DJJ !r   c           
          |st        d      	 dD ]?  }t        ||   t              rt        dj                  ||   t	        ||                      y# t
        $ r}t        dj                  |            d}~ww xY w)z2Make sure we have the main fields of a kubeconfig.z
empty file)r&   r(   r)   zinvalid type for {0}: {1}zexpected key {0} not foundN)r   
isinstancerE   r-   typer,   )clsdatarA   r4   s       r   	_ValidatezKubeconfig._Validate}   s     ,>2#$s)T*)00cDcOL  3
  >.55e<==>s   A +A 	A<A77A<c                     	 t        j                  |      }| j                  |        | ||      S # t         j                  $ r*}t        dj                  ||j                              d }~ww xY w)Nz&unable to load kubeconfig for {0}: {1})r
   	load_pathr   r-   inner_errorr[   )rY   r/   rZ   r4   s       r   LoadFromFilezKubeconfig.LoadFromFile   sl    ^^H%d MM$tX :: 
2
9
9)) s   1 A.%A))A.c                    t         j                  j                  |      rt        dj	                  |            t         j                  j                  |      r	 | j                  |      S t        j                  t         j                  j                  |              | t               |      }|j                          |S # t        t        f$ r/}t        j                  dj	                  ||             Y d}~d}~ww xY w)zARead in the kubeconfig, and if it doesn't exist create one there.z*{0} is a directory. File must be provided.z6unable to load default kubeconfig: {0}; recreating {1}N)rJ   rK   isdirIsADirectoryErrorr-   isfiler_   r   IOErrorr   debugrG   MakeDirrL   EmptyKubeconfigrS   )rY   rK   r4   
kubeconfigs       r   LoadOrCreatezKubeconfig.LoadOrCreate   s     
ww}}T
6
=
=d
C  
ww~~d
%% rwwt,-_&-J W 
		DKKt	
 	

s   C   C>%C99C>c                 H    | j                  t        j                               S r<   )ri   r$   DefaultPath)rY   s    r   DefaultzKubeconfig.Default   s    J22455r   c                  Z   t        j                  t        j                  d      } | rI| j	                  t        j
                        }|D ]%  } | st        j                  j                  |       c S  t        j                  t        j                  d      }|st        j                  j                         rt        j                  t        j                  d      }t        j                  t        j                  d      }|r"|r t        j                  j                  ||      }|s$t        j                  t        j                  d      }|sDt        dj                  t        j                  j                         rd            d            t        j                  j                  |d	d
      S )z(Return default path for kubeconfig file.
KUBECONFIGHOME	HOMEDRIVEHOMEPATHUSERPROFILEzVenvironment variable {vars} or KUBECONFIG must be set to store credentials for kubectlz&HOMEDRIVE/HOMEPATH, USERPROFILE, HOME,)varsz.kuber   )r   GetEncodedValuerJ   environsplitpathseprK   abspathr   OperatingSystem	IsWindowsrM   r   r-   )rh   kubeconfigshome_dir
home_drive	home_paths        r   rk   zKubeconfig.DefaultPath   sH    ))"**lCJ$$RZZ0k#*,
, $ ''

F;H	11;;=++BJJDj**2::zBi		77<<
I6++BJJF$$*F**446 < %+ % 
  %+ %  77<<'844r   c                 T   | j                  | j                  xs |j                         t        t        |j                  j                               t        | j                  j                               z         | _        t        t        |j                  j                               t        | j                  j                               z         | _        t        t        |j                  j                               t        | j                  j                               z         | _        y)zMerge another kubeconfig into self.

    In case of overlapping keys, the value in self is kept and the value in
    the other kubeconfig is lost.

    Args:
      kubeconfig: a Kubeconfig instance
    N)rU   r:   dictrE   r&   itemsr(   r)   )r   rh   s     r   MergezKubeconfig.Merge   s     	4//M:3M3MNZ  &&()D1D1D1F,GGDM d:++1134tDJJ<L<L<N7OOPDJZ  &&()D1D1D1F,GGDMr   N)r   r   r   r   r   propertyr:   r/   rB   rS   rU   classmethodr[   r_   ri   rl   staticmethodrk   r   r   r   r   r$   r$   8   s    92 ) )  )K., > > 
 
  ( 6 6 5 5@r   r$   c                 d    d|i}|r|rt        d      |r||d<   n||s||d<   n|sd|d<   | |dS )z0Generate and return a cluster kubeconfig object.serverz'cannot specify both ca_path and ca_datazcertificate-authorityzcertificate-authority-dataTzinsecure-skip-tls-verify)r'   r1   )r   )r'   r   ca_pathca_datahas_dns_endpointr1   s         r   Clusterr      s^     ' 
9
::'.G#$#3,3G()*.G&'7	++r   c                 x   |s|r|s|r|	st        d      i }t               }|r-|s|s|s|s|st        |||||      |d<   nt        |
|      |d<   |r|rt        d      |r||d<   n|r||d<   |r|	rt        d      |r||d	<   n|	r|	|d
<   |r(||d<   t        j
                  j                  d|  d       | |dS )a  Generates and returns a user kubeconfig object.

  Args:
    name: str, nickname for this user entry.
    auth_provider: str, authentication provider.
    auth_provider_cmd_path: str, authentication provider command path.
    auth_provider_cmd_args: str, authentication provider command args.
    auth_provider_expiry_key: str, authentication provider expiry key.
    auth_provider_token_key: str, authentication provider token key.
    cert_path: str, path to client certificate file.
    cert_data: str, base64 encoded client certificate data.
    key_path: str, path to client key file.
    key_data: str, base64 encoded client key data.
    dns_endpoint: str, cluster's DNS endpoint.
    impersonate_service_account: str, service account to impersonate.
    iam_token: str, IAM token to use for authentication.

  Returns:
    dict, valid kubeconfig user entry.

  Raises:
    Error: if no auth info is provided (auth_provider or cert AND key)
  z3either auth_provider or cert & key must be provided)r'   cmd_pathcmd_args
expiry_key	token_keyzauth-providerexecz+cannot specify both cert_path and cert_datazclient-certificatezclient-certificate-dataz)cannot specify both key_path and key_dataz
client-keyzclient-key-datatokenz-Added IAM token to kubeconfig entry for user .)r'   r2   )r   _UseExecAuth_AuthProvider_ExecAuthPluginr   statusPrint)r'   auth_providerauth_provider_cmd_pathauth_provider_cmd_argsauth_provider_expiry_keyauth_provider_token_key	cert_path	cert_datakey_pathkey_datadns_endpointimpersonate_service_account	iam_tokenr2   use_exec_auths                  r   Userr      s    P 	hI(
E
FF	$.- 	!#" ,))-+d? %\3NOd6l9
=
>>!*D	&/D	"#(
;
<<!D&D	DMJJDTF!LM	%%r   c                      d} t        j                  t        j                  d      }|r|j	                         dk(  rd} | S |r|j	                         dk(  rd} | S )zwReturns a bool noting if ExecAuth should be enabled.

  Returns:
    bool, which notes if ExecAuth should be enabled
  TUSE_GKE_GCLOUD_AUTH_PLUGINtruefalseF)r   rt   rJ   ru   lower)r   use_gke_gcloud_auth_plugins     r   r   r   O  sh     -'77jj.  !
$
*
*
,
6M 
 !
$
*
*
,
7M	r   zPath to sdk installation not found. Please switch to application default
credentials using one of

$ gcloud config set container/use_application_default_credentials true
$ export CLOUDSDK_CONTAINER_USE_APPLICATION_DEFAULT_CREDENTIALS=truezInstall gke-gcloud-auth-plugin for use with kubectl by following https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#install_pluginz{ACTION REQUIRED: gke-gcloud-auth-plugin, which is needed for continued use of kubectl, was not found or is not executable. c                    t         j                  j                  j                  j	                         }| r|r
t               t               }|dt        dd}g }|r|j                  d       |r|j                  d|z          |r||d<   |S )aQ  Generate and return an exec auth plugin config.

  Constructs an exec auth plugin config entry readable by kubectl.
  This tells kubectl to call out to gke-gcloud-auth-plugin and
  parse the output to retrieve access tokens to authenticate to
  the kubernetes master.

  Kubernetes GKE Auth Provider plugin is defined at
  https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

  GKE GCloud Exec Auth Plugin code is at
  https://github.com/kubernetes/cloud-provider-gcp/tree/master/cmd/gke-gcloud-auth-plugin

  Args:
    dns_endpoint: str, DNS endpoint.
    impersonate_service_account: str, service account to impersonate.

  Returns:
    dict, valid exec auth plugin config entry.
  Raises:
    Error: Only one of --dns-endpoint or USE_APPLICATION_DEFAULT_CREDENTIALS
    should be set at a time.
  z$client.authentication.k8s.io/v1beta1T)command
apiVersioninstallHintprovideClusterInfoz%--use_application_default_credentialsz--impersonate_service_account=args)	r	   VALUES	containeruse_app_default_credentialsGetBoolr   )_GetGkeGcloudPluginCommandAndPrintWarningGKE_GCLOUD_AUTH_INSTALL_HINTappend)r   r   #use_application_default_credentialsr   exec_cfgr   s         r   r   r   |  s    4 !!==EEG & 9
<
>>57' :1 	( 
$(KK78 KK03NNO	HV	/r   c                    d| i}| dk(  rt         j                  j                  j                  j	                         sd}t
        j                  j                         rd}|st        j                         j                  }|(t        j                  t               t        t              t        j                   j#                  ||      }	 t%                ||r|nd|r|nd|r|ndd}||d	<   |S # t&        $ r Y %w xY w)
a  Generates and returns an auth provider config.

  Constructs an auth provider config entry readable by kubectl. This tells
  kubectl to call out to a specific gcloud command and parse the output to
  retrieve access tokens to authenticate to the kubernetes master.
  Kubernetes gcp auth provider plugin at
  https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go/plugin/pkg/client/auth/gcp

  Args:
    name: auth provider name
    cmd_path: str, authentication provider command path.
    cmd_args: str, authentication provider command arguments.
    expiry_key: str, authentication provider expiry key.
    token_key: str, authentication provider token key.

  Returns:
    dict, valid auth provider config entry.
  Raises:
    Error: Path to sdk installation not found. Please switch to application
    default credentials using one of

    $ gcloud config set container/use_application_default_credentials true
    $ export CLOUDSDK_CONTAINER_USE_APPLICATION_DEFAULT_CREDENTIALS=true.
  r'   gcpgcloudz
gcloud.cmdz"config config-helper --format=jsonz{.credential.access_token}z{.credential.token_expiry})zcmd-pathzcmd-argsz	token-keyz
expiry-keyr   )r	   r   r   r   r   r   ry   rz   r   Pathssdk_bin_pathr   r4   SDK_BIN_PATH_NOT_FOUNDr   rJ   rK   rM   r   	Exception)	r'   r   r   r   r   providerbin_namer   cfgs	            r   r   r     s    6 d^(
em))EEMMOH  **,h\\^00l				()*++lH5h13  !H&J #,Y1M %J*FC$ HX	/1   	s   	
C- -	C98C9c                  ^   d} t         j                  j                         rd} | }	 t        j                  |dgddt        j
                  t        j
                         |S # t        $ r 	 t        j                         j                  }|t        j                  t               nZt        j                  j                  ||      }t        j                  |dgddt        j
                  t        j
                         |}Y |S # t        $ r t        j                  t               Y Y |S w xY ww xY w)zGet Gke Gcloud Plugin Command to be used.

  Returns Gke Gcloud Plugin Command to be used. Also,
  prints warning if plugin is not present or doesn't work correctly.

  Returns:
    string, Gke Gcloud Plugin Command to be used.
  zgke-gcloud-auth-pluginzgke-gcloud-auth-plugin.exez	--version   F)timeoutcheckstdoutstderr)r   ry   rz   
subprocessrunDEVNULLr   r   r   r   r   critical GKE_GCLOUD_AUTH_PLUGIN_NOT_FOUNDrJ   rK   rM   )r   r   r   sdk_path_bin_names       r   r   r     s    &(((*+H'5NN	+!!!!< 
./ 
 55 \\^00l		56GGLLw?,%%%%	
 $ 
.  5	ll34	.5)5s*   8A   	D,*BD"D(#D,'D((D,c                     | ||ddS )z0Generate and return a context kubeconfig object.)r1   r2   )r'   r3   r   )r'   r1   r2   s      r   Contextr   *  s     
 r   c                      dg g ddi g dS )Nv1r>   Config)r   r)   r&   r7   kindpreferencesr(   r   r   r   r   rg   rg   5  s!    
 r   )NNF)NNNNNNNNNNNN)NN)r   NNNN)$r   
__future__r   r   r   rJ   r   googlecloudsdk.corer   r   core_exceptionsr   r	   r
   googlecloudsdk.core.utilr   r   rG   r   r   r   r   rN   objectr$   r   r   r   r   r   r   r   r   r   r   rg   r   r   r   <module>r      s     4 &  ' 	  & = # * $ - 8 .9O!! 9M M  *H &j jZ,$ !  $W&t8H  d $ #$#  1j JNEP/d	r   