o
    6                     @   sv  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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ZdZdZdZdZG dd de
jZG dd deZG dd deZ G dd deZ!G dd deZ"dd Z#dd  Z$d!d" Z%		#d*d$d%Z&d+d&d'Z'G d(d) d)e(Z)dS ),z<Implementations of installers for different component types.    )absolute_import)division)unicode_literalsN)
exceptions)local_file_adapter)log)
properties)	transport)
console_io)files)http_encoding)retryUPDATE_MANAGER<      i @  c                   @      e Zd ZdZdS )Errorz)Base exception for the installers module.N__name__
__module____qualname____doc__ r   r   C/tmp/google-cloud-sdk/lib/googlecloudsdk/core/updater/installers.pyr   1       r   c                           e Zd ZdZ fddZ  ZS )ComponentDownloadFailedErrorzBException for when we cannot download a component for some reason.c                    s&   t t| dj|dt|  d S )Nz4The component [{component_id}] failed to download.

)component_id)superr   __init__formatsix	text_type)selfr   e	__class__r   r   r   9   s   
z%ComponentDownloadFailedError.__init__r   r   r   r   r   __classcell__r   r   r%   r   r   6       r   c                   @   r   )URLFetchErrorz)Exception for problems fetching via HTTP.Nr   r   r   r   r   r*   ?   r   r*   c                       r   )AuthenticationErrorz?Exception for when the resource is protected by authentication.c                    s"   t t| |d t|  d S )Nz

)r   r+   r   r!   r"   )r#   msgr$   r%   r   r   r   G   s   "zAuthenticationError.__init__r'   r   r   r%   r   r+   D   r)   r+   c                   @   r   )UnsupportedSourceErrorzGAn exception when trying to install a component with an unknown source.Nr   r   r   r   r   r-   K   r   r-   c                 C   sD  ddl m} | tjr| tjtjd} dtt	
|d}t}|tkr(t}zt| ||dW S  tjjy } zc|jjdksH|jjtjsJ|z|jdd	}|| W n tjyi } ztd
|d}~ww zt| ||dW W  Y d}~S  tjjy } z|jjdkr|tdjtjjj d|d}~ww d}~ww )a)  Gets the request object for the given URL using the requests library.

  If the URL is for cloud storage and we get a 403, this will try to load the
  active credentials and use them to authenticate the download.

  Args:
    url: str, the URL to download.
    command_path: str, the command path to include in the User-Agent header if
      the URL is HTTP.

  Raises:
    AuthenticationError: If this download requires authentication and there
      are no credentials or the credentials do not have access.

  Returns:
    requests.Response object
  r   )store   s   no-cache)s   Cache-Controls
   User-Agent)headerstimeouti  T)use_google_authz5This component requires valid credentials to install.NzAccount [{account}] does not have permission to install this component.  Please
ensure that this account should have access or run:

$ gcloud config set account `ACCOUNT`

to choose another account.)account) googlecloudsdk.core.credentialsr.   
startswithComponentInstallerGCS_BROWSER_DL_URLreplaceGCS_API_DL_URLr   Encoder	   MakeUserAgentStringTIMEOUT_IN_SECUPDATE_MANAGER_COMMAND_PATHUPDATE_MANAGER_TIMEOUT_IN_SEC_RawRequestrequestsr   	HTTPErrorresponsestatus_codeurlLoadFreshCredentialapplycreds_exceptionsr   r+   r    r   VALUEScorer3   Get)rD   command_pathr.   r0   r1   r$   credsr   r   r   MakeRequestP   sV   rM   c               
   O   s   dd }dd }t jddd|d}z|jt| ||d	d
W S  t jy@ } z|jd r;tj|jd d |jd d d  d}~ww )zExecutes an HTTP request.c                 S   s   | t jjko|jjdkS )Ni  )r@   r   rA   rB   rC   )exc_type	exc_valueunused_tracebackunused_stater   r   r   RetryIf   s   
z_RawRequest.<locals>.RetryIfc                 S   s   t d d S )NzRetrying request...)r   debug)unused_resultrQ   r   r   r   StatusUpdate   s   z!_RawRequest.<locals>.StatusUpdater      d   )max_retrialsexponential_sleep_multiplier	jitter_msstatus_update_funci  )should_retry_ifsleep_msr/   )tbN)r   RetryerRetryOnException!_ExecuteRequestAndRaiseExceptionsRetryExceptionlast_resultr   reraise)argskwargsrR   rU   retryerr$   r   r   r   r?      s,   
"r?   c                 C   sL   ddl m} | }| dr|dt  |j| ||dd}|  |S )aP  Executes an HTTP request using requests.

  Args:
    url: str, the url to download.
    headers: obj, the headers to include in the request.
    timeout: int, the timeout length for the request.

  Returns:
    A response object from the request.

  Raises:
    requests.exceptions.HTTPError in the case of a client or server error.
  r   )r@   zfile://T)r0   r1   stream)	googlecloudsdk.corer@   
GetSessionr5   mountr   LocalFileAdaptergetraise_for_status)rD   r0   r1   core_requestsrequests_sessionrB   r   r   r   ra      s   
ra   unknownc              
   C   s   |pt j}tj|st| tj|tj| }tj|r&t	| zBt
| |}t|)}d}t|j}|jtdD ]}	||	 |t|	7 }|||  q?W d   n1 s]w   Y  |d W |S  tjjtfy| }
 zt|
