
    CY                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKJ	r
  SSKJr  SSKJr  SS	KJr  SSKJ	r  SSKJ	r	  SS
KJr  SSKJ	r  SSKJr  SSKJr  SSKJr  SSKJr  SSKr " S S\R:                  5      r " S S\5      r " S S\5      r " S S\5      r  " S S\5      r!S r"S r# " S S\$5      r%g)a  Utilities for interacting with Google Cloud Storage.

This makes use of both the Cloud Storage API as well as the gsutil command-line
tool. We use the command-line tool for syncing the contents of buckets as well
as listing the contents. We use the API for checking ACLs.
    )absolute_import)division)unicode_literalsN)
exceptions)
list_pager)transfer)storage_util)iam_util)log)
properties)
transports)scaled_integerc                       \ rS rSrSrSrg)Error0   z&Base exception for storage API module. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       1lib/googlecloudsdk/api_lib/storage/storage_api.pyr   r   0   s    .r   r   c                       \ rS rSrSrSrg)BucketNotFoundError4   z6Error raised when the bucket specified does not exist.r   Nr   r   r   r   r   r   4   s    >r   r   c                       \ rS rSrSrSrg)ListBucketError8   zFError raised when there are problems listing the contents of a bucket.r   Nr   r   r   r   r    r    8   s    Nr   r    c                       \ rS rSrSrSrg)UploadError<   z5Error raised when there are problems uploading files.r   Nr   r   r   r   r#   r#   <   s    =r   r#   c                       \ rS rSrSrSrg)BucketInWrongProjectError@   a<  Error raised when a bucket exists in a project the user doesn't own.

Specifically, this applies when a command creates a bucket if it doesn't
exist, or returns the existing bucket otherwise. If the bucket exists but is
owned by a different project, it could belong to a malicious user squatting on
the bucket name.
r   Nr   r   r   r   r&   r&   @   s    r   r&   c                 H    [         R                  " U 5      u  pU=(       d    S$ )Nzapplication/octet-stream)	mimetypes
guess_type)
local_path	mime_type_s      r   _GetMimetyper.   J   s     %%j1,)		000r   c                      [         R                  R                  [        R                  " U 5      5      $ ! [         R
                   a&    [        R                  " SR                  U 5      5      ef = f)Nz![{0}] not found or not accessible)	ospathgetsizesix
ensure_strerrorr   BadFileExceptionformat)r+   s    r   _GetFileSizer8   O   sV    ;77??3>>*566	 ;

%
%&I'-vj'9; ;;s	   25 :A/c                       \ rS rSrSrSS jrS rS rS rS r	S	 r
S
 rSS jrS rSS jr       SS jrS rSS jrS rS rS rS rS rS rSrg)StorageClientW   z$Client for Google Cloud Storage API.Nc                     U=(       d    [         R                  " 5       U l        U=(       d    [         R                  " 5       U l        g N)r	   	GetClientclientGetMessagesmessages)selfr?   rA   s      r   __init__StorageClient.__init__Z   s,    4L224DK: 8 8 :DMr   c                     Sn[         R                  " [        R                  R                  R
                  R                  5       5      nUS:X  a  SnU$ X!-  S:w  a	  X!X!-  -
  -  nU$ )zReturns the property defined chunksize corrected for server granularity.

Chunk size for GCS must be a multiple of 256 KiB. This functions rounds up
the property defined chunk size to the nearest chunk size interval.
i   r   N)r   ParseIntegerr   VALUESstorageupload_chunk_sizeGet)rB   gcs_chunk_granularity	chunksizes      r   _GetChunkSizeStorageClient._GetChunkSize^   so     '++!!33779;IA~i  
	*a	/I,MNNir   c              #      #    U R                   R                  US9n[        R                  " U R                  R
                  USS9 H  nUv   M	     g7f)z3List the buckets associated with the given project.)projectN
