Index: tools/telemetry/third_party/gsutilz/gslib/translation_helper.py |
diff --git a/tools/telemetry/third_party/gsutilz/gslib/translation_helper.py b/tools/telemetry/third_party/gsutilz/gslib/translation_helper.py |
index 91adc83a3720d82b94a2ffc723b35aed49587708..a1b06f7455770f0b186cc5c438bf06ed1539f84a 100644 |
--- a/tools/telemetry/third_party/gsutilz/gslib/translation_helper.py |
+++ b/tools/telemetry/third_party/gsutilz/gslib/translation_helper.py |
@@ -36,6 +36,7 @@ from boto.gs.acl import USER_BY_EMAIL |
from boto.gs.acl import USER_BY_ID |
from gslib.cloud_api import ArgumentException |
+from gslib.cloud_api import BucketNotFoundException |
from gslib.cloud_api import NotFoundException |
from gslib.cloud_api import Preconditions |
from gslib.exception import CommandException |
@@ -74,7 +75,7 @@ DEFAULT_CONTENT_TYPE = 'application/octet-stream' |
# Because CORS is just a list in apitools, we need special handling or blank |
# CORS lists will get sent with other configuration commands such as lifecycle, |
-# commands, which would cause CORS configuration to be unintentionally removed. |
+# which would cause CORS configuration to be unintentionally removed. |
# Protorpc defaults list values to an empty list, and won't allow us to set the |
# value to None like other configuration fields, so there is no way to |
# distinguish the default value from when we actually want to remove the CORS |
@@ -85,6 +86,14 @@ DEFAULT_CONTENT_TYPE = 'application/octet-stream' |
REMOVE_CORS_CONFIG = [apitools_messages.Bucket.CorsValueListEntry( |
maxAgeSeconds=-1, method=['REMOVE_CORS_CONFIG'])] |
+# Similar to CORS above, we need a sentinel value allowing us to specify |
+# when a default object ACL should be private (containing no entries). |
+# A defaultObjectAcl value of [] means don't modify the default object ACL. |
+# A value of [PRIVATE_DEFAULT_OBJ_ACL] means create an empty/private default |
+# object ACL. |
+PRIVATE_DEFAULT_OBJ_ACL = apitools_messages.ObjectAccessControl( |
+ id='PRIVATE_DEFAULT_OBJ_ACL') |
+ |
def ObjectMetadataFromHeaders(headers): |
"""Creates object metadata according to the provided headers. |
@@ -312,9 +321,44 @@ def PreconditionsFromHeaders(headers): |
return return_preconditions |
+def CreateNotFoundExceptionForObjectWrite( |
+ dst_provider, dst_bucket_name, src_provider=None, |
+ src_bucket_name=None, src_object_name=None, src_generation=None): |
+ """Creates a NotFoundException for an object upload or copy. |
+ |
+ This is necessary because 404s don't necessarily specify which resource |
+ does not exist. |
+ |
+ Args: |
+ dst_provider: String abbreviation of destination provider, e.g., 'gs'. |
+ dst_bucket_name: Destination bucket name for the write operation. |
+ src_provider: String abbreviation of source provider, i.e. 'gs', if any. |
+ src_bucket_name: Source bucket name, if any (for the copy case). |
+ src_object_name: Source object name, if any (for the copy case). |
+ src_generation: Source object generation, if any (for the copy case). |
+ |
+ Returns: |
+ NotFoundException with appropriate message. |
+ """ |
+ dst_url_string = '%s://%s' % (dst_provider, dst_bucket_name) |
+ if src_bucket_name and src_object_name: |
+ src_url_string = '%s://%s/%s' % (src_provider, src_bucket_name, |
+ src_object_name) |
+ if src_generation: |
+ src_url_string += '#%s' % str(src_generation) |
+ return NotFoundException( |
+ 'The source object %s or the destination bucket %s does not exist.' % |
+ (src_url_string, dst_url_string)) |
+ |
+ return NotFoundException( |
+ 'The destination bucket %s does not exist or the write to the ' |
+ 'destination must be restarted' % dst_url_string) |
+ |
+ |
def CreateBucketNotFoundException(code, provider, bucket_name): |
- return NotFoundException('%s://%s bucket does not exist.' % |
- (provider, bucket_name), status=code) |
+ return BucketNotFoundException('%s://%s bucket does not exist.' % |
+ (provider, bucket_name), bucket_name, |
+ status=code) |
def CreateObjectNotFoundException(code, provider, bucket_name, object_name, |
@@ -638,6 +682,10 @@ class AclTranslation(object): |
def BotoAclFromMessage(cls, acl_message): |
acl_dicts = [] |
for message in acl_message: |
+ if message == PRIVATE_DEFAULT_OBJ_ACL: |
+ # Sentinel value indicating acl_dicts should be an empty list to create |
+ # a private (no entries) default object ACL. |
+ break |
acl_dicts.append(encoding.MessageToDict(message)) |
return cls.BotoAclFromJson(acl_dicts) |