o
    |                     @   s*  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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ZddlmZ ddlmZ dZzddlZW n	 eyc   Y nw edurneeddZdZejejejefZdZdd ZG dd de Z!e! Z"dddZ#dd Z$dS )z+Caching logic for checking if we're on GCE.    )absolute_import)division)unicode_literalsN)config)
properties)gce_read)files)retry)http_client)urllib_errorCertificateErroriX  zName or service not knownc                 C   s6   ~ ~~t |ts
dS t |tjrtt|v rdS dS )z;Decides if we need to retry the metadata server connection.FT)
isinstance(_POSSIBLE_ERRORS_GCE_METADATA_CONNECTIONr   URLError_DOMAIN_NAME_RESOLVE_ERROR_MSGsix	text_type)exc_type	exc_valueexc_tracebackstate r   F/tmp/google-cloud-sdk/lib/googlecloudsdk/core/credentials/gce_cache.py$_ShouldRetryMetadataServerConnection8   s   
r   c                   @   sj   e Zd ZdZdddZdddZdd	 Zd
d Zdd Zdd Z	dd Z
dd Zejdeddd ZdS )_OnGCECachea  Logic to check if we're on GCE and cache the result to file or memory.

  Checking if we are on GCE is done by issuing an HTTP request to a GCE server.
  Since HTTP requests are slow, we cache this information. Because every run
  of gcloud is a separate command, the cache is stored in a file in the user's
  gcloud config dir. Because within a gcloud run we might check if we're on GCE
  multiple times, we also cache this information in memory.
  A user can move the gcloud instance to and from a GCE VM, and the GCE server
  can sometimes not respond. Therefore the cache has an age and gets refreshed
  if more than _GCE_CACHE_MAX_AGE passed since it was updated.
  Nc                 C   s   || _ || _t | _d S N)	connectedexpiration_time	threadingLock	file_lock)selfr   r   r   r   r   __init__R   s   z_OnGCECache.__init__Tc                 C   sF   | j |d}|dur|S | j|    | j |d}|dur|S |  S )af  Check if we are on a GCE machine.

    Checks, in order:
    * in-memory cache
    * on-disk cache
    * metadata server

    If we read from one of these sources, update all of the caches above it in
    the list.

    If check_age is True, then update all caches if the information we have is
    older than _GCE_CACHE_MAX_AGE. In most cases, age should be respected. It
    was added for reporting metrics.

    Args:
      check_age: bool, determines if the cache should be refreshed if more than
        _GCE_CACHE_MAX_AGE time passed since last update.

    Returns:
      bool, if we are on GCE or not.
    	check_ageN)_CheckMemory_WriteMemory
_CheckDiskCheckServerRefreshAllCaches)r!   r$   on_gcer   r   r   GetOnGCEW   s   z_OnGCECache.GetOnGCEc                 C   s*   |   }| | | |t t  |S r   )_CheckServerWithRetry
_WriteDiskr&   time_GCE_CACHE_MAX_AGE)r!   r)   r   r   r   r(   x   s   
z'_OnGCECache.CheckServerRefreshAllCachesc                 C   s(   |s| j S | jr| jt kr| j S d S r   )r   r   r-   )r!   r$   r   r   r   r%   ~   s
   z_OnGCECache._CheckMemoryc                 C   s   || _ || _d S r   )r   r   )r!   r)   r   r   r   r   r&      s   
z_OnGCECache._WriteMemoryc                 C   s   t   }| j6 z t|j}|t }t	|}|t
dk|fW W  d   S  tttjfy>   Y W d   dS w 1 sBw   Y  dS )zReads cache from disk.TNNN)r   PathsGCECachePathr    osstatst_mtimer.   r   ReadFileContentsr   r   OSErrorIOErrorError)r!   gce_cache_pathmtimer   gcecache_file_valuer   r   r   r'      s   
z_OnGCECache._CheckDiskc                 C   s~   t   }| j, ztj|t|dd W n tt	tj
fy$   Y n	w W d   dS W d   dS 1 s8w   Y  dS )zUpdates cache on disk.T)privateN)r   r0   r1   r    r   WriteFileContentsr   r   r6   r7   r8   )r!   r)   r9   r   r   r   r,      s   

"z_OnGCECache._WriteDiskc                 C   s    z|   W S  ty   Y dS w )NF)_CheckServerr   r!   r   r   r   r+      s
   
z!_OnGCECache._CheckServerWithRetry   )max_retrialsshould_retry_ifc                 C   s   t t jtjjj  S r   )	r   ReadNoProxy'GOOGLE_GCE_METADATA_NUMERIC_PROJECT_URIr   VALUEScomputegce_metadata_check_timeout_secGetIntisdigitr?   r   r   r   r>      s   z_OnGCECache._CheckServerr/   T)__name__
__module____qualname____doc__r"   r*   r(   r%   r&   r'   r,   r+   r	   RetryOnExceptionr   r>   r   r   r   r   r   E   s    

!r   Tc                 C   s
   t | S )zAHelper function to abstract the caching logic of if we're on GCE.)_SINGLETON_ON_GCE_CACHEr*   r#   r   r   r   r*      s   
r*   c                   C   s   t  S )z@Force rechecking server status and refreshing of all the caches.)rP   r(   r   r   r   r   ForceCacheRefresh   s   rQ   rJ   )%rN   
__future__r   r   r   r2   socketr   r-   googlecloudsdk.corer   r   googlecloudsdk.core.credentialsr   googlecloudsdk.core.utilr   r	   r   	six.movesr
   r   SslCertificateErrorsslImportErrorgetattrr.   r   errorHTTPExceptionr   r   r   objectr   rP   r*   rQ   r   r   r   r   <module>   sF   t
