
    %              
          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	Z	ddl
mZ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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' g dgg dgddgddgddgdZ(de)de*fd Z+d!e)d"e)dejX                  fd#Z-de)ddfd$Z.	 d6d!e)d"ee)   ddfd%Z/d&e)d'e)ddfd(Z0	 	 d7d)e)d*e)d"ee)   de)fd+Z1d,ejd                  de)fd-Z3d.e)d,ejd                  d/e)dejh                  fd0Z5d1ejl                  dejn                  fd2Z8	 d6d.e)d3e)d4eee)e)f      ddfd5Z9y)8z4Version-agnostic utilities for function source code.    )absolute_import)division)unicode_literalsN)DictOptional)
exceptions)http_wrapper)transfer)util)storage_api)storage_util)gcloudignore)log)	resources)
transports)archive)files)http_client)rangezgo.modzpackage.jsonz	index.phpzcomposer.jsonzmain.pyzrequirements.txtzapp.rbGemfile)dotnetgojavanodejsphppythonruby	directoryreturnc                 R    t        j                  | t         j                  dgz         S )Nnode_modules)r   AnyFileOrDirExists	GIT_FILESr   s    7lib/googlecloudsdk/command_lib/functions/source_util.py_GcloudIgnoreCreationPredicater&   >   s(    		(	(''>*::
     pathignore_filec                 b    t         j                  dz   }t        j                  | |t        |      S )Nz
node_modules
)default_ignore_file gcloud_ignore_creation_predicater)   )r   DEFAULT_IGNORE_FILEGetFileChooserForDirr&   )r(   r)   r+   s      r%   _GetChooserr/   D   s3    $88;MM		*	*
-'E	
 r'   c                     t         j                  j                  |       st        j                  d      t         j                  j                  |       st        j                  d      y)zValidates that the given directory exists.

  Args:
    directory: a local path to the directory provided by user.

  Returns:
    The argument provided, if found valid.
  Raises:
    SourceArgumentError: If the user provided an invalid directory.
  z!Provided directory does not existz+Provided path does not point to a directoryN)osr(   existsr   SourceArgumentErrorisdirr$   s    r%   _ValidateDirectoryExistsOrRaiser5   O   sQ     
		"

(
()L
MM	y	!

(
(5  
"r'   c                 n   t        | |      }|j                  }	 t        j                  | |      }d}|dz  }||kD  rBt        j                  t        j                  |      dz   t        j                  |      dz         y# t        $ r+}t        j                  dj                  | |            d}~ww xY w)z'Validate size of unpacked source files.	predicatezError building source archive from path [{path}]. Could not validate source files: [{error}]. Please ensure that path [{path}] contains function code or specify another directory with --source)r(   errorNi   i   B)r/   
IsIncluded
file_utilsGetTreeSizeBytesOSErrorr   FunctionsErrorformatOversizedDeploymentErrorsix	text_type)r(   r)   chooserr8   size_besize_limit_mbsize_limit_bs           r%   _ValidateUnpackedSourceSizerI   b   s     k*'  )((CF -&,l

-
-f#S]]<%@3%F   
 

#
#	2 39&d!&2L	 s   B   	B4	&B//B4sourceruntimec                     t        |        t        j                  dd|      }t        j                  |       }t
        |   D ]"  }||vst        j                  d| d| d       y)zDValidates the given source directory has the required runtime files.z[0-9] z.Provided source directory does not have file [z] which is required for [z$]. Did you specify the right source?N)r5   resubr1   listdir_REQUIRED_SOURCE_FILESr   r3   )rJ   rK   versionless_runtimer   fs        r%   (ValidateDirectoryHasRequiredRuntimeFilesrT   y   so    !&)xW5
**V
%!"56a~**:1# >")#GI  7r'   zip_dirsource_pathc           	      2   t        |       |rat        j                  j                  t        j                  j	                  ||            s$t        j                  dj                  |            |rt        ||       t        j                  j	                  | d      }	 t        ||      }|j                  }t        j                  |||       |S # t        $ r=}t        j                  dj                  |t        j                   |                  d}~ww xY w)a  Prepare zip file with source of the function to upload.

  Args:
    zip_dir: str, directory in which zip file will be located. Name of the file
      will be `fun.zip`.
    source_path: str, directory containing the sources to be zipped.
    ignore_file: custom ignore_file name. Override .gcloudignore file to
      customize files to be skipped.
    enforce_size_limit: if set, enforces that the unpacked source size is less
      than or equal to 512 MB.

  Returns:
    Path to the zip file.
  Raises:
    FunctionsError
  z4File {0} referenced by --ignore-file does not exist.zfun.zipr7   zHError creating a ZIP archive with the source code for directory {0}: {1}N)r5   r1   r(   r2   joinr   IgnoreFileNotFoundErrorr@   rI   r/   r;   r   MakeZipFromDir
ValueErrorr?   rB   rC   )rU   rV   r)   enforce_size_limitzip_file_namerD   r8   rF   s           r%   CreateSourcesZipFiler^      s    , "+.[+(NO