batch_size)rA   StorageBucketsListRequestr   YieldFromListr?   buckets)rB   rP   requestbs       r   ListBucketsStorageClient.ListBucketsm   sI     mm55g5FG%%dkk&9&9&-$@g@s   AAc           	          U R                   R                  R                  U R                  R	                  UR
                  UR                  UR
                  UR                  S95      $ )zCopy one GCS object to another.

Args:
  src: Resource, the storage object resource to be copied from.
  dst: Resource, the storage object resource to be copied to.

Returns:
  Object, the storage object that was copied to.
)sourceBucketsourceObjectdestinationBucketdestinationObject)r?   objectsCopyrA   StorageObjectsCopyRequestbucketobject)rB   srcdsts      r   r`   StorageClient.Copyt   sT     ;;##//!jj!jj	 	0 	
 r   c           
      .   Sn U R                   R                  R                  U R                  R	                  UR
                  UR                  UR
                  UR                  US95      nUR                  (       a  UR                  $ UR                  nM  )ai  Rewrite one GCS object to another.

This method has the same result as the Copy method, but can handle moving
large objects that may potentially timeout a Copy request.

Args:
  src: Resource, the storage object resource to be copied from.
  dst: Resource, the storage object resource to be copied to.

Returns:
  Object, the storage object that was copied to.
N)r[   r\   r]   r^   rewriteToken)
r?   r_   RewriterA   StorageObjectsRewriteRequestrb   rc   doneresourcerh   )rB   rd   re   rewrite_tokenresps        r   ri   StorageClient.Rewrite   s     M
[[  ((
--
4
4:::: #

 #

( 5 d 
}}''m r   c                     U R                   R                  R                  U R                  R	                  UR
                  UR                  S95      $ )zGets an object from the given Cloud Storage bucket.

Args:
  object_ref: storage_util.ObjectReference, The user-specified bucket to
    download from.

Returns:
  Object: a StorageV1 Object message with details about the object.
rb   rc   )r?   r_   rJ   rA   StorageObjectsGetRequestrb   rc   rB   
object_refs     r   	GetObjectStorageClient.GetObject   sJ     ;;""4==#I#I     $J $" # #r   c                    [        U5      nU R                  R                  US9n[        U5      nU R	                  5       n[
        R                  R                  [        R                  " U5      XVS9nU R                  R                  UR                  UR                  US9nSR                  UR                  UR                  S9n	[        R                  " SR                  UU	S95         U R                   R"                  R%                  XS9n
 UR8                  R;                  5         U
R<                  U:w  aU  [        R.                  " SR                  U
R<                  U5      5        [>        R@                  " SR                  U5      5      eU
$ ! [&        R(                   a#    [+        S	R                  UR                  S
95      e[&        R,                   at  n[        R.                  " SR                  X[0        R2                  " U5      S95        [5        SR                  UR6                  X[0        R2                  " USS9S95      eSnAff = f! UR8                  R;                  5         f = f)a  Upload a file to the GCS results bucket using the storage API.

Args:
  local_path: str, the path of the file to upload. File must be on the local
    filesystem.
  target_obj_ref: storage_util.ObjectReference, the path of the file on GCS.

Returns:
  Object, the storage object that was copied to.

Raises:
  BucketNotFoundError if the user-specified bucket does not exist.
  UploadError if the file upload is not successful.
  exceptions.BadFileException if the uploaded file size does not match the
      size of the local file.
)size)r,   rL   )rb   namerc   z{bucket}/{target_path})rb   target_pathz#Uploading [{local_file}] to [{gcs}]
local_filegcs)uploadz8Could not upload file: [{bucket}] bucket does not exist.rb   z4Could not upload file [{local_file}] to [{gcs}]: {e})r|   r}   ezA{code} Could not upload file [{local_file}] to [{gcs}]: {message}{status_message}error_format)coder|   r}   messageNz6Response size: {0} bytes, but local file is {1} bytes.zYCloud storage upload failure. Uploaded file does not match local file: {0}. Please retry.)!r8   rA   Objectr.   rM   r   UploadFromFiler3   r4   StorageObjectsInsertRequestrb   rc   r7   r   infor?   r_   Insertapi_exceptionsHttpNotFoundErrorr   	HttpErrordebughttp_excHttpExceptionr#   status_codestreamcloserx   r   r6   )rB   r+   target_obj_ref	file_sizesrc_objr,   rL   r~   
insert_reqgsc_pathresponseerrs               r   CopyFileToGCSStorageClient.CopyFileToGCS   s:   " Z(Imm""	"2GZ(I""$I__%%z"i & NF::$$"" ; J
 (..$$.2G2G / H HH299Z>F : H I$$++J+Fh$ mm}}	!	iiHOO
--$ %''%%+VJ%79 9 O3 ++ 1
D6..6/1 1 ## >	iiFMM""3' N ) * 
M6s:"00(:<  => >	> mms&   *#F A	IA/III I+c           
         U R                  5       n[        R                  R                  X$US9n[        R
                  " SS9Ul        U R                  R                  UR                  UR                  S9nSR                  UR                  UR                  S9n[        R                  " SR                  X'S95         U R                  R                  R!                  XeS	9  U R                  R                  R!                  U5      n UR.                  R1                  5         [3        U5      n
UR4                  U
:w  aT  [        R6                  " SR                  XR4                  5      5        [&        R(                  " SR                  U5      5      eg! ["        R$                   a=  n	[&        R(                  " S
R                  X'[*        R,                  " U	5      S95      eSn	A	ff = f! UR.                  R1                  5         f = f)a  Download a file from the given Cloud Storage bucket.

Args:
  source_obj_ref: storage_util.ObjectReference, the path of the file on GCS
    to download.
  local_path: str, the path of the file to download to. Path must be on the
    local filesystem.
  overwrite: bool, whether or not to overwrite local_path if it already
    exists.

Raises:
  BadFileException if the file download is not successful.
)rL   	overwriteNresponse_encodingrq   z{bucket}/{object_path})rb   object_pathz%Downloading [{gcs}] to [{local_file}]r{   downloadz=Could not copy [{gcs}] to [{local_file}]. Please retry: {err})r|   r}   r   z9Download size: {0} bytes, but expected size is {1} bytes.zhCloud Storage download failure. Downloaded file [{0}] does not match Cloud Storage object. Please retry.)rM   r   Downloadr   r   GetApitoolsTransport
bytes_httprA   rr   rb   rc   r7   r   r   r?   r_   rJ   r   r   r   r6   r   r   r   r   r8   rx   r   )rB   source_obj_refr+   r   rL   r   get_reqr   r   r   r   s              r   CopyFileFromGCSStorageClient.CopyFileFromGCS   s    ""$I  ))9 * >H$99 Hmm44$$$$ 5 &G (..$$.2G2G / H HH4;; < - .
kkg9 $$((1h ooZ(I}}	!	ii 	==9;''66<fZ6HJ J " ## 4''
I6Z,,S1  34 44 oos%   >AF G"%8GG""G% %Hc           	      X   [         R                  " 5       nU R                  5       n[        R                  R                  X#S9n[        R                  " SS9Ul        U R                  R                  UR                  UR                  S9n[        R                  " SU5         U R                  R                   R#                  XTS9  UR3                  S	5        U$ ! [$        R&                   a=  n[(        R*                  " SR-                  U[.        R0                  " U5      S95      eSnAff = f)
zRead a file from the given Cloud Storage bucket.

Args:
  object_ref: storage_util.ObjectReference, The object to read from.

Raises:
  BadFileException if the file read is not successful.

Returns:
  file-like object containing the data read.
)rL   Nr   rq   zReading [%s]r   z/Could not read [{object_}]. Please retry: {err})object_r   r   )ioBytesIOrM   r   r   
FromStreamr   r   r   rA   rr   rb   rc   r   r   r?   r_   rJ   r   r   r   r6   r7   r   r   seek)rB   rt   datarL   r   r   r   s          r   
ReadObjectStorageClient.ReadObject"  s    ::<D""$I  ++D+FH$99 Hmm44     5 "G HH^Z(D
kkg9 	IIaLK ## D''
;
B
B h&<&<S&A C CD DDs   "#C D),8D$$D)c                      U R                   R                  R                  U R                  R	                  UUS95      $ ! [
        R                   a    [        SR                  U5      5      ef = f)a_  Gets a bucket from GCS, if it exists.

Args:
  bucket: str, The bucket name.
  projection: int, The fields to get as part of this request. This is
    optional and defaults to whatever the server provides.

Returns:
  Bucket: a StorageV1 Bucket message with details about the bucket.

Raises:
  BucketNotFoundError if the given bucket does not exist.
)rb   
projectionzBucket [{}] does not exist.)	r?   rU   rJ   rA   StorageBucketsGetRequestr   r   r   r7   )rB   rb   r   s      r   	GetBucketStorageClient.GetBucketB  sr    N[[  $$T]]%K%K &L & 	 	 ++ N = D DV LMMNs	   <? /A.c	           	      x  ^ U=(       d1    [         R                  R                  R                  R	                  SS9n U R
                  R                  R	                  U R                  R                  TS95        U(       d  gU R                  R1                  UTS9nU R
                  R                  R3                  U5      n[5        U4S jUR6                   5       5      (       d  [9        SR;                  T5      5      eg! [        R                   Ga    U R                  R                  UU R                  R                  TUS9S9n	U R                  R                  R                  5       n
Ub2  U R                  R                  R                  R                  US9U
l        Ub  U(       a  SU
l        OS	U
l        XR                  R                  R                  5       :w  a  U
U	R"                  l        Ub  XR"                  l        Ub2  U R                  R                  R)                  US
9U	R"                  l         U R
                  R                  R-                  U	5         g! [        R.                   aA    U R
                  R                  R	                  U R                  R                  TS95          GN;f = ff = f)a  Create a bucket if it does not already exist.

If it already exists and is accessible by the current user, this method
returns.

Args:
  bucket: str, The storage bucket to be created.
  project: str, The project to use for the API request. If None, current
    Cloud SDK project is used.
  location: str, The bucket location/region.
  check_ownership: bool, Whether to check that the resulting bucket belongs
    to the given project. DO NOT SET THIS TO FALSE if the bucket name can be
    guessed and claimed ahead of time by another user as it enables a name
    squatting exploit.
  enable_uniform_level_access: bool, to enable uniform bucket level access.
    If None, the uniformBucketLevelAccess field will be set to None in the
    bucket creation request, which means that it will use the default
    values.
  enable_public_access_prevention: bool, to enable public access prevention.
    If None, the publicAccessPrevention field will be set to None in the
    bucket creation request, which means that it will use the default
    values.
  soft_delete_duration: int, the soft delete duration in seconds.
  cors: list, A list of CorsValueListEntry objects. The bucket's
    Cross-Origin Resource Sharing (CORS) configuration. If None, no CORS
    configuration will be set.

Raises:
  api_exceptions.HttpError: If the bucket is not able to be created or is
    not accessible due to permissions.
  BucketInWrongProjectError: If the bucket already exists in a different
    project. This could belong to a malicious user squatting on the bucket
    name.
T)requiredr   )ry   location)rP   rb   N)enabledenforced	inherited)retentionDurationSeconds)rP   prefixc              3   @   >#    U  H  oR                   T:H  v   M     g 7fr=   )id).0rW   rb   s     r   	<genexpr>8StorageClient.CreateBucketIfNotExists.<locals>.<genexpr>  s     9'8!ttv~'8s   zEUnable to create bucket [{}] as it already exists in another project.)r   rG   corerP   rJ   r?   rU   rA   r   r   r   StorageBucketsInsertRequestBucketIamConfigurationValueUniformBucketLevelAccessValueuniformBucketLevelAccesspublicAccessPreventionrb   iamConfigurationcorsSoftDeletePolicyValuesoftDeletePolicyr   HttpConflictErrorrS   Listanyitemsr&   r7   )rB   rb   rP   r   check_ownershipenable_uniform_level_accessenable_public_access_preventionsoft_delete_durationr   storage_buckets_insert_requestiam_configurationbucket_list_reqbucket_lists    `           r   CreateBucketIfNotExists%StorageClient.CreateBucketIfNotExistsY  s   Z J**//77;;T;JG-
kkdmmDD E  	\  mm== > (O++%%**?;K9{'8'8999%VF^% % :e ++ ) --
3
3]]))v3; * = 4 > %
 --..DDF	$	059]]5I5I5_5_5}5}/ 6~ 6
