3 fY7@sddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z m Z ddlmZddlmZmZmZejddZejjdd Ziad d Zd d ZddZGdddeZGdddeZGdddeZ ddZ!dddZ"dde dfddZ#d ddZ$dS)!N) ApiClientConfigurationObject configuration)ConfigException)UTCformat_rfc3339 parse_rfc3339)minutesZ KUBECONFIGz~/.kube/configc Cs>x4tjD](}ytj|Wq tk r0Yq Xq WiadS)N) _temp_filesvaluesosremoveOSError) temp_filerN/Users/olari/OneDrive/sandbox/awsBlog2/lambda/kubernetes/config/kube_config.py_cleanup_temp_files$s  rc Csxttdkrtjtt|}|tkr.t|Stj\}}|t|<t|d"}|j t |trd|j n|WdQRX|S)Nrwb) lenr atexitregisterrstrtempfilemkstempopenwrite isinstanceencode)contentZ content_key_namefdrrr_create_temp_file_with_content.s    &r$cCst|ttjjjtdkS)N)tzinfo)r EXPIRY_SKEW_PREVENTION_DELAYdatetimeutcnowreplacer)expiryrrr _is_expired=s r+c@s*eZdZdZd ddZddZd d ZdS) FileOrDataaCUtility class to read content of obj[%data_key_name] or file's content of obj[%file_key_name] and represent it as file or data. Note that the data is preferred. The obj[%file_key_name] will be used iff obj['%data_key_name'] is not set or empty. Assumption is file content is raw data and data field is base64 string. The assumption can be changed with base64_file_content flag. If set to False, the content of the file will assumed to be base64 and read as is. The default True value will result in base64 encode of the file content after read.NTcCsZ|s |d}d|_d|_||_||kr2|||_n$||krVtjjtjj||||_dS)Nz-data)_file_data_base64_file_contentrpathnormpathjoin)selfobjZ file_key_nameZ data_key_namefile_base_pathbase64_file_contentrrr__init__Ls zFileOrData.__init__cCsf|j o |j}|r<|jr0ttj|jj|_n t|j|_|jr`tjj |j r`t d|j|jS)zIf obj[%data_key_name] exists, return name of a file with base64 decoded obj[%data_key_name] content otherwise obj[%file_key_name].zFile does not exists: %s) r.r/r0r$base64 decodestringrrr1isfiler)r4Zuse_data_if_no_filerrras_fileYs zFileOrData.as_filec Cs\|j o |j}|rVt|j4}|jrBtjtjtj |j |_n |j |_WdQRX|jS)zIf obj[%data_key_name] exists, Return obj[%data_key_name] otherwise base64 encoded string of obj[%file_key_name] file content.N) r/r.rr0bytesdecoder9 encodestringrrread)r4Zuse_file_if_no_datafrrras_datags zFileOrData.as_data)Nr-T)__name__ __module__ __qualname____doc__r8r<rBrrrrr,Bs  r,c@s~eZdZddeddfddZdddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZeddZdS)KubeConfigLoaderNr-cCsXtd||_d|_d|_d|_|j|||_||_dd}|rH||_n||_||_ dS)Nz kube-configcSs*tjj\}}tjjjj}|j||S)N)googleauthdefaultZ transportrequestsRequestrefresh) credentialsZ project_idrequestrrr_refresh_credentialss z7KubeConfigLoader.__init__.._refresh_credentials) ConfigNode_config_current_context_user_clusterset_active_context_config_base_path_config_persister_get_google_credentials_client_configuration)r4 config_dictactive_contextZget_google_credentialsclient_configurationconfig_base_pathconfig_persisterrPrrrr8ws  zKubeConfigLoader.__init__cCs|dkr|jd}|jdj||_|jdjdrv|jjdrv|jdj|jdddd}|rn|d|_q|d|_nd|_|jdj|jdd d |_dS) Nzcurrent-contextcontextscontextuserZusersT)safeZclustersZcluster)rR get_with_namerSsafe_getrTrU)r4Z context_namerbrrrrVs      z#KubeConfigLoader.set_active_contextcCs.|js dS|jrdS|jr"dS|jdS)aRead authentication from kube-config user section if exists. This function goes through various authentication methods in user section of kube-config and stops if it finds a valid authentication method. The order of authentication methods is: 1. GCP auth-provider 2. token_data 3. token field (point to a token file) 4. username/password N)rT_load_gcp_token_load_user_token_load_user_pass_token)r4rrr_load_authentications z%KubeConfigLoader._load_authenticationcCsd|jkrdS|jd}d|kr$dS|ddkr4dSd|ksdd|dksdd|dkrlt|ddrl|jd|dd|_|jS)Nz auth-providerr"Zgcpconfigz access-tokenr*z Bearer %s)rTr+_refresh_gcp_tokentoken)r4providerrrrrfs     z KubeConfigLoader._load_gcp_tokencCshd|jdkri|jdjd<|jdd}|j}|j|jd<t|j|jd<|jrd|j|jjdS)Nrjz auth-providerz access-tokenr*)rTvaluerYrlrr*rXrR)r4rmrNrrrrks z#KubeConfigLoader._refresh_gcp_tokencCs0t|jdd|jddj}|r,d||_dSdS)NZ tokenFilerlF)r6r7z Bearer %sT)r,rTrWrBrl)r4rlrrrrgs  z!KubeConfigLoader._load_user_tokencCsFd|jkrBd|jkrBtjj|jdd|jddjd|_dSdS)Nusernamepassword:) basic_auth authorizationT)rTurllib3util make_headersgetrl)r4rrrrhs  z&KubeConfigLoader._load_user_pass_tokencCsd|jkrj|jd|_|jjdrjt|jd|jdj|_t|jd|jdj|_t|jd|jdj|_ d|jkr|jd |_ dS)Nserverhttpszcertificate-authority)r6zclient-certificatez client-keyzinsecure-skip-tls-verify) rUhost startswithr,rWr< ssl_ca_certrT cert_filekey_file verify_ssl)r4rrr_load_cluster_infos    z#KubeConfigLoader._load_cluster_infocCsVd|jkr|j|jjd<dddddg}x*|D]"}||jkr,t|j|t||q,WdS)Nrlrsrzr|r}r~r)__dict__rlrZapi_keysetattrgetattr)r4keyskeyrrr _set_configs    zKubeConfigLoader._set_configcCs|j|j|jdS)N)rirr)r4rrr load_and_setszKubeConfigLoader.load_and_setcCsdd|jdDS)NcSsg|] }|jqSr)rn).0rarrr sz2KubeConfigLoader.list_contexts..r`)rR)r4rrr list_contextsszKubeConfigLoader.list_contextscCs|jjS)N)rSrn)r4rrrcurrent_contextsz KubeConfigLoader.current_context)N)rCrDrErr8rVrirfrkrgrhrrrrpropertyrrrrrrGus      rGc@sBeZdZdZddZddZddZdd Zd d Zdd dZ dS)rQzRemembers each config key's path and construct a relevant exception message in case of missing keys. The assumption is all access keys are present in a well-formed kube-config.cCs||_||_dS)N)r"rn)r4r"rnrrrr8szConfigNode.__init__cCs ||jkS)N)rn)r4rrrr __contains__szConfigNode.__contains__cCs t|jS)N)rrn)r4rrr__len__szConfigNode.__len__cCs.t|jtrt|ts ||jkr*|j|SdS)N)rrnlistint)r4rrrrres zConfigNode.safe_getcCsP|j|}|s td||jft|ts4t|trHtd|j|f|S|SdS)Nz/Invalid kube-config file. Expected key %s in %sz%s/%s)rerr"rdictrrQ)r4rvrrr __getitem__s zConfigNode.__getitem__FcCs~t|jtstd|jxD|jD]:}d|krt|,}tftj|tjjtjj|d|SQRXdS)N)r[r^)rrGyamlloadrr1abspathdirname)filenamekwargsrArrr%_get_kube_config_loader_for_yaml_file<s  rcCs*|dkrtjjt}t|}|j|jfS)N)rr1 expanduserKUBE_CONFIG_DEFAULT_LOCATIONrrr) config_fileloaderrrrlist_kube_config_contextsDs rTcsDdkrtjjtd}|r,fdd}|}t|||djdS)aLoads authentication and cluster information from kube-config file and stores them in kubernetes.client.configuration. :param config_file: Name of the kube-config file. :param context: set the active context. If is set to None, current_context from config file will be used. :param client_configuration: The kubernetes.client.ConfigurationObject to set configs to. :param persist_config: If True, config file will be updated when changed (e.g GCP token refresh). Nc s*td}tj||ddWdQRXdS)NwF)default_flow_style)rr safe_dump) config_maprA)rrr_save_kube_configas z+load_kube_config.._save_kube_config)r\r]r_)rr1rrrr)rrar]persist_configr_rr)rrload_kube_configMs  rcCs t}t||||dt|dS)zLoads configuration the same as load_kube_config but returns an ApiClient to be used with any API object. This will allow the caller to concurrently talk with multiple clusters.)rrar]r)rj)rrr)rrar client_configrrrnew_client_from_configls r)N)NNT)%rr9r'rrZ google.authrHZgoogle.auth.transport.requestsrtrkubernetes.clientrrrconfig_exceptionrdateutilrrr timedeltar&environrwrr rr$r+objectr,rGrQrrrrrrrrs:   33