
    6                        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e
j<                        Z G d de      Z G d de      Z  G d de      Z! G d de      Z"d Z#d Z$d Z%	 	 d$d Z&d%d!Z' G d" d#e(      Z)y)&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y)Errorz)Base exception for the installers module.N__name__
__module____qualname____doc__     -lib/googlecloudsdk/core/updater/installers.pyr   r   1       1r   r   c                   "     e Zd ZdZ fdZ xZS )ComponentDownloadFailedErrorzBException for when we cannot download a component for some reason.c                 x    t         t        |   dj                  |      t	        j
                  |      z          y )Nz4The component [{component_id}] failed to download.

)component_id)superr   __init__formatsix	text_type)selfr    e	__class__s      r   r"   z%ComponentDownloadFailedError.__init__9   s;    	
&6@GG% 	H 	'),q)9	:;r   r   r   r   r   r"   __classcell__r(   s   @r   r   r   6   s    J; ;r   r   c                       e Zd ZdZy)URLFetchErrorz)Exception for problems fetching via HTTP.Nr   r   r   r   r-   r-   ?   r   r   r-   c                   "     e Zd ZdZ fdZ xZS )AuthenticationErrorz?Exception for when the resource is protected by authentication.c                 ^    t         t        |   |dz   t        j                  |      z          y )Nz

)r!   r/   r"   r$   r%   )r&   msgr'   r(   s      r   r"   zAuthenticationError.__init__G   s%    	
t-cFlS]]1=M.MNr   r)   r+   s   @r   r/   r/   D   s    GO Or   r/   c                       e Zd ZdZy)UnsupportedSourceErrorzGAn exception when trying to install a component with an unknown source.Nr   r   r   r   r3   r3   K   s    Or   r3   c                    ddl m} | j                  t        j                        r/| j                  t        j                  t        j                  d      } dt        j                  t        j                  |            d}t        }|t        k(  rt        }	 t        | ||      S # t        j                   j"                  $ r?}|j$                  j&                  dk7  s3|j$                  j(                  j                  t        j                        s|	 |j+                  d	      }|j-                  |       n'# t.        j0                  $ r}t3        d
|      d}~ww xY w	 t        | ||      cY d}~S # t        j                   j"                  $ rl}|j$                  j&                  dk7  r|t3        dj5                  t6        j8                  j:                  j<                  j?                               |      d}~ww xY wd}~ww xY 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.credentialsr5   
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corer:   Get)rK   command_pathr5   r7   r8   r'   credss          r   MakeRequestrT   P   s   & 4^^&99:
++(;;(77<C 


y<<\J
K	' '00+G6sGW==				&	& 6zz$AJJNN,E,E))-+gF'''=ekk'!! F  
A1F FF
6gw??(( 6	
		3	&   %f""**..0 % 2346 666sb   B$ $HAG<#D54G<5EEEG<E0*H0G9A'G44G99G<<Hc                  :   d }d }t        j                  ddd|      }	 |j                  t        | ||d      S # t         j                  $ rL}|j
                  d	   r7t        j                  |j
                  d	   d	   |j
                  d	   d   
        d}~ww xY w)zExecutes an HTTP request.c                 r    | t         j                  j                  k(  xr |j                  j                  dk(  S )Ni  )rG   r   rH   rI   rJ   )exc_type	exc_valueunused_tracebackunused_states       r   RetryIfz_RawRequest.<locals>.RetryIf   s4    ++555 2**c13r   c                 .    t        j                  d       y )NzRetrying request...)r   debug)unused_resultrZ   s     r   StatusUpdatez!_RawRequest.<locals>.StatusUpdate   s    II#$r   r      d   )max_retrialsexponential_sleep_multiplier	jitter_msstatus_update_funci  )should_retry_ifsleep_msr6   )tbN)r   RetryerRetryOnException!_ExecuteRequestAndRaiseExceptionsRetryExceptionlast_resultr   reraise)argskwargsr[   r_   retryerr'   s         r   rF   rF      s    3% MM#$%	''

##) $   
		 
}}Qq)!,q1A!1DE		
s   ; BABBc                     ddl m} |j                         }| j                  d      r$|j	                  dt        j                                |j                  | ||d      }|j                          |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   )rG   zfile://T)r7   r8   stream)	googlecloudsdk.corerG   
GetSessionr<   mountr   LocalFileAdaptergetraise_for_status)rK   r7   r8   core_requestsrequests_sessionrI   s         r   rk   rk      sk     <"--/^^I9&8&I&I&KL!!	7GD " :(
	/r   c                    |xs t         j                  }t        j                  j	                  |      st        j                  |       t        j                  j                  |t        j                  j                  |             }t        j                  j	                  |      rt        j                  |       	 t        | |      }t        j                  |      5 }d}t        |j                        }|j                  t              D ],  }	|j!                  |	       |t        |	      z  } |||z         . 	 ddd        |d       |S # 1 sw Y   xY w# t"        j$                  j&                  t(        f$ r}
t+        |
      d}
~
ww xY 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_sizeNr6   )r   DefaultProgressBarCallbackospathexists
file_utilsMakeDirjoinbasenameremoverT   BinaryFileWriterlencontentiter_contentWRITE_BUFFER_SIZEwriterG   r   rH   OSErrorr-   )rK   download_dirprogress_callbackrR   download_file_pathrI   fptotal_written
total_sizechunkr'   s              r   DownloadTarr      s9   $ (P:+P+P		%|$ww||L"''2B2B32GHWW^^&'II !3-H		$	$%7	8Bmx''(j((4E(F%
U#-*45 G 
9 a 
 
9	8 


'
'	1 

s1   ;!E AE:E EE #F;FFc                 ~   |xs t         j                  }t        j                  j	                  |      st        j                  |       t        j                  |       5 }|j                         }t        |      }g }t        |d      D ]  \  }}|j                  |j                         r|j                  dz   n|j                         |j                  ||       t        j                  j!                  ||j                        }	t        j                  j#                  |	      rYt        j$                  |	t        j&                        s5t        j(                  |	t*        j,                  t*        j.                  z          |||z           |d       ddd       t        j0                  |        S # 1 sw Y    xY w)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.
  )namer6   )start/N)r   r~   r   r   r   r   r   tarfileopen
getmembersr   	enumerateappendisdirr   extractr   isfileaccessW_OKchmodstatS_IWUSRS_IREADr   )
downloaded_archiveextract_dirr   tarmemberstotal_filesr   nummember	full_paths
             r   
ExtractTarr      s/    (P:+P+P		${#||+,nnGg,KE 2Vll6;;$FKKH	kk&+&'',,{FKK8i			"299Y+H
DLL56k)* 3 a -  ))	,# -,s   D5F33F<c                   >    e Zd ZdZdZdZdZd Zd
dZddZ		 	 d
d	Z
y)r=   zBA class to install Cloud SDK components of different source types.z	.downloadz!https://storage.cloud.google.com/zhttps://storage.googleapis.com/c                     || _         || _        t        j                  j	                  | j                  t
        j                        | _        y)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_directoryr   r   r   r=   DOWNLOAD_DIR_NAME'_ComponentInstaller__download_directory)r&   sdk_rootstate_directorys      r   r"   zComponentInstaller.__init__%  s;     DO,D " 2 D D!FDr   Nc                     |j                   }|sy|j                  dk(  r| j                  |||      S t        dj	                  |j                              )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   rR   z4tar is the only supported source format [{datatype}])datatype)datatype_DownloadTarr3   r#   )r&   	componentr   rR   r   s        r   DownloadzComponentInstaller.Download2  sj    ( >>DyyE
'8#  % % !>EEYY 	F 	 ! !r   c                 :    |g S t        || j                  |      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.
    )r   )r   r   )r&   r   r   s      r   ExtractzComponentInstaller.ExtractU  s(     !iDOO+- -r   c                 6   |j                   j                  }|syt        j                  d|      s$t	        dj                  |j                              	 t        || j                  ||      S # t        t        f$ r}t        |j                  |      d}~ww xY 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   rR   rK   r'   s         r   r   zComponentInstaller._DownloadTari  s    . ..

C99Z% Ny||,. .:
t((<M#% % ./ :(q99:s   A. .B=BBNunknownN)r   r   r   r   r   r>   r@   r"   r   r   r   r   r   r   r=   r=     s8    J!
 ; 5.F!!F-( 7; )&:r   r=   r   r   )*r   
__future__r   r   r   r   r   r   r   rt   r   r   r   r	   r
   googlecloudsdk.core.consoler   r;   rN   googlecloudsdk.core.utilr   r   r   r   rG   r$   rD   rC   rE   r   r   r   r-   r/   r3   rT   rF   rk   r   r   objectr=   r   r   r   <module>r      s     C &  ' 	 	   * 2 # * ) 2 J 8 2 *  
 /  !  J 
;5 ;E 
O% OU 
@6F
:4 6:&&R!Hx: x:r   