2 
)	4*5?

25@

2	mm22HHJ	J 	'--> 
	59--2		)MM  66)= 7  	'-->
""#AB 	 --  	 F F !G !
 	 		A)s+   <C? ?D9J99%I  AJ50J94J55J9c                 N   [         R                  R                  U5      nUR                  nU R                  R                  US9n U R                  R                  R                  U5      nUR                  $ ! [        R                   a    [        SR                  US95      ef = f)zReturns the location of the bucket for a file.

Args:
  object_path: str, the path of the file in GCS.

Returns:
  str, bucket location (region) for given object in GCS.

Raises:
  BucketNotFoundError if bucket from the object path is not found.
r   zBCould not get location for file: [{bucket}] bucket does not exist.)r	   ObjectReferenceFromUrlrb   rA   r   r?   rU   rJ   r   r   r   r   r7   )rB   r   object_referencebucket_nameget_bucket_reqsource_buckets         r   GetBucketLocationForFile&StorageClient.GetBucketLocationForFile  s     $33;;KH"))K]];; < N'kk))--n=m###++ '
N66%' ''s   0A7 7-B$c              #   h  #    U R                   R                  UR                  US9n [        R                  " U R
                  R                  USS9 H  nUv   M	     g! [        R                   a#    [        SR                  UR                  S95      e[        R                   a  n[        R                  " SR                  UR                  [        R                  " U5      S95        [!        SR                  UR"                  UR                  [        R                  " US	S
9S95      eSnAff = f7f)aO  Lists the contents of a cloud storage bucket.