d}
~
ww )a  Download the given tar file.

  Args:
    url: str, The URL to download.
    download_dir: str, The path to put the temporary download file into.
    progress_callback: f(float), A function to call with the fraction of
      completeness.
    command_path: the command path to include in the User-Agent header if the
      URL is HTTP

  Returns:
    str, The path of the downloaded tar file.

  Raises:
    URLFetchError: If there is a problem fetching the given URL.
  r   )
chunk_sizeNr/   )r
   DefaultProgressBarCallbackospathexists
file_utilsMakeDirjoinbasenameremoverM   BinaryFileWriterlencontentiter_contentWRITE_BUFFER_SIZEwriter@   r   rA   OSErrorr*   )rD   download_dirprogress_callbackrK   download_file_pathrB   fptotal_written
total_sizechunkr$   r   r   r   DownloadTar   s.   






r   c           
      C   s   |pt j}tj|st| tj| d[}|	 }t
|}g }t|ddD ]>\}}|| r6|jd n|j ||| tj||j}	tj|	r_t|	tjs_t|	tjtjB  |||  q'|d W d   n1 stw   Y  t|  |S )aP  Extracts the given archive.

  Args:
    downloaded_archive: str, The path to the archive downloaded previously.
    extract_dir: str, The path to extract the tar into.
    progress_callback: f(float), A function to call with the fraction of
      completeness.

  Returns:
    [str], The files that were extracted from the tar file.
  )namer/   )start/N)r
   rs   rt   ru   rv   rw   rx   tarfileopen
getmembersr}   	enumerateappendisdirr   extractry   isfileaccessW_OKchmodstatS_IWUSRS_IREADr{   )
downloaded_archiveextract_dirr   tarmemberstotal_filesr   nummember	full_pathr   r   r   
ExtractTar   s$   



r   c                   @   sF   e Zd ZdZdZdZdZdd Zdd	d
ZdddZ			dddZ
dS )r6   zBA class to install Cloud SDK components of different source types.z	.downloadz!https://storage.cloud.google.com/zhttps://storage.googleapis.com/c                 C   s$   || _ || _tj| jtj| _dS )zInitializes an installer for components of different source types.

    Args:
      sdk_root:  str, The path to the root directory of all Cloud SDK files.
      state_directory: str, The path to the directory where the local state is
        stored.
    N)_ComponentInstaller__sdk_root$_ComponentInstaller__state_directoryrt   ru   ry   r6   DOWNLOAD_DIR_NAME'_ComponentInstaller__download_directory)r#   sdk_rootstate_directoryr   r   r   r   %  s
   
zComponentInstaller.__init__Nrq   c                 C   s:   |j }|sdS |jdkr| j|||dS tdj|jd)a  Downloads the given component for whatever source type it has.

    Args:
      component: schemas.Component, The component from the snapshot to install.
      progress_callback: f(float), A function to call with the fraction of
        completeness.
      command_path: the command path to include in the User-Agent header if the
        URL is HTTP

    Returns:
      Optional[str], The path of the downloaded archive, or None if the
        component has no actual sources.

    Raises:
      UnsupportedSourceError: If the component data source is of an unknown
        type.
      URLFetchError: If the URL associated with the component data source
        cannot be fetched.
    Nr   r   rK   z4tar is the only supported source format [{datatype}])datatype)datatype_DownloadTarr-   r    )r#   	componentr   rK   r   r   r   r   Download2  s   
zComponentInstaller.Downloadc                 C   s   |du rg S t || j|dS )ap  Extracts the archive previously downloaded from self.Download().

    Args:
      downloaded_archive: Optional[str], The path to the archive downloaded
        previously.
      progress_callback: f(float), A function to call with the fraction of
        completeness.

    Returns:
      list of str, The files that were installed or [] if nothing was installed.
    N)r   )r   r   )r#   r   r   r   r   r   ExtractU  s   zComponentInstaller.Extractc              
   C   sj   |j j}|sdS td|std|jz
t|| j||dW S  t	t
fy4 } zt|j|d}~ww )a  Download implementation for a component with source in a .tar.gz.

    Downloads the .tar for the component and returns its path.

    Args:
      component: schemas.Component, The component to install.
      progress_callback: f(float), A function to call with the fraction of
        completeness.
      command_path: the command path to include in the User-Agent header if the
        URL is HTTP

    Returns:
      Optional[str], The path of the downloaded archive, or None if the
        component has no actual sources.

    Raises:
      ValueError: If the source URL for the tar file is relative, but there is
        no location information associated with the snapshot we are installing
        from.
      URLFetchError: If there is a problem fetching the component's URL.
    Nz^\w+://zhCannot install component [{0}] from a relative path because the base URL of the snapshot is not defined.r   )r   sourceresearch
ValueErrorr    idr   r   r*   r+   r   )r#   r   r   rK   rD   r$   r   r   r   r   i  s    zComponentInstaller._DownloadTarNrq   N)r   r   r   r   r   r7   r9   r   r   r   r   r   r   r   r   r6     s    

#r6   r   r   )*r   
__future__r   r   r   rt   r   r   r   ri   r   r   r   r   r	   googlecloudsdk.core.consoler
   r4   rG   googlecloudsdk.core.utilr   rw   r   r   r@   r!   r=   r<   r>   r   r   r   r*   r+   r-   rM   r?   ra   r   r   objectr6   r   r   r   r   <module>   sJ   	C

)$