,
,>EE	
 
 [9'',,w	2-+{3G""I=+K 
 
 

#
#	!!'S]]15E!F s   0C 	D8DDfunction_refc                     | j                   }| j                  }dj                  d t        d      D              }dj	                  |||      S )NrM   c              3   b   K   | ]'  }t        j                  t        j                         ) y wN)randomchoicestringascii_lowercase).0_s     r%   	<genexpr>z-_GenerateRemoteZipFileName.<locals>.<genexpr>   s      L)Q6==!7!78)s   -/   z{0}-{1}-{2}.zip)locationsIdfunctionsIdrX   r   r@   )r_   regionnamesuffixs       r%   _GenerateRemoteZipFileNamerp      sE    ##&		!	!$77L%)LL&		!	!&$	77r'   
source_zipstage_bucketc                 Z   t        |      }t        j                  j                  |      }t        j                  j                  ||      }	 t        j                         j                  | |       |S # t        j                  $ r% t        j                  dj                  |            w xY w)a>  Uploads the given source ZIP file to the provided staging bucket.

  Args:
    source_zip: the source ZIP file to upload.
    function_ref: the function resource reference.
    stage_bucket: the name of GCS bucket to stage the files to.

  Returns:
    dest_object: a reference to the uploaded Cloud Storage object.
  z;Failed to upload the function source code to the bucket {0})rp   r   BucketReferenceFromArgumentObjectReferenceFromBucketRefr   StorageClientCopyFileToGCScalliope_exceptionsBadFileExceptionr   SourceUploadErrorr@   )rq   r_   rr   zip_file
bucket_refdest_objects         r%   UploadToStageBucketr      s     (5(++88F*,,:::xP+--j+F 
 
	-	- 

&
&ELL	
 s   $A2 28B*responsec                     | j                   t        j                  k(  rt        j                  j                  |       t        j                  |       S rb   )status_coder   	FORBIDDENhttp_exceptionsHttpForbiddenErrorFromResponser	   CheckResponse)r   s    r%   &_UploadFileToGeneratedUrlCheckResponser      s@     [222

,
,
9
9(
CC		#	#H	--r'   urlextra_headersc                 |   |xs i }t         j                  j                  | d      dt        j                  ddffd}	 t        j
                  |dddi|	      }j                  j                         |_        t        j                  t        j                         ||t        j                  
      }j                  j                          |j                  dz  dk7  r;t!        j"                  dj%                  ||j                  |j&                              y# j                  j                          w xY w)zUpload the given source ZIP file to provided generated URL.

  Args:
    source_zip: the source ZIP file to upload.
    url: the signed Cloud Storage URL to upload to.
    extra_headers: extra headers to attach to the request.
  zapplication/zip)	mime_type
retry_argsr   Nc                 V   t        | j                  t        j                        rst	        j
                  d       t        j                  | j                         t        j                  t        j                  | j                  | j                               y j                  |        y )Nz5Caught delayed permission propagation error, retrying)max_wait)
isinstanceexcr   r   r   debugr	   RebuildHttpConnectionshttptimesleep	http_utilCalculateWaitForRetrynum_retriesmax_retry_wait
retry_func)r   uploads    r%   _UploadRetryFuncz.UploadToGeneratedUrl.<locals>._UploadRetryFunc   sq    *../"D"DE	iiGH))*//:
jj

)
)$$z/H/H 
#r'   PUTzcontent-type)http_methodheaders)r   check_response_funcretriesd      zYFailed to upload the function source code to signed url: {url}. Status: [{code}:{detail}])r   codedetail)r
   UploadFromFiler	   ExceptionRetryArgsRequeststreamreadbodyMakeRequestr   GetApitoolsTransportr   r   closer   r   r|   r@   content)rq   r   r   r   upload_requestr   r   s         @r%   UploadToGeneratedUrlr      s(     %2-??##J:K#L&
$<#B#B 
$t 
$!))!2DmDN
 !--,,.N'''')#B""H MMS A%

&
&	$$*F(..x7G7G %+ %
  & MMs   A5D D;rb   )NF):__doc__
__future__r   r   r   r1   rc   rN   re   r   typingr   r   apitools.base.pyr   r   r	   r
   r   r   googlecloudsdk.api_lib.storager   r   googlecloudsdk.callioperz   $googlecloudsdk.command_lib.functionsgooglecloudsdk.command_lib.utilr   googlecloudsdk.corer   r   r   googlecloudsdk.core.utilr   r   r<   rB   	six.movesr   r   rQ   strboolr&   FileChooserr/   r5   rI   rT   r^   Resourcerp   rv   r   Responser   r   r    r'   r%   <module>r      s   ; &  ' 	  	   ! : ) % . 6 7 E ; 8 # ) * , 8 
 !  *),-y! c d c  0H0H s t ( -1
$SM	.S 3 4 " "&	))) #)
 	)X8Y-?-? 8C 8#,#5#5EH!!6.##.. JN000.6tCH~.F0	0r'   