Args:
  bucket_ref: The reference to the bucket.
  prefix: str, Filter results to those whose names begin with this prefix.

Yields:
  Object messages.

Raises:
  BucketNotFoundError if the user-specified bucket does not exist.
  ListBucketError if there was an error listing the bucket.
)rb   r   NrQ   z8Could not list bucket: [{bucket}] bucket does not exist.r   z%Could not list bucket [{bucket}]: {e})rb   r   z2{code} Could not list bucket [{bucket}]: {message}r   r   )r   rb   r   )rA   StorageObjectsListRequestrb   r   rT   r?   r_   r   r   r   r7   r   r   r   r   r   r    r   )rB   
bucket_refr   rV   objr   s         r   
ListBucketStorageClient.ListBucket  s     mm55   6 1G<))$++*=*=*1dD#	D ++ -
D6**6+- - ## <	ii7>>""h&<&<Q&? ? A B
>6q}}Z->->"00&8:  ;< <<s*   %D25A D2A	D/'BD**D//D2c                     U R                   R                  R                  U R                  R	                  UR
                  UR                  S95        g)zfDelete the specified object.

Args:
  object_ref: storage_util.ObjectReference, The object to delete.
rq   N)r?   r_   DeleterA   StorageObjectsDeleteRequestrb   rc   rs   s     r   DeleteObjectStorageClient.DeleteObject  sE     	KKt}}HH      I  " #r   c                     U R                   R                  R                  U R                  R	                  UR
                  S95        g)zkDelete the specified bucket.

