def buckets_patch(bucket_name): """Implement the 'Buckets: patch' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) patch = json.loads(flask.request.data) bucket.apply_patch(patch) return testbench_utils.filtered_response(flask.request, bucket.metadata)
def bucket_acl_update(bucket_name, entity): """Implement the 'BucketAccessControls: update' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) payload = json.loads(flask.request.data) acl = bucket.update_acl(entity, payload.get('role', '')) return testbench_utils.filtered_response(flask.request, acl)
def resumable_upload_chunk(bucket_name): """Receive a chunk for a resumable upload.""" gcs_url = flask.url_for( "objects_insert", bucket_name=bucket_name, _external=True ).replace("/upload/", "/") bucket = testbench_utils.lookup_bucket(bucket_name) return bucket.receive_upload_chunk(gcs_url, flask.request)
def buckets_get(bucket_name): """Implement the 'Buckets: get' API: return the metadata for a bucket.""" base_url = flask.url_for('gcs_index', _external=True) insert_magic_bucket(base_url) bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) return testbench_utils.filtered_response(flask.request, bucket.metadata)
def bucket_test_iam_permissions(bucket_name): """Implement the 'Buckets: testIamPermissions' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) return testbench_utils.filtered_response( flask.request, bucket.test_iam_permissions(flask.request) )
def bucket_set_iam_policy(bucket_name): """Implement the 'Buckets: setIamPolicy' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) return testbench_utils.filtered_response( flask.request, bucket.set_iam_policy(flask.request) )
def bucket_default_object_acl_patch(bucket_name, entity): """Implement the 'DefaultObjectAccessControls: patch' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) payload = json.loads(flask.request.data) acl = bucket.update_default_object_acl(entity, payload.get("role", "")) return testbench_utils.filtered_response(flask.request, acl)
def _update_predefined_acl(self, predefined_acl): """Update the ACL based on the given request parameter value.""" if predefined_acl is None: predefined_acl = 'projectPrivate' self.insert_acl( testbench_utils.canonical_entity_name('project-owners-123456789'), 'OWNER') bucket = testbench_utils.lookup_bucket(self.bucket_name) owner = bucket.metadata.get('owner') if owner is None: owner_entity = 'project-owners-123456789' else: owner_entity = owner.get('entity') if predefined_acl == 'authenticatedRead': self.insert_acl('allAuthenticatedUsers', 'READER') elif predefined_acl == 'bucketOwnerFullControl': self.insert_acl(owner_entity, 'OWNER') elif predefined_acl == 'bucketOwnerRead': self.insert_acl(owner_entity, 'READER') elif predefined_acl == 'private': self.insert_acl('project-owners', 'OWNER') elif predefined_acl == 'projectPrivate': self.insert_acl( testbench_utils.canonical_entity_name( 'project-editors-123456789'), 'OWNER') self.insert_acl( testbench_utils.canonical_entity_name( 'project-viewers-123456789'), 'READER') elif predefined_acl == 'publicRead': self.insert_acl(testbench_utils.canonical_entity_name('allUsers'), 'READER') else: raise error_response.ErrorResponse('Invalid predefinedAcl value', status_code=400)
def bucket_acl_create(bucket_name): """Implement the 'BucketAccessControls: create' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) payload = json.loads(flask.request.data) return testbench_utils.filtered_response( flask.request, bucket.insert_acl(payload.get('entity', ''), payload.get('role', '')))
def bucket_notification_list(bucket_name): """Implement the 'Notifications: list' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) return testbench_utils.filtered_response( flask.request, {"kind": "storage#notifications", "items": bucket.list_notifications()}, )
def bucket_default_object_acl_list(bucket_name): """Implement the 'BucketAccessControls: list' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) result = { 'items': bucket.metadata.get('defaultObjectAcl', []), } return testbench_utils.filtered_response(flask.request, result)
def objects_insert(bucket_name): """Implement the 'Objects: insert' API. Insert a new GCS Object.""" gcs_url = flask.url_for( "objects_insert", bucket_name=bucket_name, _external=True ).replace("/upload/", "/") insert_magic_bucket(gcs_url) upload_type = flask.request.args.get("uploadType") if upload_type is None: raise error_response.ErrorResponse( "uploadType not set in Objects: insert", status_code=400 ) if upload_type not in {"multipart", "media", "resumable"}: raise error_response.ErrorResponse( "testbench does not support %s uploadType" % upload_type, status_code=400 ) if upload_type == "resumable": bucket = testbench_utils.lookup_bucket(bucket_name) upload_url = flask.url_for( "objects_insert", bucket_name=bucket_name, _external=True ) return bucket.create_resumable_upload(upload_url, flask.request) object_path = None blob = None current_version = None if upload_type == "media": object_name = flask.request.args.get("name", None) if object_name is None: raise error_response.ErrorResponse( "name not set in Objects: insert", status_code=412 ) object_path, blob = testbench_utils.get_object( bucket_name, object_name, gcs_object.GcsObject(bucket_name, object_name) ) blob.check_preconditions(flask.request) current_version = blob.insert(gcs_url, flask.request) else: resource, media_headers, media_body = testbench_utils.parse_multi_part( flask.request ) object_name = flask.request.args.get("name", resource.get("name", None)) if object_name is None: raise error_response.ErrorResponse( "name not set in Objects: insert", status_code=412 ) object_path, blob = testbench_utils.get_object( bucket_name, object_name, gcs_object.GcsObject(bucket_name, object_name) ) blob.check_preconditions(flask.request) current_version = blob.insert_multipart( gcs_url, flask.request, resource, media_headers, media_body ) testbench_utils.insert_object(object_path, blob) return testbench_utils.filtered_response(flask.request, current_version.metadata)
def _insert_revision(self, revision): """Insert a new revision that has been initialized and checked. :param revision: GcsObjectVersion the new revision to insert. :rtype:NoneType """ update = {self.generation: revision} bucket = testbench_utils.lookup_bucket(self.bucket_name) if not bucket.versioning_enabled(): self.revisions = update else: self.revisions.update(update)
def delete_resumable_upload(bucket_name): upload_type = flask.request.args.get("uploadType") if upload_type != "resumable": raise error_response.ErrorResponse( "testbench can delete resumable uploadType only", status_code=400) upload_id = flask.request.args.get("upload_id") if upload_id is None: raise error_response.ErrorResponse( "missing upload_id in delete_resumable_upload", status_code=400) bucket = testbench_utils.lookup_bucket(bucket_name) if upload_id not in bucket.resumable_uploads: raise error_response.ErrorResponse("upload_id does not exist", status_code=404) bucket.resumable_uploads.pop(upload_id) return testbench_utils.filtered_response(flask.request, {})
def buckets_update(bucket_name): """Implement the 'Buckets: update' API: update an existing Bucket.""" base_url = flask.url_for('gcs_index', _external=True) insert_magic_bucket(base_url) payload = json.loads(flask.request.data) name = payload.get('name') if name is None: raise error_response.ErrorResponse( 'Missing bucket name in `Buckets: update`', status_code=412) if name != bucket_name: raise error_response.ErrorResponse( 'Mismatched bucket name parameter in `Buckets: update`', status_code=400) bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) bucket.update_from_metadata(payload) return testbench_utils.filtered_response(flask.request, bucket.metadata)
def objects_list(bucket_name): """Implement the 'Objects: list' API: return the objects in a bucket.""" # Lookup the bucket, if this fails the bucket does not exist, and this # function should return an error. base_url = flask.url_for("gcs_index", _external=True) insert_magic_bucket(base_url) _ = testbench_utils.lookup_bucket(bucket_name) result = {"next_page_token": "", "items": []} versions_parameter = flask.request.args.get("versions") all_versions = versions_parameter is not None and bool(versions_parameter) for name, o in testbench_utils.all_objects(): if name.find(bucket_name + "/o") != 0: continue if o.get_latest() is None: continue if all_versions: for object_version in o.revisions.values(): result["items"].append(object_version.metadata) else: result["items"].append(o.get_latest().metadata) return testbench_utils.filtered_response(flask.request, result)
def objects_insert(bucket_name): """Implement the 'Objects: insert' API. Insert a new GCS Object.""" gcs_url = flask.url_for('objects_insert', bucket_name=bucket_name, _external=True).replace('/upload/', '/') insert_magic_bucket(gcs_url) upload_type = flask.request.args.get('uploadType') if upload_type is None: raise error_response.ErrorResponse( 'uploadType not set in Objects: insert', status_code=400) if upload_type not in {'multipart', 'media', 'resumable'}: raise error_response.ErrorResponse( 'testbench does not support %s uploadType' % upload_type, status_code=400) if upload_type == 'resumable': bucket = testbench_utils.lookup_bucket(bucket_name) upload_url = flask.url_for('objects_insert', bucket_name=bucket_name, _external=True) return bucket.create_resumable_upload(upload_url, flask.request) object_name = flask.request.args.get('name', None) if object_name is None: raise error_response.ErrorResponse('name not set in Objects: insert', status_code=412) object_path, blob = testbench_utils.get_object( bucket_name, object_name, gcs_object.GcsObject(bucket_name, object_name)) blob.check_preconditions(flask.request) if upload_type == 'media': current_version = blob.insert(gcs_url, flask.request) else: current_version = blob.insert_multipart(gcs_url, flask.request) testbench_utils.insert_object(object_path, blob) return testbench_utils.filtered_response(flask.request, current_version.metadata)
def _update_predefined_acl(self, predefined_acl): """Update the ACL based on the given request parameter value.""" if predefined_acl is None: predefined_acl = "projectPrivate" self.insert_acl( testbench_utils.canonical_entity_name("project-owners-123456789"), "OWNER") bucket = testbench_utils.lookup_bucket(self.bucket_name) owner = bucket.metadata.get("owner") if owner is None: owner_entity = "project-owners-123456789" else: owner_entity = owner.get("entity") if predefined_acl == "authenticatedRead": self.insert_acl("allAuthenticatedUsers", "READER") elif predefined_acl == "bucketOwnerFullControl": self.insert_acl(owner_entity, "OWNER") elif predefined_acl == "bucketOwnerRead": self.insert_acl(owner_entity, "READER") elif predefined_acl == "private": self.insert_acl("project-owners", "OWNER") elif predefined_acl == "projectPrivate": self.insert_acl( testbench_utils.canonical_entity_name( "project-editors-123456789"), "OWNER", ) self.insert_acl( testbench_utils.canonical_entity_name( "project-viewers-123456789"), "READER", ) elif predefined_acl == "publicRead": self.insert_acl(testbench_utils.canonical_entity_name("allUsers"), "READER") else: raise error_response.ErrorResponse("Invalid predefinedAcl value", status_code=400)
def objects_list(bucket_name): """Implement the 'Objects: list' API: return the objects in a bucket.""" # Lookup the bucket, if this fails the bucket does not exist, and this # function should return an error. base_url = flask.url_for("gcs_index", _external=True) insert_magic_bucket(base_url) _ = testbench_utils.lookup_bucket(bucket_name) result = {"next_page_token": "", "items": [], "prefixes:": []} versions_parameter = flask.request.args.get("versions") all_versions = versions_parameter is not None and bool(versions_parameter) prefixes = set() prefix = flask.request.args.get("prefix", "", type("")) delimiter = flask.request.args.get("delimiter", "", type("")) start_offset = flask.request.args.get("startOffset", "", type("")) end_offset = flask.request.args.get("endOffset", "", type("")) bucket_link = bucket_name + "/o/" for name, o in testbench_utils.all_objects(): if name.find(bucket_link + prefix) != 0: continue if o.get_latest() is None: continue # We assume `delimiter` has only one character. if name[len(bucket_link):] < start_offset: continue if end_offset != "" and name[len(bucket_link):] >= end_offset: continue delimiter_index = name.find(delimiter, len(bucket_link + prefix)) if delimiter != "" and delimiter_index > 0: # We don't want to include `bucket_link` in the returned prefix. prefixes.add(name[len(bucket_link):delimiter_index + 1]) continue if all_versions: for object_version in o.revisions.values(): result["items"].append(object_version.metadata) else: result["items"].append(o.get_latest().metadata) result["prefixes"] = list(prefixes) return testbench_utils.filtered_response(flask.request, result)
def bucket_acl_list(bucket_name): """Implement the 'BucketAccessControls: list' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) result = {"items": bucket.metadata.get("acl", [])} return testbench_utils.filtered_response(flask.request, result)
def bucket_lock_retention_policy(bucket_name): """Implement the 'Buckets: lockRetentionPolicy' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.lock_retention_policy(flask.request) return testbench_utils.filtered_response(flask.request, bucket.metadata)
def bucket_notification_get(bucket_name, notification_id): """Implement the 'Notifications: get' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) notification = bucket.get_notification(notification_id) return testbench_utils.filtered_response(flask.request, notification)
def bucket_default_object_acl_get(bucket_name, entity): """Implement the 'BucketAccessControls: get' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) acl = bucket.get_default_object_acl(entity) return testbench_utils.filtered_response(flask.request, acl)
def bucket_acl_delete(bucket_name, entity): """Implement the 'BucketAccessControls: delete' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) bucket.delete_acl(entity) return testbench_utils.filtered_response(flask.request, {})
def buckets_delete(bucket_name): """Implement the 'Buckets: delete' API.""" bucket = testbench_utils.lookup_bucket(bucket_name) bucket.check_preconditions(flask.request) testbench_utils.delete_bucket(bucket_name) return testbench_utils.filtered_response(flask.request, {})