Args:
  bucket_ref: storage_util.BucketReference to the bucket of the object
r   N)r?   rU   r   rA   StorageBucketsDeleteRequestrb   rB   r   s     r   DeleteBucketStorageClient.DeleteBucket  s8     	KK119J9J1KMr   c                     U R                   R                  R                  U R                  R	                  UR
                  [        R                  S95      $ )zFetch the IAM Policy attached to the specified bucket.

Args:
  bucket_ref: storage_util.BucketReference to the bucket with the policy.

Returns:
  The bucket's IAM Policy.
)rb   optionsRequestedPolicyVersion)r?   rU   GetIamPolicyrA   !StorageBucketsGetIamPolicyRequestrb   r
   !MAX_LIBRARY_IAM_SUPPORTED_VERSIONr   s     r   r   StorageClient.GetIamPolicy  sJ     ;;++77$$*2.. 	8 	01 1r   c                     U R                   R                  R                  U R                  R	                  UR
                  US95      $ )a  Set the IAM Policy attached to the specified bucket to the given policy.

If 'policy' has no etag specified, this will BLINDLY OVERWRITE the IAM
policy!

Args:
  bucket_ref: storage_util.BucketReference to the bucket.
  policy: The new IAM Policy.

Returns:
  The new IAM Policy.
)rb   policy)r?   rU   SetIamPolicyrA   !StorageBucketsSetIamPolicyRequestrb   )rB   r   r   s      r   r  StorageClient.SetIamPolicy(  sC     ;;++77$$V 	8 	56 6r   c                 *    U R                  XU4/5      $ )aC  Add an IAM policy binding on the specified bucket.

Does an atomic Read-Modify-Write, adding the member to the role.

Args:
  bucket_ref: storage_util.BucketReference to the bucket with the policy.
  member: Principal to add to the policy binding.
  role: Role to add to the policy binding.

Returns:
  The new IAM Policy.
)AddIamPolicyBindings)rB   r   memberroles       r   AddIamPolicyBinding!StorageClient.AddIamPolicyBinding9  s     $$Z4.1ABBr   c                    U R                  U5      n[        R                  Ul        SnU HD  u  pV[        R                  " U R
                  R                  R                  X5U5      (       d  MB  SnMF     U(       a  U R                  X5      $ U$ )a(  Add IAM policy bindings on the specified bucket.

Does an atomic Read-Modify-Write, adding the member to the role.

Args:
  bucket_ref: storage_util.BucketReference to the bucket with the policy.
  member_roles: List of 2-tuples in the form [(member, role), ...].

Returns:
  The new IAM Policy.
FT)	r   r
   r   versionAddBindingToIamPolicyrA   PolicyBindingsValueListEntryr  )rB   r   member_rolesr   policy_was_updatedr  r  s          r   r  "StorageClient.AddIamPolicyBindingsH  s     z*F??FN$		'	'
--


5
5vt
M 
M! %
 z22Mr   )r?   rA   )NN)Fr=   )NNTNNNN)r   r   r   r   r   rC   rM   rX   r`   ri   ru   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r   r   r   r:   r:   W   s    ,;$(6#>@1Jf@N4 "&&*n%`'4!<F#M16"Cr   r:   )&r   
__future__r   r   r   r   r)   r0   apitools.base.pyr   r   r   r   googlecloudsdk.api_lib.storager	   googlecloudsdk.api_lib.utilr   googlecloudsdk.calliopegooglecloudsdk.command_lib.iamr
   googlecloudsdk.corecore_excr   r   googlecloudsdk.core.credentialsr   googlecloudsdk.core.utilr   r3   r   r   r    r#   r&   r.   r8   rc   r:   r   r   r   <module>r     s     '  ' 	  	 9 ' % 7 > . 3 6 # * 6 3 
/HNN /?% ?Oe O>% > 1
;IF Ir   