From f880f79cea526c3628e03632e12c3911b424f6a5 Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Wed, 24 Apr 2024 00:01:20 +0000 Subject: [PATCH 01/39] ci: disable codecov uploads (#3) --- .github/workflows/build.yaml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index df89ebab..3f237dc3 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -43,21 +43,6 @@ jobs: PYTHONPATH: "." run: | pytest --cov=./ --cov-report=xml - - name: Upload coverage to Codecov - if: ${{ matrix.python-version == '3.12' }} - uses: Wandalen/wretry.action@1a10d4835a1506f513ad8e7488aeb474ab20055c # v1.4.10 - with: - action: codecov/codecov-action@v4 - with: | - token: ${{ secrets.CODECOV_TOKEN }} - env_vars: OS,PYTHON - fail_ci_if_error: true - files: ./coverage.xml - flags: unittests - name: codecov-umbrella - verbose: true - attempt_limit: 5 - attempt_delay: 10000 windows-tests: runs-on: windows-2022 strategy: From 3ea6a1642847966ca810069cf78e1897db39a24e Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Wed, 24 Apr 2024 00:04:41 +0000 Subject: [PATCH 02/39] impl: add bidi streaming read patches (#1) Add the bi-di streaming read RPCs as patches. In follow up PRs we can implement the bidi functions. These patches may need updates from time to time, as the line number hints change. --- .gitignore | 1 + README.md | 8 +- bidi-streaming-read.patch | 260 ++++++++++++++++++ google/storage/v2/storage_pb2.py | 373 +++++++++++++++----------- google/storage/v2/storage_pb2_grpc.py | 43 +++ update-protos.sh | 10 + 6 files changed, 525 insertions(+), 170 deletions(-) create mode 100644 bidi-streaming-read.patch diff --git a/.gitignore b/.gitignore index 75458d84..28cd2f03 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ cov.xml googleapis_storage_testbench.egg-info/ coverage.xml .venv/ +.googleapis/ diff --git a/README.md b/README.md index 019cbd88..f2199fae 100644 --- a/README.md +++ b/README.md @@ -122,14 +122,8 @@ run the grpc_tools generator: ```shell cd $HOME/storage-testbench - -# This creates a new directory with the protos from `googleapis`. If -# the clone already exists use: -# git -C $HOME/googleapis pull -git -C $HOME clone https://github.com/googleapis/googleapis - pip install grpcio-tools -./update-protos.sh $HOME/googleapis +./update-protos.sh $PWD/.googleapis ``` Then commit the files generated in `google/**`: diff --git a/bidi-streaming-read.patch b/bidi-streaming-read.patch new file mode 100644 index 00000000..da6917af --- /dev/null +++ b/bidi-streaming-read.patch @@ -0,0 +1,260 @@ +diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto +index 62922eadf..9d2c07960 100644 +--- a/google/storage/v2/storage.proto ++++ b/google/storage/v2/storage.proto +@@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; + import "google/protobuf/empty.proto"; + import "google/protobuf/field_mask.proto"; + import "google/protobuf/timestamp.proto"; ++import "google/rpc/status.proto"; + import "google/type/date.proto"; + + option go_package = "cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb"; +@@ -274,6 +275,28 @@ service Storage { + option (google.api.method_signature) = "bucket,object,generation"; + } + ++ // Reads an object's data. ++ // ++ // This is a bi-directional API with the added support for reading multiple ++ // ranges within one stream both within and across multiple messages. This can ++ // improve performance compared with performing individual range read RPCs. ++ // If the server encountered an error for any of the inputs, the stream will ++ // be closed with the relevant error code. ++ // Because the API allows for multiple outstanding requests, when the stream ++ // is closed the error response will contain a BidiReadObjectRangesError proto ++ // in the error extension describing the error for each outstanding read_id. ++ rpc BidiReadObject(stream BidiReadObjectRequest) ++ returns (stream BidiReadObjectResponse) { ++ option (google.api.method_signature) = "bucket,object"; ++ option (google.api.method_signature) = "bucket,object,generation"; ++ option (google.api.routing) = { ++ routing_parameters { ++ field: "read_object_spec.bucket" ++ path_template: "{bucket=**}" ++ } ++ }; ++ } ++ + // Updates an object's metadata. + // Equivalent to JSON API's storage.objects.patch. + rpc UpdateObject(UpdateObjectRequest) returns (Object) { +@@ -995,6 +1018,218 @@ message ReadObjectResponse { + Object metadata = 4; + } + ++// Describes the object to read in a BidiReadObject request. ++message BidiReadObjectSpec { ++ // The name of the bucket containing the object to read. ++ string bucket = 1 [ ++ (google.api.field_behavior) = REQUIRED, ++ (google.api.resource_reference).type = "storage.googleapis.com/Bucket" ++ ]; ++ ++ // The name of the object to read. ++ string object = 2 [ ++ (google.api.field_behavior) = REQUIRED ++ ]; ++ ++ // If present, selects a specific revision of this object (as opposed ++ // to the latest version, the default). ++ int64 generation = 3; ++ ++ // Makes the operation conditional on whether the object's current generation ++ // matches the given value. Setting to 0 makes the operation succeed only if ++ // there are no live versions of the object. ++ optional int64 if_generation_match = 4; ++ ++ // Makes the operation conditional on whether the object's live generation ++ // does not match the given value. If no live object exists, the precondition ++ // fails. Setting to 0 makes the operation succeed only if there is a live ++ // version of the object. ++ optional int64 if_generation_not_match = 5; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration matches the given value. ++ optional int64 if_metageneration_match = 6; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration does not match the given value. ++ optional int64 if_metageneration_not_match = 7; ++ ++ // A set of parameters common to Storage API requests concerning an object. ++ // (-- api-linter: core::0131::request-unknown-fields=disabled ++ // aip.dev/not-precedent: All Cloud Storage object requests share a common ++ // set of parameters to handle billing and other per-request concerns. --) ++ CommonObjectRequestParams common_object_request_params = 8; ++ ++ // Mask specifying which fields to read. ++ // The checksummed_data field and its children will always be present. ++ // If no mask is specified, will default to all fields except metadata.owner ++ // and metadata.acl. ++ // * may be used to mean "all fields". ++ optional google.protobuf.FieldMask read_mask = 12; ++} ++ ++// Request message for BidiReadObject. ++message BidiReadObjectRequest { ++ ++ // The first message of each stream must set this field. The stream returns an ++ // error if any subsequent message sets this field, or if the first message ++ // does not set the field. ++ oneof first_message { ++ // Describes the object to read ++ BidiReadObjectSpec read_spec = 6; ++ // The read handle is an optimized way of creating new streams. Read handles ++ // are generated and periodically refreshed from prior reads. ++ BidiReadHandle read_handle = 7; ++ } ++ ++ // Provides a list of 0 or more (up to 100) ranges to read. If a single range ++ // is large enough to require multiple responses, they are guaranteed to be ++ // delivered in increasing offset order. There are no ordering guarantees ++ // across ranges. When no ranges are provided, the response message will not ++ // include ObjectRangeData. For full object downloads, the offset and size can ++ // be set to 0. ++ repeated ReadRange read_ranges = 8; ++ ++ // The first message of each stream should set this field. If this is not ++ // the first message, an error will be returned. ++ BidiReadObjectSpec read_object_spec = 1 [deprecated = true]; ++ ++ // The offset for the first byte to return in the read, relative to the start ++ // of the object. ++ // ++ // A negative `read_offset` value will be interpreted as the number of bytes ++ // back from the end of the object to be returned. For example, if an object's ++ // length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and ++ // `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting ++ // a negative offset with magnitude larger than the size of the object will ++ // return the entire object. ++ int64 read_offset = 4 [deprecated = true]; ++ ++ // The maximum number of `data` bytes the server is allowed to return in the ++ // sum of all `Object` messages. A `read_limit` of zero indicates that there ++ // is no limit, and a negative `read_limit` will cause an error. ++ // ++ // If the stream returns fewer bytes than allowed by the `read_limit` and no ++ // error occurred, the stream includes all data from the `read_offset` to the ++ // end of the resource. ++ int64 read_limit = 5 [deprecated = true]; ++} ++ ++// Response message for BidiReadObject. ++message BidiReadObjectResponse { ++ // A portion of the data for the object. The service **may** leave `data` ++ // empty for any given `ReadResponse`. This enables the service to inform the ++ // client that the request is still live while it is running an operation to ++ // generate more data. ++ ChecksummedData checksummed_data = 1 ++ [deprecated = true]; ++ ++ // The checksums of the complete object regardless of data range. If the ++ // object is downloaded in full, the client should compute one of these ++ // checksums over the downloaded object and compare it against the value ++ // provided here. ++ ObjectChecksums object_checksums = 2 ++ [deprecated = true]; ++ ++ // If read_offset and or read_limit was specified on the ++ // ReadObjectRequest, ContentRange will be populated on the first ++ // ReadObjectResponse message following the request. ++ ContentRange content_range = 3 [deprecated = true]; ++ ++ // A portion of the object's data. The service **may** leave data ++ // empty for any given ReadResponse. This enables the service to inform the ++ // client that the request is still live while it is running an operation to ++ // generate more data. ++ // The service **may** pipeline multiple responses belonging to different read ++ // requests. Each ObjectRangeData entry will have a read_id ++ // set to the same value as the corresponding source read request. ++ repeated ObjectRangeData object_data_ranges = 6; ++ ++ // Metadata of the object whose media is being returned. ++ // Only populated in the first response in the stream. ++ Object metadata = 4; ++ ++ // This field will be periodically refreshed, however it may not be set in ++ // every response. It allows the client to more efficiently open subsequent ++ // bidirectional streams to the same object. ++ BidiReadHandle read_handle = 7; ++ ++ // If set, indicates there are no more bytes to read for the given range. ++ bool end_of_range = 5 [deprecated = true]; ++} ++ ++// Error extension proto containing details for all outstanding reads on the ++// failed stream ++message BidiReadObjectError { ++ // The error code for each outstanding read_range ++ repeated ReadRangeError read_range_errors = 1; ++} ++ ++// Error extension proto containing details for a single range read ++message ReadRangeError { ++ // The id of the corresponding read_range ++ int64 read_id = 1; ++ // The status which should be an enum value of [google.rpc.Code]. ++ google.rpc.Status status = 2; ++} ++ ++// Describes a range of bytes to read in a BidiReadObjectRanges request. ++message ReadRange { ++ // The offset for the first byte to return in the read, relative to the start ++ // of the object. ++ // ++ // A negative read_offset value will be interpreted as the number of bytes ++ // back from the end of the object to be returned. For example, if an object's ++ // length is 15 bytes, a ReadObjectRequest with read_offset = -5 and ++ // read_limit = 3 would return bytes 10 through 12 of the object. Requesting ++ // a negative offset with magnitude larger than the size of the object will ++ // return the entire object. A read_offset larger than the size of the object ++ // will result in an OutOfRange error. ++ int64 read_offset = 1 [(google.api.field_behavior) = REQUIRED]; ++ ++ // The maximum number of data bytes the server is allowed to return across ++ // all response messages with the same read_id. A read_limit of zero ++ // indicates that there is no limit, and a negative read_limit will cause an ++ // error. If the stream returns fewer bytes than allowed by the read_limit ++ // and no error occurred, the stream includes all data from the read_offset ++ // to the resource end. ++ int64 read_limit = 2 [(google.api.field_behavior) = OPTIONAL]; ++ ++ // Read identifier provided by the client. When the client issues more than ++ // one outstanding ReadRange on the same stream, responses can be mapped back ++ // to their corresponding requests using this value. Clients must ensure that ++ // all outstanding requests have different read_id values. The server may ++ // close the stream with an error if this condition is not met. ++ int64 read_id = 3 [(google.api.field_behavior) = REQUIRED]; ++} ++ ++// Contains data and metadata for a range of an object. ++message ObjectRangeData { ++ // A portion of the data for the object. ++ ChecksummedData checksummed_data = 1; ++ ++ // The ReadRange describes the content being returned with read_id set to the ++ // corresponding ReadObjectRequest in the stream. Multiple ObjectRangeData ++ // messages may have the same read_id but increasing offsets. ++ // ReadObjectResponse messages with the same read_id are guaranteed to be ++ // delivered in increasing offset order. ++ ReadRange read_range = 2; ++ ++ // If set, indicates there are no more bytes to read for the given ReadRange. ++ bool range_end = 3; ++} ++ ++// BidiReadHandle contains a handle from a previous BiDiReadObject ++// invocation. The client can use this instead of BidiReadObjectSpec as an ++// optimized way of opening subsequent bidirectional streams to the same object. ++message BidiReadHandle { ++ // Opaque value describing a previous read. ++ bytes handle = 1 [(google.api.field_behavior) = REQUIRED]; ++ ++ // The routing token is used by the SDK to correctly route the request. ++ string routing_token = 2 [(google.api.field_behavior) = REQUIRED]; ++} ++ + // Describes an attempt to insert an object, possibly over multiple requests. + message WriteObjectSpec { + // Required. Destination object, including its name and its metadata. diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index 243eaff1..29447a88 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -36,10 +36,11 @@ from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.rpc import status_pb2 as google_dot_rpc_dot_status__pb2 from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x8d\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_size\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xaf\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"r\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xaa\'\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x92\x04\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xc7\x02\n\x15\x42idiReadObjectRequest\x12:\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecH\x00\x12\x38\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x00\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x43\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"A\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\x12\x1a\n\rrouting_token\x18\x02 \x01(\tB\x03\xe0\x41\x02\"\x8d\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_size\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xaf\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"r\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xf1(\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\xc4\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\"Y\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -101,6 +102,34 @@ _globals['_GETOBJECTREQUEST'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' _globals['_GETOBJECTREQUEST'].fields_by_name['object']._options = None _globals['_GETOBJECTREQUEST'].fields_by_name['object']._serialized_options = b'\340A\002' + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['bucket']._options = None + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._options = None + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_object_spec']._options = None + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_object_spec']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._options = None + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_limit']._options = None + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_limit']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['checksummed_data']._options = None + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['checksummed_data']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['object_checksums']._options = None + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['object_checksums']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['content_range']._options = None + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['content_range']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['end_of_range']._options = None + _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['end_of_range']._serialized_options = b'\030\001' + _globals['_READRANGE'].fields_by_name['read_offset']._options = None + _globals['_READRANGE'].fields_by_name['read_offset']._serialized_options = b'\340A\002' + _globals['_READRANGE'].fields_by_name['read_limit']._options = None + _globals['_READRANGE'].fields_by_name['read_limit']._serialized_options = b'\340A\001' + _globals['_READRANGE'].fields_by_name['read_id']._options = None + _globals['_READRANGE'].fields_by_name['read_id']._serialized_options = b'\340A\002' + _globals['_BIDIREADHANDLE'].fields_by_name['handle']._options = None + _globals['_BIDIREADHANDLE'].fields_by_name['handle']._serialized_options = b'\340A\002' + _globals['_BIDIREADHANDLE'].fields_by_name['routing_token']._options = None + _globals['_BIDIREADHANDLE'].fields_by_name['routing_token']._serialized_options = b'\340A\002' _globals['_WRITEOBJECTSPEC'].fields_by_name['resource']._options = None _globals['_WRITEOBJECTSPEC'].fields_by_name['resource']._serialized_options = b'\340A\002' _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._options = None @@ -291,6 +320,8 @@ _globals['_STORAGE'].methods_by_name['GetObject']._serialized_options = b'\332A\rbucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['ReadObject']._options = None _globals['_STORAGE'].methods_by_name['ReadObject']._serialized_options = b'\332A\rbucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}' + _globals['_STORAGE'].methods_by_name['BidiReadObject']._options = None + _globals['_STORAGE'].methods_by_name['BidiReadObject']._serialized_options = b'\332A\rbucket,object\332A\030bucket,object,generation\212\323\344\223\002(\022&\n\027read_object_spec.bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['UpdateObject']._options = None _globals['_STORAGE'].methods_by_name['UpdateObject']._serialized_options = b'\332A\022object,update_mask\212\323\344\223\002\036\022\034\n\robject.bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['ListObjects']._options = None @@ -313,166 +344,182 @@ _globals['_STORAGE'].methods_by_name['ListHmacKeys']._serialized_options = b'\332A\007project\212\323\344\223\002\013\022\t\n\007project' _globals['_STORAGE'].methods_by_name['UpdateHmacKey']._options = None _globals['_STORAGE'].methods_by_name['UpdateHmacKey']._serialized_options = b'\332A\024hmac_key,update_mask\212\323\344\223\002\"\022 \n\020hmac_key.project\022\014{project=**}' - _globals['_DELETEBUCKETREQUEST']._serialized_start=378 - _globals['_DELETEBUCKETREQUEST']._serialized_end=592 - _globals['_GETBUCKETREQUEST']._serialized_start=595 - _globals['_GETBUCKETREQUEST']._serialized_end=872 - _globals['_CREATEBUCKETREQUEST']._serialized_start=875 - _globals['_CREATEBUCKETREQUEST']._serialized_end=1081 - _globals['_LISTBUCKETSREQUEST']._serialized_start=1084 - _globals['_LISTBUCKETSREQUEST']._serialized_end=1280 - _globals['_LISTBUCKETSRESPONSE']._serialized_start=1282 - _globals['_LISTBUCKETSRESPONSE']._serialized_end=1372 - _globals['_LOCKBUCKETRETENTIONPOLICYREQUEST']._serialized_start=1374 - _globals['_LOCKBUCKETRETENTIONPOLICYREQUEST']._serialized_end=1501 - _globals['_UPDATEBUCKETREQUEST']._serialized_start=1504 - _globals['_UPDATEBUCKETREQUEST']._serialized_end=1830 - _globals['_DELETENOTIFICATIONCONFIGREQUEST']._serialized_start=1832 - _globals['_DELETENOTIFICATIONCONFIGREQUEST']._serialized_end=1930 - _globals['_GETNOTIFICATIONCONFIGREQUEST']._serialized_start=1932 - _globals['_GETNOTIFICATIONCONFIGREQUEST']._serialized_end=2027 - _globals['_CREATENOTIFICATIONCONFIGREQUEST']._serialized_start=2030 - _globals['_CREATENOTIFICATIONCONFIGREQUEST']._serialized_end=2203 - _globals['_LISTNOTIFICATIONCONFIGSREQUEST']._serialized_start=2206 - _globals['_LISTNOTIFICATIONCONFIGSREQUEST']._serialized_end=2344 - _globals['_LISTNOTIFICATIONCONFIGSRESPONSE']._serialized_start=2346 - _globals['_LISTNOTIFICATIONCONFIGSRESPONSE']._serialized_end=2473 - _globals['_COMPOSEOBJECTREQUEST']._serialized_start=2476 - _globals['_COMPOSEOBJECTREQUEST']._serialized_end=3233 - _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT']._serialized_start=2943 - _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT']._serialized_end=3181 - _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT_OBJECTPRECONDITIONS']._serialized_start=3102 - _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT_OBJECTPRECONDITIONS']._serialized_end=3181 - _globals['_DELETEOBJECTREQUEST']._serialized_start=3236 - _globals['_DELETEOBJECTREQUEST']._serialized_end=3701 - _globals['_RESTOREOBJECTREQUEST']._serialized_start=3704 - _globals['_RESTOREOBJECTREQUEST']._serialized_end=4225 - _globals['_CANCELRESUMABLEWRITEREQUEST']._serialized_start=4227 - _globals['_CANCELRESUMABLEWRITEREQUEST']._serialized_end=4280 - _globals['_CANCELRESUMABLEWRITERESPONSE']._serialized_start=4282 - _globals['_CANCELRESUMABLEWRITERESPONSE']._serialized_end=4312 - _globals['_READOBJECTREQUEST']._serialized_start=4315 - _globals['_READOBJECTREQUEST']._serialized_end=4885 - _globals['_GETOBJECTREQUEST']._serialized_start=4888 - _globals['_GETOBJECTREQUEST']._serialized_end=5460 - _globals['_READOBJECTRESPONSE']._serialized_start=5463 - _globals['_READOBJECTRESPONSE']._serialized_end=5708 - _globals['_WRITEOBJECTSPEC']._serialized_start=5711 - _globals['_WRITEOBJECTSPEC']._serialized_end=6108 - _globals['_WRITEOBJECTREQUEST']._serialized_start=6111 - _globals['_WRITEOBJECTREQUEST']._serialized_end=6501 - _globals['_WRITEOBJECTRESPONSE']._serialized_start=6503 - _globals['_WRITEOBJECTRESPONSE']._serialized_end=6613 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=6616 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=7047 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=7049 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=7163 - _globals['_LISTOBJECTSREQUEST']._serialized_start=7166 - _globals['_LISTOBJECTSREQUEST']._serialized_end=7595 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=7598 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=7731 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=7733 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=7848 - _globals['_REWRITEOBJECTREQUEST']._serialized_start=7851 - _globals['_REWRITEOBJECTREQUEST']._serialized_end=9171 - _globals['_REWRITERESPONSE']._serialized_start=9174 - _globals['_REWRITERESPONSE']._serialized_end=9325 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=9328 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=9570 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=9572 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=9620 - _globals['_UPDATEOBJECTREQUEST']._serialized_start=9623 - _globals['_UPDATEOBJECTREQUEST']._serialized_end=10118 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=10120 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=10216 - _globals['_CREATEHMACKEYREQUEST']._serialized_start=10219 - _globals['_CREATEHMACKEYREQUEST']._serialized_end=10347 - _globals['_CREATEHMACKEYRESPONSE']._serialized_start=10349 - _globals['_CREATEHMACKEYRESPONSE']._serialized_end=10452 - _globals['_DELETEHMACKEYREQUEST']._serialized_start=10454 - _globals['_DELETEHMACKEYREQUEST']._serialized_end=10570 - _globals['_GETHMACKEYREQUEST']._serialized_start=10572 - _globals['_GETHMACKEYREQUEST']._serialized_end=10685 - _globals['_LISTHMACKEYSREQUEST']._serialized_start=10688 - _globals['_LISTHMACKEYSREQUEST']._serialized_end=10876 - _globals['_LISTHMACKEYSRESPONSE']._serialized_start=10878 - _globals['_LISTHMACKEYSRESPONSE']._serialized_end=10980 - _globals['_UPDATEHMACKEYREQUEST']._serialized_start=10983 - _globals['_UPDATEHMACKEYREQUEST']._serialized_end=11113 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=11115 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=11239 - _globals['_SERVICECONSTANTS']._serialized_start=11242 - _globals['_SERVICECONSTANTS']._serialized_end=11956 - _globals['_SERVICECONSTANTS_VALUES']._serialized_start=11263 - _globals['_SERVICECONSTANTS_VALUES']._serialized_end=11956 - _globals['_BUCKET']._serialized_start=11959 - _globals['_BUCKET']._serialized_end=15561 - _globals['_BUCKET_BILLING']._serialized_start=13400 - _globals['_BUCKET_BILLING']._serialized_end=13433 - _globals['_BUCKET_CORS']._serialized_start=13435 - _globals['_BUCKET_CORS']._serialized_end=13523 - _globals['_BUCKET_ENCRYPTION']._serialized_start=13525 - _globals['_BUCKET_ENCRYPTION']._serialized_end=13602 - _globals['_BUCKET_IAMCONFIG']._serialized_start=13605 - _globals['_BUCKET_IAMCONFIG']._serialized_end=13841 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=13751 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=13841 - _globals['_BUCKET_LIFECYCLE']._serialized_start=13844 - _globals['_BUCKET_LIFECYCLE']._serialized_end=14599 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=13914 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=14599 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=14058 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=14103 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=14106 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=14599 - _globals['_BUCKET_LOGGING']._serialized_start=14601 - _globals['_BUCKET_LOGGING']._serialized_end=14657 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=14660 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=14803 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=14806 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=14983 - _globals['_BUCKET_VERSIONING']._serialized_start=14985 - _globals['_BUCKET_VERSIONING']._serialized_end=15014 - _globals['_BUCKET_WEBSITE']._serialized_start=15016 - _globals['_BUCKET_WEBSITE']._serialized_end=15075 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=15077 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=15124 - _globals['_BUCKET_AUTOCLASS']._serialized_start=15127 - _globals['_BUCKET_AUTOCLASS']._serialized_end=15394 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=15396 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=15441 - _globals['_BUCKET_LABELSENTRY']._serialized_start=15443 - _globals['_BUCKET_LABELSENTRY']._serialized_end=15488 - _globals['_BUCKETACCESSCONTROL']._serialized_start=15564 - _globals['_BUCKETACCESSCONTROL']._serialized_end=15770 - _globals['_CHECKSUMMEDDATA']._serialized_start=15772 - _globals['_CHECKSUMMEDDATA']._serialized_end=15845 - _globals['_OBJECTCHECKSUMS']._serialized_start=15847 - _globals['_OBJECTCHECKSUMS']._serialized_end=15914 - _globals['_HMACKEYMETADATA']._serialized_start=15917 - _globals['_HMACKEYMETADATA']._serialized_end=16218 - _globals['_NOTIFICATIONCONFIG']._serialized_start=16221 - _globals['_NOTIFICATIONCONFIG']._serialized_end=16644 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=16462 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=16517 - _globals['_CUSTOMERENCRYPTION']._serialized_start=16646 - _globals['_CUSTOMERENCRYPTION']._serialized_end=16722 - _globals['_OBJECT']._serialized_start=16725 - _globals['_OBJECT']._serialized_end=18049 - _globals['_OBJECT_METADATAENTRY']._serialized_start=17939 - _globals['_OBJECT_METADATAENTRY']._serialized_end=17986 - _globals['_OBJECTACCESSCONTROL']._serialized_start=18052 - _globals['_OBJECTACCESSCONTROL']._serialized_end=18258 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=18260 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=18368 - _globals['_PROJECTTEAM']._serialized_start=18370 - _globals['_PROJECTTEAM']._serialized_end=18421 - _globals['_SERVICEACCOUNT']._serialized_start=18423 - _globals['_SERVICEACCOUNT']._serialized_end=18462 - _globals['_OWNER']._serialized_start=18464 - _globals['_OWNER']._serialized_end=18506 - _globals['_CONTENTRANGE']._serialized_start=18508 - _globals['_CONTENTRANGE']._serialized_end=18575 - _globals['_STORAGE']._serialized_start=18578 - _globals['_STORAGE']._serialized_end=23612 + _globals['_DELETEBUCKETREQUEST']._serialized_start=403 + _globals['_DELETEBUCKETREQUEST']._serialized_end=617 + _globals['_GETBUCKETREQUEST']._serialized_start=620 + _globals['_GETBUCKETREQUEST']._serialized_end=897 + _globals['_CREATEBUCKETREQUEST']._serialized_start=900 + _globals['_CREATEBUCKETREQUEST']._serialized_end=1106 + _globals['_LISTBUCKETSREQUEST']._serialized_start=1109 + _globals['_LISTBUCKETSREQUEST']._serialized_end=1305 + _globals['_LISTBUCKETSRESPONSE']._serialized_start=1307 + _globals['_LISTBUCKETSRESPONSE']._serialized_end=1397 + _globals['_LOCKBUCKETRETENTIONPOLICYREQUEST']._serialized_start=1399 + _globals['_LOCKBUCKETRETENTIONPOLICYREQUEST']._serialized_end=1526 + _globals['_UPDATEBUCKETREQUEST']._serialized_start=1529 + _globals['_UPDATEBUCKETREQUEST']._serialized_end=1855 + _globals['_DELETENOTIFICATIONCONFIGREQUEST']._serialized_start=1857 + _globals['_DELETENOTIFICATIONCONFIGREQUEST']._serialized_end=1955 + _globals['_GETNOTIFICATIONCONFIGREQUEST']._serialized_start=1957 + _globals['_GETNOTIFICATIONCONFIGREQUEST']._serialized_end=2052 + _globals['_CREATENOTIFICATIONCONFIGREQUEST']._serialized_start=2055 + _globals['_CREATENOTIFICATIONCONFIGREQUEST']._serialized_end=2228 + _globals['_LISTNOTIFICATIONCONFIGSREQUEST']._serialized_start=2231 + _globals['_LISTNOTIFICATIONCONFIGSREQUEST']._serialized_end=2369 + _globals['_LISTNOTIFICATIONCONFIGSRESPONSE']._serialized_start=2371 + _globals['_LISTNOTIFICATIONCONFIGSRESPONSE']._serialized_end=2498 + _globals['_COMPOSEOBJECTREQUEST']._serialized_start=2501 + _globals['_COMPOSEOBJECTREQUEST']._serialized_end=3258 + _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT']._serialized_start=2968 + _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT']._serialized_end=3206 + _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT_OBJECTPRECONDITIONS']._serialized_start=3127 + _globals['_COMPOSEOBJECTREQUEST_SOURCEOBJECT_OBJECTPRECONDITIONS']._serialized_end=3206 + _globals['_DELETEOBJECTREQUEST']._serialized_start=3261 + _globals['_DELETEOBJECTREQUEST']._serialized_end=3726 + _globals['_RESTOREOBJECTREQUEST']._serialized_start=3729 + _globals['_RESTOREOBJECTREQUEST']._serialized_end=4250 + _globals['_CANCELRESUMABLEWRITEREQUEST']._serialized_start=4252 + _globals['_CANCELRESUMABLEWRITEREQUEST']._serialized_end=4305 + _globals['_CANCELRESUMABLEWRITERESPONSE']._serialized_start=4307 + _globals['_CANCELRESUMABLEWRITERESPONSE']._serialized_end=4337 + _globals['_READOBJECTREQUEST']._serialized_start=4340 + _globals['_READOBJECTREQUEST']._serialized_end=4910 + _globals['_GETOBJECTREQUEST']._serialized_start=4913 + _globals['_GETOBJECTREQUEST']._serialized_end=5485 + _globals['_READOBJECTRESPONSE']._serialized_start=5488 + _globals['_READOBJECTRESPONSE']._serialized_end=5733 + _globals['_BIDIREADOBJECTSPEC']._serialized_start=5736 + _globals['_BIDIREADOBJECTSPEC']._serialized_end=6266 + _globals['_BIDIREADOBJECTREQUEST']._serialized_start=6269 + _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6596 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6599 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=7006 + _globals['_BIDIREADOBJECTERROR']._serialized_start=7008 + _globals['_BIDIREADOBJECTERROR']._serialized_end=7091 + _globals['_READRANGEERROR']._serialized_start=7093 + _globals['_READRANGEERROR']._serialized_end=7162 + _globals['_READRANGE']._serialized_start=7164 + _globals['_READRANGE']._serialized_end=7248 + _globals['_OBJECTRANGEDATA']._serialized_start=7251 + _globals['_OBJECTRANGEDATA']._serialized_end=7399 + _globals['_BIDIREADHANDLE']._serialized_start=7401 + _globals['_BIDIREADHANDLE']._serialized_end=7466 + _globals['_WRITEOBJECTSPEC']._serialized_start=7469 + _globals['_WRITEOBJECTSPEC']._serialized_end=7866 + _globals['_WRITEOBJECTREQUEST']._serialized_start=7869 + _globals['_WRITEOBJECTREQUEST']._serialized_end=8259 + _globals['_WRITEOBJECTRESPONSE']._serialized_start=8261 + _globals['_WRITEOBJECTRESPONSE']._serialized_end=8371 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8374 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=8805 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=8807 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=8921 + _globals['_LISTOBJECTSREQUEST']._serialized_start=8924 + _globals['_LISTOBJECTSREQUEST']._serialized_end=9353 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9356 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9489 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9491 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=9606 + _globals['_REWRITEOBJECTREQUEST']._serialized_start=9609 + _globals['_REWRITEOBJECTREQUEST']._serialized_end=10929 + _globals['_REWRITERESPONSE']._serialized_start=10932 + _globals['_REWRITERESPONSE']._serialized_end=11083 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11086 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11328 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11330 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11378 + _globals['_UPDATEOBJECTREQUEST']._serialized_start=11381 + _globals['_UPDATEOBJECTREQUEST']._serialized_end=11876 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=11878 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=11974 + _globals['_CREATEHMACKEYREQUEST']._serialized_start=11977 + _globals['_CREATEHMACKEYREQUEST']._serialized_end=12105 + _globals['_CREATEHMACKEYRESPONSE']._serialized_start=12107 + _globals['_CREATEHMACKEYRESPONSE']._serialized_end=12210 + _globals['_DELETEHMACKEYREQUEST']._serialized_start=12212 + _globals['_DELETEHMACKEYREQUEST']._serialized_end=12328 + _globals['_GETHMACKEYREQUEST']._serialized_start=12330 + _globals['_GETHMACKEYREQUEST']._serialized_end=12443 + _globals['_LISTHMACKEYSREQUEST']._serialized_start=12446 + _globals['_LISTHMACKEYSREQUEST']._serialized_end=12634 + _globals['_LISTHMACKEYSRESPONSE']._serialized_start=12636 + _globals['_LISTHMACKEYSRESPONSE']._serialized_end=12738 + _globals['_UPDATEHMACKEYREQUEST']._serialized_start=12741 + _globals['_UPDATEHMACKEYREQUEST']._serialized_end=12871 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12873 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12997 + _globals['_SERVICECONSTANTS']._serialized_start=13000 + _globals['_SERVICECONSTANTS']._serialized_end=13714 + _globals['_SERVICECONSTANTS_VALUES']._serialized_start=13021 + _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13714 + _globals['_BUCKET']._serialized_start=13717 + _globals['_BUCKET']._serialized_end=17319 + _globals['_BUCKET_BILLING']._serialized_start=15158 + _globals['_BUCKET_BILLING']._serialized_end=15191 + _globals['_BUCKET_CORS']._serialized_start=15193 + _globals['_BUCKET_CORS']._serialized_end=15281 + _globals['_BUCKET_ENCRYPTION']._serialized_start=15283 + _globals['_BUCKET_ENCRYPTION']._serialized_end=15360 + _globals['_BUCKET_IAMCONFIG']._serialized_start=15363 + _globals['_BUCKET_IAMCONFIG']._serialized_end=15599 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=15509 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15599 + _globals['_BUCKET_LIFECYCLE']._serialized_start=15602 + _globals['_BUCKET_LIFECYCLE']._serialized_end=16357 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15672 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=16357 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15816 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15861 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15864 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=16357 + _globals['_BUCKET_LOGGING']._serialized_start=16359 + _globals['_BUCKET_LOGGING']._serialized_end=16415 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=16418 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=16561 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=16564 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16741 + _globals['_BUCKET_VERSIONING']._serialized_start=16743 + _globals['_BUCKET_VERSIONING']._serialized_end=16772 + _globals['_BUCKET_WEBSITE']._serialized_start=16774 + _globals['_BUCKET_WEBSITE']._serialized_end=16833 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16835 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16882 + _globals['_BUCKET_AUTOCLASS']._serialized_start=16885 + _globals['_BUCKET_AUTOCLASS']._serialized_end=17152 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=17154 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=17199 + _globals['_BUCKET_LABELSENTRY']._serialized_start=17201 + _globals['_BUCKET_LABELSENTRY']._serialized_end=17246 + _globals['_BUCKETACCESSCONTROL']._serialized_start=17322 + _globals['_BUCKETACCESSCONTROL']._serialized_end=17528 + _globals['_CHECKSUMMEDDATA']._serialized_start=17530 + _globals['_CHECKSUMMEDDATA']._serialized_end=17603 + _globals['_OBJECTCHECKSUMS']._serialized_start=17605 + _globals['_OBJECTCHECKSUMS']._serialized_end=17672 + _globals['_HMACKEYMETADATA']._serialized_start=17675 + _globals['_HMACKEYMETADATA']._serialized_end=17976 + _globals['_NOTIFICATIONCONFIG']._serialized_start=17979 + _globals['_NOTIFICATIONCONFIG']._serialized_end=18402 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=18220 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=18275 + _globals['_CUSTOMERENCRYPTION']._serialized_start=18404 + _globals['_CUSTOMERENCRYPTION']._serialized_end=18480 + _globals['_OBJECT']._serialized_start=18483 + _globals['_OBJECT']._serialized_end=19807 + _globals['_OBJECT_METADATAENTRY']._serialized_start=19697 + _globals['_OBJECT_METADATAENTRY']._serialized_end=19744 + _globals['_OBJECTACCESSCONTROL']._serialized_start=19810 + _globals['_OBJECTACCESSCONTROL']._serialized_end=20016 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=20018 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=20126 + _globals['_PROJECTTEAM']._serialized_start=20128 + _globals['_PROJECTTEAM']._serialized_end=20179 + _globals['_SERVICEACCOUNT']._serialized_start=20181 + _globals['_SERVICEACCOUNT']._serialized_end=20220 + _globals['_OWNER']._serialized_start=20222 + _globals['_OWNER']._serialized_end=20264 + _globals['_CONTENTRANGE']._serialized_start=20266 + _globals['_CONTENTRANGE']._serialized_end=20333 + _globals['_STORAGE']._serialized_start=20336 + _globals['_STORAGE']._serialized_end=25569 # @@protoc_insertion_point(module_scope) diff --git a/google/storage/v2/storage_pb2_grpc.py b/google/storage/v2/storage_pb2_grpc.py index 92d90be6..9a35d122 100644 --- a/google/storage/v2/storage_pb2_grpc.py +++ b/google/storage/v2/storage_pb2_grpc.py @@ -147,6 +147,11 @@ def __init__(self, channel): request_serializer=google_dot_storage_dot_v2_dot_storage__pb2.ReadObjectRequest.SerializeToString, response_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.ReadObjectResponse.FromString, ) + self.BidiReadObject = channel.stream_stream( + '/google.storage.v2.Storage/BidiReadObject', + request_serializer=google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectResponse.FromString, + ) self.UpdateObject = channel.unary_unary( '/google.storage.v2.Storage/UpdateObject', request_serializer=google_dot_storage_dot_v2_dot_storage__pb2.UpdateObjectRequest.SerializeToString, @@ -395,6 +400,22 @@ def ReadObject(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def BidiReadObject(self, request_iterator, context): + """Reads an object's data. + + This is a bi-directional API with the added support for reading multiple + ranges within one stream both within and across multiple messages. This can + improve performance compared with performing individual range read RPCs. + If the server encountered an error for any of the inputs, the stream will + be closed with the relevant error code. + Because the API allows for multiple outstanding requests, when the stream + is closed the error response will contain a BidiReadObjectRangesError proto + in the error extension describing the error for each outstanding read_id. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def UpdateObject(self, request, context): """Updates an object's metadata. Equivalent to JSON API's storage.objects.patch. @@ -672,6 +693,11 @@ def add_StorageServicer_to_server(servicer, server): request_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.ReadObjectRequest.FromString, response_serializer=google_dot_storage_dot_v2_dot_storage__pb2.ReadObjectResponse.SerializeToString, ), + 'BidiReadObject': grpc.stream_stream_rpc_method_handler( + servicer.BidiReadObject, + request_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectRequest.FromString, + response_serializer=google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectResponse.SerializeToString, + ), 'UpdateObject': grpc.unary_unary_rpc_method_handler( servicer.UpdateObject, request_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.UpdateObjectRequest.FromString, @@ -1091,6 +1117,23 @@ def ReadObject(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def BidiReadObject(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream(request_iterator, target, '/google.storage.v2.Storage/BidiReadObject', + google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectRequest.SerializeToString, + google_dot_storage_dot_v2_dot_storage__pb2.BidiReadObjectResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def UpdateObject(request, target, diff --git a/update-protos.sh b/update-protos.sh index 634c3368..525cf110 100755 --- a/update-protos.sh +++ b/update-protos.sh @@ -31,6 +31,16 @@ readonly INPUTS=( ) readonly INPUTS +if [[ ! -d "${GOOGLEAPIS_ROOT}" ]]; then + git clone https://github.com/googleapis/googleapis.git "${GOOGLEAPIS_ROOT}" +else + git -C "${GOOGLEAPIS_ROOT}" clean -f -d -x + git -C "${GOOGLEAPIS_ROOT}" restore google/storage + git -C "${GOOGLEAPIS_ROOT}" checkout master + git -C "${GOOGLEAPIS_ROOT}" pull +fi +env -C .googleapis patch -p1 <$PWD/bidi-streaming-read.patch + for input in "${INPUTS[@]}"; do python -m grpc_tools.protoc -I"${GOOGLEAPIS_ROOT}" \ --python_out=. --grpc_python_out=. "${GOOGLEAPIS_ROOT}/${input}" From f678970d3627610a73d7d917bb836378ee469806 Mon Sep 17 00:00:00 2001 From: Carlos O'Ryan Date: Wed, 24 Apr 2024 20:31:17 +0000 Subject: [PATCH 03/39] chore: update patches to meet C++ requirements (#4) I would prefer if we use the same patches across all the SDKs. C++ has more strict requirements to generate the GAPICs, gRPC, and proto libraries. --- bidi-streaming-read.patch | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bidi-streaming-read.patch b/bidi-streaming-read.patch index da6917af..24a01c0c 100644 --- a/bidi-streaming-read.patch +++ b/bidi-streaming-read.patch @@ -1,5 +1,17 @@ +diff --git a/google/storage/v2/BUILD.bazel b/google/storage/v2/BUILD.bazel +index 8fa25cc09..d84fc9456 100644 +--- a/google/storage/v2/BUILD.bazel ++++ b/google/storage/v2/BUILD.bazel +@@ -58,6 +58,7 @@ proto_library( + "//google/api:routing_proto", + "//google/iam/v1:iam_policy_proto", + "//google/iam/v1:policy_proto", ++ "//google/rpc:status_proto", + "//google/type:date_proto", + "@com_google_protobuf//:duration_proto", + "@com_google_protobuf//:empty_proto", diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index 62922eadf..9d2c07960 100644 +index 62922eadf..4ae3ab8cb 100644 --- a/google/storage/v2/storage.proto +++ b/google/storage/v2/storage.proto @@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; @@ -10,7 +22,7 @@ index 62922eadf..9d2c07960 100644 import "google/type/date.proto"; option go_package = "cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb"; -@@ -274,6 +275,28 @@ service Storage { +@@ -274,6 +275,26 @@ service Storage { option (google.api.method_signature) = "bucket,object,generation"; } @@ -26,8 +38,6 @@ index 62922eadf..9d2c07960 100644 + // in the error extension describing the error for each outstanding read_id. + rpc BidiReadObject(stream BidiReadObjectRequest) + returns (stream BidiReadObjectResponse) { -+ option (google.api.method_signature) = "bucket,object"; -+ option (google.api.method_signature) = "bucket,object,generation"; + option (google.api.routing) = { + routing_parameters { + field: "read_object_spec.bucket" @@ -39,7 +49,7 @@ index 62922eadf..9d2c07960 100644 // Updates an object's metadata. // Equivalent to JSON API's storage.objects.patch. rpc UpdateObject(UpdateObjectRequest) returns (Object) { -@@ -995,6 +1018,218 @@ message ReadObjectResponse { +@@ -995,6 +1016,218 @@ message ReadObjectResponse { Object metadata = 4; } From 296974306fb228f777c2ccbc48eaa78f25b67403 Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 12 Jul 2024 13:31:32 -0700 Subject: [PATCH 04/39] chore: update proto patches circa 2024-06-13 (#6) * chore: update patches c.20240612 * generate storage/v2 files * generate google/ files * Revert "generate google/ files" This reverts commit 51217d21f933892bfca252d6c3c6294f68f53d2e. * Revert "generate storage/v2 files" This reverts commit c57c13a4bb8a9f4b8bd8f2e54232b4befe2de742. * fix venv and update protos * update readme --- README.md | 2 +- bidi-streaming-read.patch | 56 +++++-- google/storage/v2/storage_pb2.py | 278 +++++++++++++++---------------- 3 files changed, 181 insertions(+), 155 deletions(-) diff --git a/README.md b/README.md index f2199fae..2e1ba546 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ run the grpc_tools generator: ```shell cd $HOME/storage-testbench -pip install grpcio-tools +pip install --no-deps grpcio-tools ./update-protos.sh $PWD/.googleapis ``` diff --git a/bidi-streaming-read.patch b/bidi-streaming-read.patch index 24a01c0c..47db6565 100644 --- a/bidi-streaming-read.patch +++ b/bidi-streaming-read.patch @@ -1,5 +1,5 @@ diff --git a/google/storage/v2/BUILD.bazel b/google/storage/v2/BUILD.bazel -index 8fa25cc09..d84fc9456 100644 +index 8fa25cc09..c17d0fe82 100644 --- a/google/storage/v2/BUILD.bazel +++ b/google/storage/v2/BUILD.bazel @@ -58,6 +58,7 @@ proto_library( @@ -10,8 +10,16 @@ index 8fa25cc09..d84fc9456 100644 "//google/type:date_proto", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:empty_proto", +@@ -132,6 +133,7 @@ go_proto_library( + "//google/api:annotations_go_proto", + "//google/api:routing_go_proto", + "//google/iam/v1:iam_go_proto", ++ "//google/rpc:status_go_proto", + "//google/type:date_go_proto", + ], + ) diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index 62922eadf..4ae3ab8cb 100644 +index 0f9758f19..c9c027345 100644 --- a/google/storage/v2/storage.proto +++ b/google/storage/v2/storage.proto @@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; @@ -49,7 +57,7 @@ index 62922eadf..4ae3ab8cb 100644 // Updates an object's metadata. // Equivalent to JSON API's storage.objects.patch. rpc UpdateObject(UpdateObjectRequest) returns (Object) { -@@ -995,6 +1016,218 @@ message ReadObjectResponse { +@@ -995,6 +1016,236 @@ message ReadObjectResponse { Object metadata = 4; } @@ -101,6 +109,15 @@ index 62922eadf..4ae3ab8cb 100644 + // and metadata.acl. + // * may be used to mean "all fields". + optional google.protobuf.FieldMask read_mask = 12; ++ ++ // The client can optionally set this field. The read handle is an optimized ++ // way of creating new streams. Read handles are generated and periodically ++ // refreshed from prior reads. ++ optional BidiReadHandle read_handle = 13; ++ ++ // The routing token that influences request routing for the stream. Must be ++ // provided if a BidiReadObjectRedirectedError is returned. ++ optional string routing_token = 14; +} + +// Request message for BidiReadObject. @@ -109,14 +126,17 @@ index 62922eadf..4ae3ab8cb 100644 + // The first message of each stream must set this field. The stream returns an + // error if any subsequent message sets this field, or if the first message + // does not set the field. ++ // TODO(b/340927727): The oneof will be removed once the field is no longer ++ // referenced + oneof first_message { + // Describes the object to read -+ BidiReadObjectSpec read_spec = 6; -+ // The read handle is an optimized way of creating new streams. Read handles -+ // are generated and periodically refreshed from prior reads. -+ BidiReadHandle read_handle = 7; ++ BidiReadObjectSpec read_spec = 6 [deprecated = true]; + } + ++ // The first message of each stream should set this field. If this is not ++ // the first message, an error will be returned. Describes the object to read. ++ BidiReadObjectSpec read_object_spec = 1; ++ + // Provides a list of 0 or more (up to 100) ranges to read. If a single range + // is large enough to require multiple responses, they are guaranteed to be + // delivered in increasing offset order. There are no ordering guarantees @@ -125,10 +145,6 @@ index 62922eadf..4ae3ab8cb 100644 + // be set to 0. + repeated ReadRange read_ranges = 8; + -+ // The first message of each stream should set this field. If this is not -+ // the first message, an error will be returned. -+ BidiReadObjectSpec read_object_spec = 1 [deprecated = true]; -+ + // The offset for the first byte to return in the read, relative to the start + // of the object. + // @@ -181,7 +197,8 @@ index 62922eadf..4ae3ab8cb 100644 + repeated ObjectRangeData object_data_ranges = 6; + + // Metadata of the object whose media is being returned. -+ // Only populated in the first response in the stream. ++ // Only populated in the first response in the stream and not populated when ++ // the stream is opened with a read handle. + Object metadata = 4; + + // This field will be periodically refreshed, however it may not be set in @@ -193,6 +210,18 @@ index 62922eadf..4ae3ab8cb 100644 + bool end_of_range = 5 [deprecated = true]; +} + ++// Error proto containing details for a redirected read. This error is only ++// returned on initial open in case of a redirect. ++message BidiReadObjectRedirectedError { ++ ++ // The read handle for the redirected read. The client can use this for the ++ // subsequent open. ++ BidiReadHandle read_handle = 1; ++ ++ // The routing token that should be used when reopening the read stream. ++ optional string routing_token = 2; ++} ++ +// Error extension proto containing details for all outstanding reads on the +// failed stream +message BidiReadObjectError { @@ -260,9 +289,6 @@ index 62922eadf..4ae3ab8cb 100644 +message BidiReadHandle { + // Opaque value describing a previous read. + bytes handle = 1 [(google.api.field_behavior) = REQUIRED]; -+ -+ // The routing token is used by the SDK to correctly route the request. -+ string routing_token = 2 [(google.api.field_behavior) = REQUIRED]; +} + // Describes an attempt to insert an object, possibly over multiple requests. diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index 29447a88..cc6e77e5 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -40,7 +40,7 @@ from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x92\x04\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xc7\x02\n\x15\x42idiReadObjectRequest\x12:\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecH\x00\x12\x38\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x00\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x43\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"A\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\x12\x1a\n\rrouting_token\x18\x02 \x01(\tB\x03\xe0\x41\x02\"\x8d\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_size\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xaf\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"r\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xf1(\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\xc4\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\"Y\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x8d\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"\x8d\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_size\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xaf\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"r\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xc6(\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -106,8 +106,8 @@ _globals['_BIDIREADOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._options = None _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_object_spec']._options = None - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_object_spec']._serialized_options = b'\030\001' + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._options = None + _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._serialized_options = b'\030\001' _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._options = None _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._serialized_options = b'\030\001' _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_limit']._options = None @@ -128,8 +128,6 @@ _globals['_READRANGE'].fields_by_name['read_id']._serialized_options = b'\340A\002' _globals['_BIDIREADHANDLE'].fields_by_name['handle']._options = None _globals['_BIDIREADHANDLE'].fields_by_name['handle']._serialized_options = b'\340A\002' - _globals['_BIDIREADHANDLE'].fields_by_name['routing_token']._options = None - _globals['_BIDIREADHANDLE'].fields_by_name['routing_token']._serialized_options = b'\340A\002' _globals['_WRITEOBJECTSPEC'].fields_by_name['resource']._options = None _globals['_WRITEOBJECTSPEC'].fields_by_name['resource']._serialized_options = b'\340A\002' _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._options = None @@ -321,7 +319,7 @@ _globals['_STORAGE'].methods_by_name['ReadObject']._options = None _globals['_STORAGE'].methods_by_name['ReadObject']._serialized_options = b'\332A\rbucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['BidiReadObject']._options = None - _globals['_STORAGE'].methods_by_name['BidiReadObject']._serialized_options = b'\332A\rbucket,object\332A\030bucket,object,generation\212\323\344\223\002(\022&\n\027read_object_spec.bucket\022\013{bucket=**}' + _globals['_STORAGE'].methods_by_name['BidiReadObject']._serialized_options = b'\212\323\344\223\002(\022&\n\027read_object_spec.bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['UpdateObject']._options = None _globals['_STORAGE'].methods_by_name['UpdateObject']._serialized_options = b'\332A\022object,update_mask\212\323\344\223\002\036\022\034\n\robject.bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['ListObjects']._options = None @@ -389,137 +387,139 @@ _globals['_READOBJECTRESPONSE']._serialized_start=5488 _globals['_READOBJECTRESPONSE']._serialized_end=5733 _globals['_BIDIREADOBJECTSPEC']._serialized_start=5736 - _globals['_BIDIREADOBJECTSPEC']._serialized_end=6266 - _globals['_BIDIREADOBJECTREQUEST']._serialized_start=6269 - _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6596 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6599 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=7006 - _globals['_BIDIREADOBJECTERROR']._serialized_start=7008 - _globals['_BIDIREADOBJECTERROR']._serialized_end=7091 - _globals['_READRANGEERROR']._serialized_start=7093 - _globals['_READRANGEERROR']._serialized_end=7162 - _globals['_READRANGE']._serialized_start=7164 - _globals['_READRANGE']._serialized_end=7248 - _globals['_OBJECTRANGEDATA']._serialized_start=7251 - _globals['_OBJECTRANGEDATA']._serialized_end=7399 - _globals['_BIDIREADHANDLE']._serialized_start=7401 - _globals['_BIDIREADHANDLE']._serialized_end=7466 - _globals['_WRITEOBJECTSPEC']._serialized_start=7469 - _globals['_WRITEOBJECTSPEC']._serialized_end=7866 - _globals['_WRITEOBJECTREQUEST']._serialized_start=7869 - _globals['_WRITEOBJECTREQUEST']._serialized_end=8259 - _globals['_WRITEOBJECTRESPONSE']._serialized_start=8261 - _globals['_WRITEOBJECTRESPONSE']._serialized_end=8371 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8374 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=8805 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=8807 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=8921 - _globals['_LISTOBJECTSREQUEST']._serialized_start=8924 - _globals['_LISTOBJECTSREQUEST']._serialized_end=9353 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9356 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9489 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9491 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=9606 - _globals['_REWRITEOBJECTREQUEST']._serialized_start=9609 - _globals['_REWRITEOBJECTREQUEST']._serialized_end=10929 - _globals['_REWRITERESPONSE']._serialized_start=10932 - _globals['_REWRITERESPONSE']._serialized_end=11083 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11086 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11328 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11330 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11378 - _globals['_UPDATEOBJECTREQUEST']._serialized_start=11381 - _globals['_UPDATEOBJECTREQUEST']._serialized_end=11876 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=11878 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=11974 - _globals['_CREATEHMACKEYREQUEST']._serialized_start=11977 - _globals['_CREATEHMACKEYREQUEST']._serialized_end=12105 - _globals['_CREATEHMACKEYRESPONSE']._serialized_start=12107 - _globals['_CREATEHMACKEYRESPONSE']._serialized_end=12210 - _globals['_DELETEHMACKEYREQUEST']._serialized_start=12212 - _globals['_DELETEHMACKEYREQUEST']._serialized_end=12328 - _globals['_GETHMACKEYREQUEST']._serialized_start=12330 - _globals['_GETHMACKEYREQUEST']._serialized_end=12443 - _globals['_LISTHMACKEYSREQUEST']._serialized_start=12446 - _globals['_LISTHMACKEYSREQUEST']._serialized_end=12634 - _globals['_LISTHMACKEYSRESPONSE']._serialized_start=12636 - _globals['_LISTHMACKEYSRESPONSE']._serialized_end=12738 - _globals['_UPDATEHMACKEYREQUEST']._serialized_start=12741 - _globals['_UPDATEHMACKEYREQUEST']._serialized_end=12871 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12873 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12997 - _globals['_SERVICECONSTANTS']._serialized_start=13000 - _globals['_SERVICECONSTANTS']._serialized_end=13714 - _globals['_SERVICECONSTANTS_VALUES']._serialized_start=13021 - _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13714 - _globals['_BUCKET']._serialized_start=13717 - _globals['_BUCKET']._serialized_end=17319 - _globals['_BUCKET_BILLING']._serialized_start=15158 - _globals['_BUCKET_BILLING']._serialized_end=15191 - _globals['_BUCKET_CORS']._serialized_start=15193 - _globals['_BUCKET_CORS']._serialized_end=15281 - _globals['_BUCKET_ENCRYPTION']._serialized_start=15283 - _globals['_BUCKET_ENCRYPTION']._serialized_end=15360 - _globals['_BUCKET_IAMCONFIG']._serialized_start=15363 - _globals['_BUCKET_IAMCONFIG']._serialized_end=15599 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=15509 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15599 - _globals['_BUCKET_LIFECYCLE']._serialized_start=15602 - _globals['_BUCKET_LIFECYCLE']._serialized_end=16357 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15672 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=16357 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15816 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15861 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15864 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=16357 - _globals['_BUCKET_LOGGING']._serialized_start=16359 - _globals['_BUCKET_LOGGING']._serialized_end=16415 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=16418 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=16561 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=16564 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16741 - _globals['_BUCKET_VERSIONING']._serialized_start=16743 - _globals['_BUCKET_VERSIONING']._serialized_end=16772 - _globals['_BUCKET_WEBSITE']._serialized_start=16774 - _globals['_BUCKET_WEBSITE']._serialized_end=16833 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16835 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16882 - _globals['_BUCKET_AUTOCLASS']._serialized_start=16885 - _globals['_BUCKET_AUTOCLASS']._serialized_end=17152 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=17154 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=17199 - _globals['_BUCKET_LABELSENTRY']._serialized_start=17201 - _globals['_BUCKET_LABELSENTRY']._serialized_end=17246 - _globals['_BUCKETACCESSCONTROL']._serialized_start=17322 - _globals['_BUCKETACCESSCONTROL']._serialized_end=17528 - _globals['_CHECKSUMMEDDATA']._serialized_start=17530 - _globals['_CHECKSUMMEDDATA']._serialized_end=17603 - _globals['_OBJECTCHECKSUMS']._serialized_start=17605 - _globals['_OBJECTCHECKSUMS']._serialized_end=17672 - _globals['_HMACKEYMETADATA']._serialized_start=17675 - _globals['_HMACKEYMETADATA']._serialized_end=17976 - _globals['_NOTIFICATIONCONFIG']._serialized_start=17979 - _globals['_NOTIFICATIONCONFIG']._serialized_end=18402 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=18220 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=18275 - _globals['_CUSTOMERENCRYPTION']._serialized_start=18404 - _globals['_CUSTOMERENCRYPTION']._serialized_end=18480 - _globals['_OBJECT']._serialized_start=18483 - _globals['_OBJECT']._serialized_end=19807 - _globals['_OBJECT_METADATAENTRY']._serialized_start=19697 - _globals['_OBJECT_METADATAENTRY']._serialized_end=19744 - _globals['_OBJECTACCESSCONTROL']._serialized_start=19810 - _globals['_OBJECTACCESSCONTROL']._serialized_end=20016 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=20018 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=20126 - _globals['_PROJECTTEAM']._serialized_start=20128 - _globals['_PROJECTTEAM']._serialized_end=20179 - _globals['_SERVICEACCOUNT']._serialized_start=20181 - _globals['_SERVICEACCOUNT']._serialized_end=20220 - _globals['_OWNER']._serialized_start=20222 - _globals['_OWNER']._serialized_end=20264 - _globals['_CONTENTRANGE']._serialized_start=20266 - _globals['_CONTENTRANGE']._serialized_end=20333 - _globals['_STORAGE']._serialized_start=20336 - _globals['_STORAGE']._serialized_end=25569 + _globals['_BIDIREADOBJECTSPEC']._serialized_end=6389 + _globals['_BIDIREADOBJECTREQUEST']._serialized_start=6392 + _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6661 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6664 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=7071 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=7074 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=7207 + _globals['_BIDIREADOBJECTERROR']._serialized_start=7209 + _globals['_BIDIREADOBJECTERROR']._serialized_end=7292 + _globals['_READRANGEERROR']._serialized_start=7294 + _globals['_READRANGEERROR']._serialized_end=7363 + _globals['_READRANGE']._serialized_start=7365 + _globals['_READRANGE']._serialized_end=7449 + _globals['_OBJECTRANGEDATA']._serialized_start=7452 + _globals['_OBJECTRANGEDATA']._serialized_end=7600 + _globals['_BIDIREADHANDLE']._serialized_start=7602 + _globals['_BIDIREADHANDLE']._serialized_end=7639 + _globals['_WRITEOBJECTSPEC']._serialized_start=7642 + _globals['_WRITEOBJECTSPEC']._serialized_end=8039 + _globals['_WRITEOBJECTREQUEST']._serialized_start=8042 + _globals['_WRITEOBJECTREQUEST']._serialized_end=8432 + _globals['_WRITEOBJECTRESPONSE']._serialized_start=8434 + _globals['_WRITEOBJECTRESPONSE']._serialized_end=8544 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8547 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=8978 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=8980 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9094 + _globals['_LISTOBJECTSREQUEST']._serialized_start=9097 + _globals['_LISTOBJECTSREQUEST']._serialized_end=9526 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9529 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9662 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9664 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=9779 + _globals['_REWRITEOBJECTREQUEST']._serialized_start=9782 + _globals['_REWRITEOBJECTREQUEST']._serialized_end=11102 + _globals['_REWRITERESPONSE']._serialized_start=11105 + _globals['_REWRITERESPONSE']._serialized_end=11256 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11259 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11501 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11503 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11551 + _globals['_UPDATEOBJECTREQUEST']._serialized_start=11554 + _globals['_UPDATEOBJECTREQUEST']._serialized_end=12049 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=12051 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=12147 + _globals['_CREATEHMACKEYREQUEST']._serialized_start=12150 + _globals['_CREATEHMACKEYREQUEST']._serialized_end=12278 + _globals['_CREATEHMACKEYRESPONSE']._serialized_start=12280 + _globals['_CREATEHMACKEYRESPONSE']._serialized_end=12383 + _globals['_DELETEHMACKEYREQUEST']._serialized_start=12385 + _globals['_DELETEHMACKEYREQUEST']._serialized_end=12501 + _globals['_GETHMACKEYREQUEST']._serialized_start=12503 + _globals['_GETHMACKEYREQUEST']._serialized_end=12616 + _globals['_LISTHMACKEYSREQUEST']._serialized_start=12619 + _globals['_LISTHMACKEYSREQUEST']._serialized_end=12807 + _globals['_LISTHMACKEYSRESPONSE']._serialized_start=12809 + _globals['_LISTHMACKEYSRESPONSE']._serialized_end=12911 + _globals['_UPDATEHMACKEYREQUEST']._serialized_start=12914 + _globals['_UPDATEHMACKEYREQUEST']._serialized_end=13044 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=13046 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=13170 + _globals['_SERVICECONSTANTS']._serialized_start=13173 + _globals['_SERVICECONSTANTS']._serialized_end=13887 + _globals['_SERVICECONSTANTS_VALUES']._serialized_start=13194 + _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13887 + _globals['_BUCKET']._serialized_start=13890 + _globals['_BUCKET']._serialized_end=17492 + _globals['_BUCKET_BILLING']._serialized_start=15331 + _globals['_BUCKET_BILLING']._serialized_end=15364 + _globals['_BUCKET_CORS']._serialized_start=15366 + _globals['_BUCKET_CORS']._serialized_end=15454 + _globals['_BUCKET_ENCRYPTION']._serialized_start=15456 + _globals['_BUCKET_ENCRYPTION']._serialized_end=15533 + _globals['_BUCKET_IAMCONFIG']._serialized_start=15536 + _globals['_BUCKET_IAMCONFIG']._serialized_end=15772 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=15682 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15772 + _globals['_BUCKET_LIFECYCLE']._serialized_start=15775 + _globals['_BUCKET_LIFECYCLE']._serialized_end=16530 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15845 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=16530 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15989 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=16034 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=16037 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=16530 + _globals['_BUCKET_LOGGING']._serialized_start=16532 + _globals['_BUCKET_LOGGING']._serialized_end=16588 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=16591 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=16734 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=16737 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16914 + _globals['_BUCKET_VERSIONING']._serialized_start=16916 + _globals['_BUCKET_VERSIONING']._serialized_end=16945 + _globals['_BUCKET_WEBSITE']._serialized_start=16947 + _globals['_BUCKET_WEBSITE']._serialized_end=17006 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=17008 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=17055 + _globals['_BUCKET_AUTOCLASS']._serialized_start=17058 + _globals['_BUCKET_AUTOCLASS']._serialized_end=17325 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=17327 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=17372 + _globals['_BUCKET_LABELSENTRY']._serialized_start=17374 + _globals['_BUCKET_LABELSENTRY']._serialized_end=17419 + _globals['_BUCKETACCESSCONTROL']._serialized_start=17495 + _globals['_BUCKETACCESSCONTROL']._serialized_end=17701 + _globals['_CHECKSUMMEDDATA']._serialized_start=17703 + _globals['_CHECKSUMMEDDATA']._serialized_end=17776 + _globals['_OBJECTCHECKSUMS']._serialized_start=17778 + _globals['_OBJECTCHECKSUMS']._serialized_end=17845 + _globals['_HMACKEYMETADATA']._serialized_start=17848 + _globals['_HMACKEYMETADATA']._serialized_end=18149 + _globals['_NOTIFICATIONCONFIG']._serialized_start=18152 + _globals['_NOTIFICATIONCONFIG']._serialized_end=18575 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=18393 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=18448 + _globals['_CUSTOMERENCRYPTION']._serialized_start=18577 + _globals['_CUSTOMERENCRYPTION']._serialized_end=18653 + _globals['_OBJECT']._serialized_start=18656 + _globals['_OBJECT']._serialized_end=19980 + _globals['_OBJECT_METADATAENTRY']._serialized_start=19870 + _globals['_OBJECT_METADATAENTRY']._serialized_end=19917 + _globals['_OBJECTACCESSCONTROL']._serialized_start=19983 + _globals['_OBJECTACCESSCONTROL']._serialized_end=20189 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=20191 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=20299 + _globals['_PROJECTTEAM']._serialized_start=20301 + _globals['_PROJECTTEAM']._serialized_end=20352 + _globals['_SERVICEACCOUNT']._serialized_start=20354 + _globals['_SERVICEACCOUNT']._serialized_end=20393 + _globals['_OWNER']._serialized_start=20395 + _globals['_OWNER']._serialized_end=20437 + _globals['_CONTENTRANGE']._serialized_start=20439 + _globals['_CONTENTRANGE']._serialized_end=20506 + _globals['_STORAGE']._serialized_start=20509 + _globals['_STORAGE']._serialized_end=25699 # @@protoc_insertion_point(module_scope) From ef3d194bb785856e4e945f6ace670e0fd882a1ec Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 26 Jul 2024 11:54:01 -0700 Subject: [PATCH 05/39] feat: BidiRead initial scaffolding n ranges in 1 stream (#7) * feat: BidiRead initial scaffolding n ranges in 1 stream * attempt using a priorityQueue with bidireads --- testbench/grpc_server.py | 93 +++++++++++++++++++++++++++++++++ tests/test_grpc_server.py | 106 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index ee085f1e..ee04d1ec 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -577,6 +577,99 @@ def ReadObject(self, request, context): content_range = None start = start + size + def BidiReadObject(self, request_iterator, context): + # A PriorityQueue holds tuples (offset, response) where the offset serves as the priority predicate. + # A response is removed from the queue with the lowest offset. This will help guarantee that + # responses with the same read_id will be delivered in increasing offset order. + from queue import PriorityQueue + + responses = PriorityQueue() + # TBD: yield_size is configurable and is used to emulate interleaved responses. + yield_size = 1 + + # Helper function that processes ReadRange. This could potentially become the target function + # when we introduce multiple workers. + def process_read_range(range, metadata=None): + size = storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES + # A read range corresponds to a unique read_id. + # For the same read_id, it is guaranteed that responses are delivered in increasing offset order. + start = range.read_offset + read_end = len(blob.media) + read_id = range.read_id + + if start > read_end: + # TODO: Error handling, return a list of read_range_errors in BidiReadObjectError. + return testbench.error.range_not_satisfiable(context) + if range.read_limit < 0: + # TODO: Error handling, return a list of read_range_errors in BidiReadObjectError. + # A negative read_limit will cause an error. + return testbench.error.range_not_satisfiable(context) + elif range.read_limit > 0: + # read_limit is the maximum number of data bytes the server is allowed to return across all response messages with the same read_id. + read_end = min(read_end, start + range.read_limit) + + while start <= read_end: + end = min(start + size, read_end) + chunk = blob.media[start:end] + # Verify if there are no more bytes to read for the given ReadRange. + range_end = True if end == read_end else False + res = storage_pb2.BidiReadObjectResponse( + object_data_ranges=[ + storage_pb2.ObjectRangeData( + checksummed_data=storage_pb2.ChecksummedData( + content=chunk, + ), + read_range=storage_pb2.ReadRange( + read_offset=start, + read_limit=range.read_limit, + read_id=read_id, + ), + range_end=range_end, + ), + ], + metadata=metadata, + ) + # Put tuple (offset, response) into the priority queue. + responses.put((start, res)) + start = end + 1 + + # Handle first request message. + first_message = next(request_iterator) + obj_spec = first_message.read_object_spec + blob = self.db.get_object( + obj_spec.bucket, + obj_spec.object, + context=context, + generation=obj_spec.generation, + preconditions=testbench.common.make_grpc_preconditions(obj_spec), + ) + metadata = blob.metadata + for range in first_message.read_ranges: + process_read_range(range, metadata=metadata) + # Let's start returning some responses. + while responses.qsize() > yield_size: + item = responses.get() + yield item[1] + + # Handle incoming requests, after finshing processing the first message. + for request in request_iterator: + for range in request.read_ranges: + process_read_range(range) + # Let's start returning some responses. Response messages per read_id are put into + # the priority queue altogether before yielding. + # Not all responses are dequeued, and will result in interleaved responses. + while responses.qsize() > yield_size: + item = responses.get() + yield item[1] + while responses.qsize() > yield_size: + item = responses.get() + yield item[1] + + # Finally, let's make sure all responses in the priority queue are returned. + while not responses.empty(): + item = responses.get() + yield item[1] + @retry_test(method="storage.objects.patch") def UpdateObject(self, request, context): intersection = field_mask_pb2.FieldMask( diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 7d784f82..586fec61 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2238,6 +2238,112 @@ def test_bidi_write_object_resumable(self): self.assertEqual(blob.name, "object-name") self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + def test_bidi_read_object(self): + # Create object in database to read. + media = TestGrpc._create_block(5 * 1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test n ranges in 1 stream, where n=2. + offset_1 = 0 + limit_1 = 2 * 1024 * 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + offset_2 = 3 * 1024 * 1024 + limit_2 = 2 * 1024 * 1024 + read_id_2 = read_id_1 + 1 + + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + storage_pb2.ReadRange( + read_offset=offset_2, + read_limit=limit_2, + read_id=read_id_2, + ), + ], + ) + + streamer = self.grpc.BidiReadObject([r1], context=self.mock_context()) + responses = list(streamer) + read_range_1 = responses[0].object_data_ranges[0].read_range + self.assertEqual(read_id_1, read_range_1.read_id) + self.assertEqual(offset_1, read_range_1.read_offset) + self.assertEqual(limit_1, read_range_1.read_limit) + read_range_last = responses[-1].object_data_ranges[-1].read_range + self.assertEqual(read_id_2, read_range_last.read_id) + self.assertEqual(offset_2, read_range_last.read_offset) + self.assertEqual(limit_2, read_range_last.read_limit) + + def test_bidi_read_object_out_of_order(self): + # Create object in database to read. + media = TestGrpc._create_block(6 * 1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test n ranges in 1 stream, where n=3. Test range requests offsets are out of order. + offset_1 = 0 + limit_1 = 3 * 1024 * 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + offset_2 = 4 * 1024 * 1024 + limit_2 = 1024 + read_id_2 = read_id_1 - 1 + offset_3 = 5 * 1024 * 1024 + limit_3 = 1 + read_id_3 = read_id_1 + 1 + + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + storage_pb2.ReadRange( + read_offset=offset_3, + read_limit=limit_3, + read_id=read_id_3, + ), + ], + ) + r2 = storage_pb2.BidiReadObjectRequest( + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_2, + read_limit=limit_2, + read_id=read_id_2, + ), + ], + ) + + streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) + responses = list(streamer) + read_range_1 = responses[0].object_data_ranges[0].read_range + self.assertEqual(read_id_1, read_range_1.read_id) + self.assertEqual(offset_1, read_range_1.read_offset) + self.assertEqual(limit_1, read_range_1.read_limit) + read_range_last = responses[-1].object_data_ranges[-1].read_range + self.assertEqual(read_id_3, read_range_last.read_id) + self.assertEqual(offset_3, read_range_last.read_offset) + self.assertEqual(limit_3, read_range_last.read_limit) + if __name__ == "__main__": unittest.main() From 2a0e94c3525724a68ac5bf20aa3ef7d95b0234b8 Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 26 Jul 2024 13:46:18 -0700 Subject: [PATCH 06/39] feat: add crc32c checksum to BidiRead (#9) --- testbench/grpc_server.py | 1 + tests/test_grpc_server.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index ee04d1ec..adf369f0 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -618,6 +618,7 @@ def process_read_range(range, metadata=None): storage_pb2.ObjectRangeData( checksummed_data=storage_pb2.ChecksummedData( content=chunk, + crc32c=crc32c.crc32c(chunk), ), read_range=storage_pb2.ReadRange( read_offset=start, diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 586fec61..1e79026f 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2277,13 +2277,17 @@ def test_bidi_read_object(self): streamer = self.grpc.BidiReadObject([r1], context=self.mock_context()) responses = list(streamer) read_range_1 = responses[0].object_data_ranges[0].read_range + data_1 = responses[0].object_data_ranges[0].checksummed_data self.assertEqual(read_id_1, read_range_1.read_id) self.assertEqual(offset_1, read_range_1.read_offset) self.assertEqual(limit_1, read_range_1.read_limit) + self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) read_range_last = responses[-1].object_data_ranges[-1].read_range + data_last = responses[-1].object_data_ranges[-1].checksummed_data self.assertEqual(read_id_2, read_range_last.read_id) self.assertEqual(offset_2, read_range_last.read_offset) self.assertEqual(limit_2, read_range_last.read_limit) + self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) def test_bidi_read_object_out_of_order(self): # Create object in database to read. @@ -2336,13 +2340,17 @@ def test_bidi_read_object_out_of_order(self): streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) responses = list(streamer) read_range_1 = responses[0].object_data_ranges[0].read_range + data_1 = responses[0].object_data_ranges[0].checksummed_data self.assertEqual(read_id_1, read_range_1.read_id) self.assertEqual(offset_1, read_range_1.read_offset) self.assertEqual(limit_1, read_range_1.read_limit) + self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) read_range_last = responses[-1].object_data_ranges[-1].read_range + data_last = responses[-1].object_data_ranges[-1].checksummed_data self.assertEqual(read_id_3, read_range_last.read_id) self.assertEqual(offset_3, read_range_last.read_offset) self.assertEqual(limit_3, read_range_last.read_limit) + self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) if __name__ == "__main__": From f580ee8c6c377458f38a2d1a3845599d6d282b04 Mon Sep 17 00:00:00 2001 From: cojenco Date: Thu, 29 Aug 2024 13:44:01 -0700 Subject: [PATCH 07/39] test: BidiRead object not found error handling (#10) * feat: BidiReadObjectError part 1 object not found * use grpc.StatusCode.value * for discussion, return in error details * object resolution errors, not found and precondition failed * remove extra line change --- tests/test_grpc_server.py | 89 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 1e79026f..8b74a2be 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2352,6 +2352,95 @@ def test_bidi_read_object_out_of_order(self): self.assertEqual(limit_3, read_range_last.read_limit) self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) + def test_bidi_read_object_not_found(self): + # Test BidiReadObject with non-existent object. + nonexistent_object_name = "object-name2" + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object=nonexistent_object_name, + ), + read_ranges=[], + ) + # The code depends on `context.abort()` raising an exception. + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiReadObject([r1], context=context) + list(streamer) + context.abort.assert_called_once_with( + grpc.StatusCode.NOT_FOUND, unittest.mock.ANY + ) + + # Test BidiReadObject with invalid object generation. + # Create object in database to read. + media = TestGrpc._create_block(1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + obj = self.db.get_object("bucket-name", "object-name", None) + invalid_generation = obj.metadata.generation + 1 + r2 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + generation=invalid_generation, + ), + read_ranges=[], + ) + # The code depends on `context.abort()` raising an exception. + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiReadObject([r2], context=context) + list(streamer) + context.abort.assert_called_once_with( + grpc.StatusCode.NOT_FOUND, unittest.mock.ANY + ) + + def test_bidi_read_object_generation_precondition_failed(self): + # Create object in database to read. + media = TestGrpc._create_block(1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test BidiReadObject with invalid object generation match precondition. + invalid_generation_match = 0 + offset_1 = 0 + limit_1 = 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + if_generation_match=invalid_generation_match, + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + ], + ) + # The code depends on `context.abort()` raising an exception. + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiReadObject([r1], context=context) + list(streamer) + context.abort.assert_called_once_with( + grpc.StatusCode.FAILED_PRECONDITION, unittest.mock.ANY + ) + if __name__ == "__main__": unittest.main() From 86e722966bb51b0bfccf9accf55e69e2019156c4 Mon Sep 17 00:00:00 2001 From: cojenco Date: Thu, 29 Aug 2024 15:58:10 -0700 Subject: [PATCH 08/39] feat: pack BidiReadObjectError in error details for out of range (#11) * feat: pack BidiReadObjectError in error details for out of range * review comments --- setup.py | 1 + testbench/grpc_server.py | 47 +++++++++++---- tests/test_grpc_server.py | 123 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index a2a83c56..2193bdfa 100644 --- a/setup.py +++ b/setup.py @@ -44,6 +44,7 @@ python_requires=">=3.8", install_requires=[ "grpcio==1.62.2", + "grpcio-status==1.62.2", "googleapis-common-protos==1.63.0", "protobuf==4.25.3", "flask==3.0.3", diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index adf369f0..1bb41be1 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -21,11 +21,15 @@ import uuid from collections.abc import Iterable from concurrent import futures +from queue import PriorityQueue import crc32c +import google.protobuf.any_pb2 as any_pb2 import google.protobuf.empty_pb2 as empty_pb2 import grpc from google.protobuf import field_mask_pb2, json_format, text_format +from google.rpc import status_pb2 +from grpc_status import rpc_status import gcs import testbench @@ -581,8 +585,6 @@ def BidiReadObject(self, request_iterator, context): # A PriorityQueue holds tuples (offset, response) where the offset serves as the priority predicate. # A response is removed from the queue with the lowest offset. This will help guarantee that # responses with the same read_id will be delivered in increasing offset order. - from queue import PriorityQueue - responses = PriorityQueue() # TBD: yield_size is configurable and is used to emulate interleaved responses. yield_size = 1 @@ -597,14 +599,14 @@ def process_read_range(range, metadata=None): read_end = len(blob.media) read_id = range.read_id - if start > read_end: - # TODO: Error handling, return a list of read_range_errors in BidiReadObjectError. - return testbench.error.range_not_satisfiable(context) - if range.read_limit < 0: - # TODO: Error handling, return a list of read_range_errors in BidiReadObjectError. - # A negative read_limit will cause an error. - return testbench.error.range_not_satisfiable(context) - elif range.read_limit > 0: + if start > read_end or range.read_limit < 0: + status_msg = self._pack_bidiread_error_details( + range, grpc.StatusCode.OUT_OF_RANGE + ) + grpc_status = rpc_status.to_status(status_msg) + return context.abort(grpc_status) + + if range.read_limit > 0: # read_limit is the maximum number of data bytes the server is allowed to return across all response messages with the same read_id. read_end = min(read_end, start + range.read_limit) @@ -671,6 +673,31 @@ def process_read_range(range, metadata=None): item = responses.get() yield item[1] + def _to_read_range_error_proto(self, range, status_code): + return storage_pb2.ReadRangeError( + read_id=range.read_id, + status={ + "code": status_code.value[0], + "message": status_code.value[1], + }, + ) + + def _pack_bidiread_error_details(self, range, status_code): + range_read_error = self._to_read_range_error_proto(range, status_code) + code = status_code.value[0] + message = status_code.value[1] + detail = any_pb2.Any() + detail.Pack( + storage_pb2.BidiReadObjectError( + read_range_errors=[range_read_error], + ) + ) + return status_pb2.Status( + code=code, + message=message, + details=[detail], + ) + @retry_test(method="storage.objects.patch") def UpdateObject(self, request, context): intersection = field_mask_pb2.FieldMask( diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 8b74a2be..709ba60b 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -24,6 +24,7 @@ import crc32c import grpc +import grpc_status from google.protobuf import field_mask_pb2, timestamp_pb2 import gcs @@ -2441,6 +2442,128 @@ def test_bidi_read_object_generation_precondition_failed(self): grpc.StatusCode.FAILED_PRECONDITION, unittest.mock.ANY ) + def test_bidi_read_object_out_of_order(self): + # Create object in database to read. + media = TestGrpc._create_block(6 * 1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test n ranges in 1 stream, where n=3. Test range requests offsets are out of order. + offset_1 = 0 + limit_1 = 3 * 1024 * 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + offset_2 = 4 * 1024 * 1024 + limit_2 = 1024 + read_id_2 = read_id_1 - 1 + offset_3 = 5 * 1024 * 1024 + limit_3 = 1 + read_id_3 = read_id_1 + 1 + + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + storage_pb2.ReadRange( + read_offset=offset_3, + read_limit=limit_3, + read_id=read_id_3, + ), + ], + ) + r2 = storage_pb2.BidiReadObjectRequest( + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_2, + read_limit=limit_2, + read_id=read_id_2, + ), + ], + ) + + streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) + responses = list(streamer) + read_range_1 = responses[0].object_data_ranges[0].read_range + data_1 = responses[0].object_data_ranges[0].checksummed_data + self.assertEqual(read_id_1, read_range_1.read_id) + self.assertEqual(offset_1, read_range_1.read_offset) + self.assertEqual(limit_1, read_range_1.read_limit) + self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) + read_range_last = responses[-1].object_data_ranges[-1].read_range + data_last = responses[-1].object_data_ranges[-1].checksummed_data + self.assertEqual(read_id_3, read_range_last.read_id) + self.assertEqual(offset_3, read_range_last.read_offset) + self.assertEqual(limit_3, read_range_last.read_limit) + self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) + + def test_bidi_read_out_of_range_error(self): + # Create object in database to read. + media = TestGrpc._create_block(1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test out-of-range offset. + offset_1 = 8 * 1024 * 1024 + limit_1 = 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + ], + ) + # Test out-of-range with negative read limit. + limit_2 = -2048 + offset_2 = 10 + read_id_2 = read_id_1 + 1 + r2 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_2, + read_limit=limit_2, + read_id=read_id_2, + ), + ], + ) + + for request in [r1, r2]: + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiReadObject([request], context=context) + list(streamer) + + context.abort.assert_called_once() + abort_status = context.abort.call_args[0][0] + grpc_status_details_bin = abort_status.trailing_metadata[0][1] + self.assertIsInstance(abort_status, grpc_status.rpc_status._Status) + self.assertIn(grpc.StatusCode.OUT_OF_RANGE, abort_status) + self.assertIn(b"BidiReadObjectError", grpc_status_details_bin) + if __name__ == "__main__": unittest.main() From 0545b7059039d0aba8132826fffd2a017329782c Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 9 Sep 2024 17:03:22 -0400 Subject: [PATCH 09/39] fix(grpc_server): Higher fidelity BidiReadObject. (#12) * fix(grpc_server): Higher fidelity BidiReadObject. The emulator behaved slightly differently than the real implementation. This brings its behavior on first message closer to the spec. --- testbench/grpc_server.py | 158 +++++++++++++++++------------- tests/test_grpc_server.py | 196 +++++++++++++------------------------- 2 files changed, 154 insertions(+), 200 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 1bb41be1..fd8cffb2 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -21,7 +21,8 @@ import uuid from collections.abc import Iterable from concurrent import futures -from queue import PriorityQueue +from queue import Queue +from threading import Thread import crc32c import google.protobuf.any_pb2 as any_pb2 @@ -582,16 +583,46 @@ def ReadObject(self, request, context): start = start + size def BidiReadObject(self, request_iterator, context): - # A PriorityQueue holds tuples (offset, response) where the offset serves as the priority predicate. - # A response is removed from the queue with the lowest offset. This will help guarantee that - # responses with the same read_id will be delivered in increasing offset order. - responses = PriorityQueue() - # TBD: yield_size is configurable and is used to emulate interleaved responses. - yield_size = 1 - - # Helper function that processes ReadRange. This could potentially become the target function - # when we introduce multiple workers. - def process_read_range(range, metadata=None): + # handle first message + try: + first_message = next(request_iterator) + except StopIteration: + # ok if no messages arrive from the client. + return + + obj_spec = first_message.read_object_spec + blob = self.db.get_object( + obj_spec.bucket, + obj_spec.object, + context=context, + generation=obj_spec.generation, + preconditions=testbench.common.make_grpc_preconditions(obj_spec), + ) + metadata = blob.metadata + + # first_response is protected by GIL + first_response = True + + def response(resp): + nonlocal first_response + if first_response: + first_response = False + resp.metadata.CopyFrom(metadata) + resp.read_handle.handle = b"an-opaque-handle" + # We ignore the read_mask for this test server + return resp + + if not first_message.read_ranges: + # always emit a response to the first request. + yield response(storage_pb2.BidiReadObjectResponse()) + + # Start handling async requests. maxsize=1 means that concurrent + # requests have a chance of blocking and therefore interleaving with one + # another. + responses = Queue(maxsize=1) + + def process_read_range(range): + nonlocal responses size = storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES # A read range corresponds to a unique read_id. # For the same read_id, it is guaranteed that responses are delivered in increasing offset order. @@ -604,74 +635,65 @@ def process_read_range(range, metadata=None): range, grpc.StatusCode.OUT_OF_RANGE ) grpc_status = rpc_status.to_status(status_msg) - return context.abort(grpc_status) + responses.put(("abort", grpc_status)) + return if range.read_limit > 0: # read_limit is the maximum number of data bytes the server is allowed to return across all response messages with the same read_id. read_end = min(read_end, start + range.read_limit) - while start <= read_end: + while start < read_end: end = min(start + size, read_end) chunk = blob.media[start:end] # Verify if there are no more bytes to read for the given ReadRange. - range_end = True if end == read_end else False - res = storage_pb2.BidiReadObjectResponse( - object_data_ranges=[ - storage_pb2.ObjectRangeData( - checksummed_data=storage_pb2.ChecksummedData( - content=chunk, - crc32c=crc32c.crc32c(chunk), + range_end = end == read_end + res = response( + storage_pb2.BidiReadObjectResponse( + object_data_ranges=[ + storage_pb2.ObjectRangeData( + checksummed_data=storage_pb2.ChecksummedData( + content=chunk, + crc32c=crc32c.crc32c(chunk), + ), + read_range=storage_pb2.ReadRange( + read_offset=start, + read_limit=range.read_limit, + read_id=read_id, + ), + range_end=range_end, ), - read_range=storage_pb2.ReadRange( - read_offset=start, - read_limit=range.read_limit, - read_id=read_id, - ), - range_end=range_end, - ), - ], - metadata=metadata, + ], + ) ) - # Put tuple (offset, response) into the priority queue. - responses.put((start, res)) - start = end + 1 - - # Handle first request message. - first_message = next(request_iterator) - obj_spec = first_message.read_object_spec - blob = self.db.get_object( - obj_spec.bucket, - obj_spec.object, - context=context, - generation=obj_spec.generation, - preconditions=testbench.common.make_grpc_preconditions(obj_spec), + responses.put(("respond", res)) + start = end + + def gather_requests(initial_ranges): + nonlocal responses + with futures.ThreadPoolExecutor() as readers: + for range in initial_ranges: + readers.submit(process_read_range, range) + for request in request_iterator: + for range in request.read_ranges: + readers.submit(process_read_range, range) + responses.put(("terminate", None)) + + gather_thread = Thread( + target=gather_requests, args=(first_message.read_ranges,) ) - metadata = blob.metadata - for range in first_message.read_ranges: - process_read_range(range, metadata=metadata) - # Let's start returning some responses. - while responses.qsize() > yield_size: - item = responses.get() - yield item[1] - - # Handle incoming requests, after finshing processing the first message. - for request in request_iterator: - for range in request.read_ranges: - process_read_range(range) - # Let's start returning some responses. Response messages per read_id are put into - # the priority queue altogether before yielding. - # Not all responses are dequeued, and will result in interleaved responses. - while responses.qsize() > yield_size: - item = responses.get() - yield item[1] - while responses.qsize() > yield_size: - item = responses.get() - yield item[1] - - # Finally, let's make sure all responses in the priority queue are returned. - while not responses.empty(): - item = responses.get() - yield item[1] + try: + gather_thread.start() + + while True: + action, resp = responses.get() + if action == "terminate": + break + elif action == "respond": + yield response(resp) + elif action == "abort": + context.abort(resp) + finally: + gather_thread.join() def _to_read_range_error_proto(self, range, status_code): return storage_pb2.ReadRangeError( diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 709ba60b..f802fb1e 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -16,9 +16,11 @@ """Unit test for testbench.grpc.""" +import collections import datetime import json import os +import time import unittest import unittest.mock @@ -2276,82 +2278,22 @@ def test_bidi_read_object(self): ) streamer = self.grpc.BidiReadObject([r1], context=self.mock_context()) - responses = list(streamer) - read_range_1 = responses[0].object_data_ranges[0].read_range - data_1 = responses[0].object_data_ranges[0].checksummed_data - self.assertEqual(read_id_1, read_range_1.read_id) - self.assertEqual(offset_1, read_range_1.read_offset) - self.assertEqual(limit_1, read_range_1.read_limit) - self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) - read_range_last = responses[-1].object_data_ranges[-1].read_range - data_last = responses[-1].object_data_ranges[-1].checksummed_data - self.assertEqual(read_id_2, read_range_last.read_id) - self.assertEqual(offset_2, read_range_last.read_offset) - self.assertEqual(limit_2, read_range_last.read_limit) - self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) - - def test_bidi_read_object_out_of_order(self): - # Create object in database to read. - media = TestGrpc._create_block(6 * 1024 * 1024).encode("utf-8") - request = testbench.common.FakeRequest( - args={"name": "object-name"}, data=media, headers={}, environ={} - ) - blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) - self.db.insert_object("bucket-name", blob, None) + returned_by_readid = { + read_id_1: offset_1, + read_id_2: offset_2, + } + for resp in streamer: + for range in resp.object_data_ranges: + read_id = range.read_range.read_id + offset = range.read_range.read_offset + self.assertEqual(returned_by_readid[read_id], offset) - # Test n ranges in 1 stream, where n=3. Test range requests offsets are out of order. - offset_1 = 0 - limit_1 = 3 * 1024 * 1024 - read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) - offset_2 = 4 * 1024 * 1024 - limit_2 = 1024 - read_id_2 = read_id_1 - 1 - offset_3 = 5 * 1024 * 1024 - limit_3 = 1 - read_id_3 = read_id_1 + 1 + data = range.checksummed_data + self.assertEqual(crc32c.crc32c(data.content), data.crc32c) + returned_by_readid[read_id] += len(data.content) - r1 = storage_pb2.BidiReadObjectRequest( - read_object_spec=storage_pb2.BidiReadObjectSpec( - bucket="projects/_/buckets/bucket-name", - object="object-name", - ), - read_ranges=[ - storage_pb2.ReadRange( - read_offset=offset_1, - read_limit=limit_1, - read_id=read_id_1, - ), - storage_pb2.ReadRange( - read_offset=offset_3, - read_limit=limit_3, - read_id=read_id_3, - ), - ], - ) - r2 = storage_pb2.BidiReadObjectRequest( - read_ranges=[ - storage_pb2.ReadRange( - read_offset=offset_2, - read_limit=limit_2, - read_id=read_id_2, - ), - ], - ) - - streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) - responses = list(streamer) - read_range_1 = responses[0].object_data_ranges[0].read_range - data_1 = responses[0].object_data_ranges[0].checksummed_data - self.assertEqual(read_id_1, read_range_1.read_id) - self.assertEqual(offset_1, read_range_1.read_offset) - self.assertEqual(limit_1, read_range_1.read_limit) - self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) - read_range_last = responses[-1].object_data_ranges[-1].read_range - data_last = responses[-1].object_data_ranges[-1].checksummed_data - self.assertEqual(read_id_3, read_range_last.read_id) - self.assertEqual(offset_3, read_range_last.read_offset) - self.assertEqual(limit_3, read_range_last.read_limit) - self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) + self.assertEqual(returned_by_readid[read_id_1], offset_1 + limit_1) + self.assertEqual(returned_by_readid[read_id_2], offset_2 + limit_2) def test_bidi_read_object_not_found(self): # Test BidiReadObject with non-existent object. @@ -2442,68 +2384,58 @@ def test_bidi_read_object_generation_precondition_failed(self): grpc.StatusCode.FAILED_PRECONDITION, unittest.mock.ANY ) - def test_bidi_read_object_out_of_order(self): - # Create object in database to read. - media = TestGrpc._create_block(6 * 1024 * 1024).encode("utf-8") - request = testbench.common.FakeRequest( - args={"name": "object-name"}, data=media, headers={}, environ={} - ) - blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) - self.db.insert_object("bucket-name", blob, None) + def test_bidi_read_object_interleaves_responses(self): + # This lets the test pass in a reasonale amount of time - otherwise the + # test harness prints a _lot_ to stdout. + OLD_CHUNK = storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES + try: + CHUNK = 100 + storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES = CHUNK + # 100 ranges of 2 chunks each. Empirically, that makes this test + # flake fewer than 1 in 10,000 runs. + media = TestGrpc._create_block(100 * 2 * CHUNK).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": f"object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) - # Test n ranges in 1 stream, where n=3. Test range requests offsets are out of order. - offset_1 = 0 - limit_1 = 3 * 1024 * 1024 - read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) - offset_2 = 4 * 1024 * 1024 - limit_2 = 1024 - read_id_2 = read_id_1 - 1 - offset_3 = 5 * 1024 * 1024 - limit_3 = 1 - read_id_3 = read_id_1 + 1 + def make_2_chunk_range(i): + return storage_pb2.ReadRange( + read_offset=2 * CHUNK * i, + read_limit=2 * CHUNK, + read_id=i, + ) - r1 = storage_pb2.BidiReadObjectRequest( - read_object_spec=storage_pb2.BidiReadObjectSpec( - bucket="projects/_/buckets/bucket-name", - object="object-name", - ), - read_ranges=[ - storage_pb2.ReadRange( - read_offset=offset_1, - read_limit=limit_1, - read_id=read_id_1, - ), - storage_pb2.ReadRange( - read_offset=offset_3, - read_limit=limit_3, - read_id=read_id_3, - ), - ], - ) - r2 = storage_pb2.BidiReadObjectRequest( - read_ranges=[ - storage_pb2.ReadRange( - read_offset=offset_2, - read_limit=limit_2, - read_id=read_id_2, + first_read_ranges = [make_2_chunk_range(i) for i in range(50)] + second_read_ranges = [make_2_chunk_range(i) for i in range(50, 100)] + + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", ), - ], - ) + read_ranges=first_read_ranges, + ) + r2 = storage_pb2.BidiReadObjectRequest( + read_ranges=second_read_ranges, + ) - streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) - responses = list(streamer) - read_range_1 = responses[0].object_data_ranges[0].read_range - data_1 = responses[0].object_data_ranges[0].checksummed_data - self.assertEqual(read_id_1, read_range_1.read_id) - self.assertEqual(offset_1, read_range_1.read_offset) - self.assertEqual(limit_1, read_range_1.read_limit) - self.assertEqual(crc32c.crc32c(data_1.content), data_1.crc32c) - read_range_last = responses[-1].object_data_ranges[-1].read_range - data_last = responses[-1].object_data_ranges[-1].checksummed_data - self.assertEqual(read_id_3, read_range_last.read_id) - self.assertEqual(offset_3, read_range_last.read_offset) - self.assertEqual(limit_3, read_range_last.read_limit) - self.assertEqual(crc32c.crc32c(data_last.content), data_last.crc32c) + def response_to_ranges(resp): + return [ + (range.read_range.read_id, range.read_range.read_offset) + for range in resp.object_data_ranges + ] + + streamer = self.grpc.BidiReadObject([r1, r2], context=self.mock_context()) + response_ranges = [response_to_ranges(resp) for resp in list(streamer)] + self.assertNotEqual(sorted(response_ranges), response_ranges) + finally: + storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES = OLD_CHUNK + + def test_bidi_read_no_messages_sent(self): + streamer = self.grpc.BidiReadObject([], context=self.mock_context()) + self.assertEqual(len(list(streamer)), 0) # No responses, does not raise def test_bidi_read_out_of_range_error(self): # Create object in database to read. From 7f92a5eeb1b3a7706fab0e4ceeafcd90b1257559 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Tue, 10 Sep 2024 16:32:30 -0400 Subject: [PATCH 10/39] feat(appendable): Appendable object proto support (#13) Patch the BidiWriteObject protos to support appendable object BidiWriteObject RPCs. While I'm here, update `setup.py` to pin the correct version of grpcio-tools for proto compilation, and have `update-protos.sh` use the already `.gitignore`'d directory `.googleapis` as the base if none is specified. --- bidi-appendable-write.patch | 116 +++++++++++++ google/storage/v2/storage_pb2.py | 270 ++++++++++++++++--------------- setup.py | 1 + update-protos.sh | 12 +- 4 files changed, 266 insertions(+), 133 deletions(-) create mode 100644 bidi-appendable-write.patch diff --git a/bidi-appendable-write.patch b/bidi-appendable-write.patch new file mode 100644 index 00000000..143eb3a5 --- /dev/null +++ b/bidi-appendable-write.patch @@ -0,0 +1,116 @@ +diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto +index c9c027345..0bcd970e0 100644 +--- a/google/storage/v2/storage.proto ++++ b/google/storage/v2/storage.proto +@@ -1177,6 +1171,22 @@ message BidiReadObjectRedirectedError { + optional string routing_token = 2; + } + ++// Error proto containing details for a redirected write. This error is only ++// returned on initial open in case of a redirect. ++message BidiWriteObjectRedirectedError { ++ // The routing token that should be used when reopening the write stream. ++ optional string routing_token = 1; ++ ++ // Opaque value describing a previous write. ++ optional BidiWriteHandle write_handle = 2; ++ ++ // The generation of the object that triggered the redirect. ++ // Note that if this error was returned as part of an appendable object ++ // create, this object generation is now successfully created and ++ // append_object_spec should be used when reconnecting. ++ optional int64 generation = 3; ++} ++ + // Error extension proto containing details for all outstanding reads on the + // failed stream + message BidiReadObjectError { +@@ -1246,6 +1262,14 @@ message BidiReadHandle { + bytes handle = 1 [(google.api.field_behavior) = REQUIRED]; + } + ++// BidiWriteHandle contains a handle from a previous BidiWriteObject ++// invocation. The client can use this as an optimized way of opening subsequent ++// bidirectional streams to the same object. ++message BidiWriteHandle { ++ // Opaque value describing a previous write. ++ bytes handle = 1; ++} ++ + // Describes an attempt to insert an object, possibly over multiple requests. + message WriteObjectSpec { + // Required. Destination object, including its name and its metadata. +@@ -1283,6 +1307,12 @@ message WriteObjectSpec { + // you must start the upload over from scratch, this time sending the correct + // number of bytes. + optional int64 object_size = 8; ++ ++ // If true, the object will be created in appendable mode. ++ // This field may only be set when using BidiWriteObject. ++ optional bool appendable = 9; ++ ++ reserved 2; + } + + // Request message for WriteObject. +@@ -1352,6 +1382,38 @@ message WriteObjectResponse { + } + } + ++// Describes an attempt to append to an object, possibly over multiple requests. ++message AppendObjectSpec { ++ // The name of the bucket containing the object to write. ++ string bucket = 1 [ ++ (google.api.resource_reference).type = "storage.googleapis.com/Bucket" ++ ]; ++ ++ // The name of the object to open for writing. ++ string object = 2 [ ++ (google.api.field_behavior) = REQUIRED ++ ]; ++ ++ // The generation number of the object to open for writing. ++ int64 generation = 3 [(google.api.field_behavior) = REQUIRED]; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration matches the given value. ++ optional int64 if_metageneration_match = 4; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration does not match the given value. ++ optional int64 if_metageneration_not_match = 5; ++ ++ // An optional routing token that influences request routing for the stream. ++ // Must be provided if a BidiWriteObjectRedirectedError is returned. ++ optional string routing_token = 6; ++ ++ // An optional write handle returned from a previous BidiWriteObjectResponse ++ // message or a BidiWriteObjectRedirectedError error. ++ optional BidiWriteHandle write_handle = 7; ++} ++ + // Request message for BidiWriteObject. + message BidiWriteObjectRequest { + // The first message of each stream should set one of the following. +@@ -1363,6 +1434,9 @@ message BidiWriteObjectRequest { + // For non-resumable uploads. Describes the overall upload, including the + // destination bucket and object name, preconditions, etc. + WriteObjectSpec write_object_spec = 2; ++ ++ // For appendable uploads. Describes the object to append to. ++ AppendObjectSpec append_object_spec = 11; + } + + // Required. The offset from the beginning of the object at which the data +@@ -1435,6 +1509,11 @@ message BidiWriteObjectResponse { + // the upload has finalized. + Object resource = 2; + } ++ ++ // An optional write handle that will periodically be present in response ++ // messages. Clients should save it for later use in establishing a new stream ++ // if a connection is interrupted. ++ optional BidiWriteHandle write_handle = 3; + } + + // Request message for ListObjects. diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index cc6e77e5..40420d1f 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -40,7 +40,7 @@ from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x8d\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"\x8d\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_size\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xaf\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"r\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xc6(\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"b\n\x1f\x44\x65leteNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"_\n\x1cGetNotificationConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/NotificationConfig\"\xad\x01\n\x1f\x43reateNotificationConfigRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12G\n\x13notification_config\x18\x02 \x01(\x0b\x32%.google.storage.v2.NotificationConfigB\x03\xe0\x41\x02\"\x8a\x01\n\x1eListNotificationConfigsRequest\x12\x41\n\x06parent\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\x12)storage.googleapis.com/NotificationConfig\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"\x7f\n\x1fListNotificationConfigsResponse\x12\x43\n\x14notification_configs\x18\x01 \x03(\x0b\x32%.google.storage.v2.NotificationConfig\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x89\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xbc\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x8d\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xbb\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendableJ\x04\x08\x02\x10\x03\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xfe\x02\n\x10\x41ppendObjectSpec\x12\x32\n\x06\x62ucket\x18\x01 \x01(\tB\"\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"`\n\x18GetServiceAccountRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\x80\x01\n\x14\x43reateHmacKeyRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x02 \x01(\tB\x03\xe0\x41\x02\"g\n\x15\x43reateHmacKeyResponse\x12\x34\n\x08metadata\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x18\n\x10secret_key_bytes\x18\x03 \x01(\x0c\"t\n\x14\x44\x65leteHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"q\n\x11GetHmacKeyRequest\x12\x16\n\taccess_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x44\n\x07project\x18\x02 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\"\xbc\x01\n\x13ListHmacKeysRequest\x12\x44\n\x07project\x18\x01 \x01(\tB3\xe0\x41\x02\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1d\n\x15service_account_email\x18\x04 \x01(\t\x12\x19\n\x11show_deleted_keys\x18\x05 \x01(\x08\"f\n\x14ListHmacKeysResponse\x12\x35\n\thmac_keys\x18\x01 \x03(\x0b\x32\".google.storage.v2.HmacKeyMetadata\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x82\x01\n\x14UpdateHmacKeyRequest\x12\x39\n\x08hmac_key\x18\x01 \x01(\x0b\x32\".google.storage.v2.HmacKeyMetadataB\x03\xe0\x41\x02\x12/\n\x0bupdate_mask\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\x92\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:G\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"\xad\x02\n\x0fHmacKeyMetadata\x12\x0f\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\taccess_id\x18\x02 \x01(\tB\x03\xe0\x41\x05\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\"\n\x15service_account_email\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12\r\n\x05state\x18\x05 \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\"\xa7\x03\n\x12NotificationConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\x05topic\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x0c\n\x04\x65tag\x18\x07 \x01(\t\x12\x13\n\x0b\x65vent_types\x18\x03 \x03(\t\x12V\n\x11\x63ustom_attributes\x18\x04 \x03(\x0b\x32;.google.storage.v2.NotificationConfig.CustomAttributesEntry\x12\x1a\n\x12object_name_prefix\x18\x05 \x01(\t\x12\x1b\n\x0epayload_format\x18\x06 \x01(\tB\x03\xe0\x41\x02\x1a\x37\n\x15\x43ustomAttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:}\xea\x41z\n)storage.googleapis.com/NotificationConfig\x12Mprojects/{project}/buckets/{bucket}/notificationConfigs/{notification_config}\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xac\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x00\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"\'\n\x0eServiceAccount\x12\x15\n\remail_address\x18\x01 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xc6(\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\xd7\x01\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"l\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02O\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12\x9f\x01\n\x18\x44\x65leteNotificationConfig\x12\x32.google.storage.v2.DeleteNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa8\x01\n\x15GetNotificationConfig\x12/.google.storage.v2.GetNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x18\x43reateNotificationConfig\x12\x32.google.storage.v2.CreateNotificationConfigRequest\x1a%.google.storage.v2.NotificationConfig\":\xda\x41\x1aparent,notification_config\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xa8\x01\n\x17ListNotificationConfigs\x12\x31.google.storage.v2.ListNotificationConfigsRequest\x1a\x32.google.storage.v2.ListNotificationConfigsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x80\x01\n\x11GetServiceAccount\x12+.google.storage.v2.GetServiceAccountRequest\x1a!.google.storage.v2.ServiceAccount\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x95\x01\n\rCreateHmacKey\x12\'.google.storage.v2.CreateHmacKeyRequest\x1a(.google.storage.v2.CreateHmacKeyResponse\"1\xda\x41\x1dproject,service_account_email\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12w\n\rDeleteHmacKey\x12\'.google.storage.v2.DeleteHmacKeyRequest\x1a\x16.google.protobuf.Empty\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12}\n\nGetHmacKey\x12$.google.storage.v2.GetHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"%\xda\x41\x11\x61\x63\x63\x65ss_id,project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12|\n\x0cListHmacKeys\x12&.google.storage.v2.ListHmacKeysRequest\x1a\'.google.storage.v2.ListHmacKeysResponse\"\x1b\xda\x41\x07project\x8a\xd3\xe4\x93\x02\x0b\x12\t\n\x07project\x12\x9d\x01\n\rUpdateHmacKey\x12\'.google.storage.v2.UpdateHmacKeyRequest\x1a\".google.storage.v2.HmacKeyMetadata\"?\xda\x41\x14hmac_key,update_mask\x8a\xd3\xe4\x93\x02\"\x12 \n\x10hmac_key.project\x12\x0c{project=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -132,6 +132,12 @@ _globals['_WRITEOBJECTSPEC'].fields_by_name['resource']._serialized_options = b'\340A\002' _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._options = None _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._serialized_options = b'\340A\002' + _globals['_APPENDOBJECTSPEC'].fields_by_name['bucket']._options = None + _globals['_APPENDOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\372A\037\n\035storage.googleapis.com/Bucket' + _globals['_APPENDOBJECTSPEC'].fields_by_name['object']._options = None + _globals['_APPENDOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' + _globals['_APPENDOBJECTSPEC'].fields_by_name['generation']._options = None + _globals['_APPENDOBJECTSPEC'].fields_by_name['generation']._serialized_options = b'\340A\002' _globals['_BIDIWRITEOBJECTREQUEST'].fields_by_name['write_offset']._options = None _globals['_BIDIWRITEOBJECTREQUEST'].fields_by_name['write_offset']._serialized_options = b'\340A\002' _globals['_LISTOBJECTSREQUEST'].fields_by_name['parent']._options = None @@ -394,132 +400,138 @@ _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=7071 _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=7074 _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=7207 - _globals['_BIDIREADOBJECTERROR']._serialized_start=7209 - _globals['_BIDIREADOBJECTERROR']._serialized_end=7292 - _globals['_READRANGEERROR']._serialized_start=7294 - _globals['_READRANGEERROR']._serialized_end=7363 - _globals['_READRANGE']._serialized_start=7365 - _globals['_READRANGE']._serialized_end=7449 - _globals['_OBJECTRANGEDATA']._serialized_start=7452 - _globals['_OBJECTRANGEDATA']._serialized_end=7600 - _globals['_BIDIREADHANDLE']._serialized_start=7602 - _globals['_BIDIREADHANDLE']._serialized_end=7639 - _globals['_WRITEOBJECTSPEC']._serialized_start=7642 - _globals['_WRITEOBJECTSPEC']._serialized_end=8039 - _globals['_WRITEOBJECTREQUEST']._serialized_start=8042 - _globals['_WRITEOBJECTREQUEST']._serialized_end=8432 - _globals['_WRITEOBJECTRESPONSE']._serialized_start=8434 - _globals['_WRITEOBJECTRESPONSE']._serialized_end=8544 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8547 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=8978 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=8980 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9094 - _globals['_LISTOBJECTSREQUEST']._serialized_start=9097 - _globals['_LISTOBJECTSREQUEST']._serialized_end=9526 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9529 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9662 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9664 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=9779 - _globals['_REWRITEOBJECTREQUEST']._serialized_start=9782 - _globals['_REWRITEOBJECTREQUEST']._serialized_end=11102 - _globals['_REWRITERESPONSE']._serialized_start=11105 - _globals['_REWRITERESPONSE']._serialized_end=11256 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11259 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11501 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11503 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11551 - _globals['_UPDATEOBJECTREQUEST']._serialized_start=11554 - _globals['_UPDATEOBJECTREQUEST']._serialized_end=12049 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=12051 - _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=12147 - _globals['_CREATEHMACKEYREQUEST']._serialized_start=12150 - _globals['_CREATEHMACKEYREQUEST']._serialized_end=12278 - _globals['_CREATEHMACKEYRESPONSE']._serialized_start=12280 - _globals['_CREATEHMACKEYRESPONSE']._serialized_end=12383 - _globals['_DELETEHMACKEYREQUEST']._serialized_start=12385 - _globals['_DELETEHMACKEYREQUEST']._serialized_end=12501 - _globals['_GETHMACKEYREQUEST']._serialized_start=12503 - _globals['_GETHMACKEYREQUEST']._serialized_end=12616 - _globals['_LISTHMACKEYSREQUEST']._serialized_start=12619 - _globals['_LISTHMACKEYSREQUEST']._serialized_end=12807 - _globals['_LISTHMACKEYSRESPONSE']._serialized_start=12809 - _globals['_LISTHMACKEYSRESPONSE']._serialized_end=12911 - _globals['_UPDATEHMACKEYREQUEST']._serialized_start=12914 - _globals['_UPDATEHMACKEYREQUEST']._serialized_end=13044 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=13046 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=13170 - _globals['_SERVICECONSTANTS']._serialized_start=13173 - _globals['_SERVICECONSTANTS']._serialized_end=13887 - _globals['_SERVICECONSTANTS_VALUES']._serialized_start=13194 - _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13887 - _globals['_BUCKET']._serialized_start=13890 - _globals['_BUCKET']._serialized_end=17492 - _globals['_BUCKET_BILLING']._serialized_start=15331 - _globals['_BUCKET_BILLING']._serialized_end=15364 - _globals['_BUCKET_CORS']._serialized_start=15366 - _globals['_BUCKET_CORS']._serialized_end=15454 - _globals['_BUCKET_ENCRYPTION']._serialized_start=15456 - _globals['_BUCKET_ENCRYPTION']._serialized_end=15533 - _globals['_BUCKET_IAMCONFIG']._serialized_start=15536 - _globals['_BUCKET_IAMCONFIG']._serialized_end=15772 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=15682 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15772 - _globals['_BUCKET_LIFECYCLE']._serialized_start=15775 - _globals['_BUCKET_LIFECYCLE']._serialized_end=16530 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15845 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=16530 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15989 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=16034 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=16037 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=16530 - _globals['_BUCKET_LOGGING']._serialized_start=16532 - _globals['_BUCKET_LOGGING']._serialized_end=16588 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=16591 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=16734 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=16737 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16914 - _globals['_BUCKET_VERSIONING']._serialized_start=16916 - _globals['_BUCKET_VERSIONING']._serialized_end=16945 - _globals['_BUCKET_WEBSITE']._serialized_start=16947 - _globals['_BUCKET_WEBSITE']._serialized_end=17006 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=17008 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=17055 - _globals['_BUCKET_AUTOCLASS']._serialized_start=17058 - _globals['_BUCKET_AUTOCLASS']._serialized_end=17325 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=17327 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=17372 - _globals['_BUCKET_LABELSENTRY']._serialized_start=17374 - _globals['_BUCKET_LABELSENTRY']._serialized_end=17419 - _globals['_BUCKETACCESSCONTROL']._serialized_start=17495 - _globals['_BUCKETACCESSCONTROL']._serialized_end=17701 - _globals['_CHECKSUMMEDDATA']._serialized_start=17703 - _globals['_CHECKSUMMEDDATA']._serialized_end=17776 - _globals['_OBJECTCHECKSUMS']._serialized_start=17778 - _globals['_OBJECTCHECKSUMS']._serialized_end=17845 - _globals['_HMACKEYMETADATA']._serialized_start=17848 - _globals['_HMACKEYMETADATA']._serialized_end=18149 - _globals['_NOTIFICATIONCONFIG']._serialized_start=18152 - _globals['_NOTIFICATIONCONFIG']._serialized_end=18575 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=18393 - _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=18448 - _globals['_CUSTOMERENCRYPTION']._serialized_start=18577 - _globals['_CUSTOMERENCRYPTION']._serialized_end=18653 - _globals['_OBJECT']._serialized_start=18656 - _globals['_OBJECT']._serialized_end=19980 - _globals['_OBJECT_METADATAENTRY']._serialized_start=19870 - _globals['_OBJECT_METADATAENTRY']._serialized_end=19917 - _globals['_OBJECTACCESSCONTROL']._serialized_start=19983 - _globals['_OBJECTACCESSCONTROL']._serialized_end=20189 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=20191 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=20299 - _globals['_PROJECTTEAM']._serialized_start=20301 - _globals['_PROJECTTEAM']._serialized_end=20352 - _globals['_SERVICEACCOUNT']._serialized_start=20354 - _globals['_SERVICEACCOUNT']._serialized_end=20393 - _globals['_OWNER']._serialized_start=20395 - _globals['_OWNER']._serialized_end=20437 - _globals['_CONTENTRANGE']._serialized_start=20439 - _globals['_CONTENTRANGE']._serialized_end=20506 - _globals['_STORAGE']._serialized_start=20509 - _globals['_STORAGE']._serialized_end=25699 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_start=7210 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_end=7408 + _globals['_BIDIREADOBJECTERROR']._serialized_start=7410 + _globals['_BIDIREADOBJECTERROR']._serialized_end=7493 + _globals['_READRANGEERROR']._serialized_start=7495 + _globals['_READRANGEERROR']._serialized_end=7564 + _globals['_READRANGE']._serialized_start=7566 + _globals['_READRANGE']._serialized_end=7650 + _globals['_OBJECTRANGEDATA']._serialized_start=7653 + _globals['_OBJECTRANGEDATA']._serialized_end=7801 + _globals['_BIDIREADHANDLE']._serialized_start=7803 + _globals['_BIDIREADHANDLE']._serialized_end=7840 + _globals['_BIDIWRITEHANDLE']._serialized_start=7842 + _globals['_BIDIWRITEHANDLE']._serialized_end=7875 + _globals['_WRITEOBJECTSPEC']._serialized_start=7878 + _globals['_WRITEOBJECTSPEC']._serialized_end=8321 + _globals['_WRITEOBJECTREQUEST']._serialized_start=8324 + _globals['_WRITEOBJECTREQUEST']._serialized_end=8714 + _globals['_WRITEOBJECTRESPONSE']._serialized_start=8716 + _globals['_WRITEOBJECTRESPONSE']._serialized_end=8826 + _globals['_APPENDOBJECTSPEC']._serialized_start=8829 + _globals['_APPENDOBJECTSPEC']._serialized_end=9211 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=9214 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=9712 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=9715 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9909 + _globals['_LISTOBJECTSREQUEST']._serialized_start=9912 + _globals['_LISTOBJECTSREQUEST']._serialized_end=10341 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=10344 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=10477 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=10479 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=10594 + _globals['_REWRITEOBJECTREQUEST']._serialized_start=10597 + _globals['_REWRITEOBJECTREQUEST']._serialized_end=11917 + _globals['_REWRITERESPONSE']._serialized_start=11920 + _globals['_REWRITERESPONSE']._serialized_end=12071 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=12074 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=12316 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=12318 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=12366 + _globals['_UPDATEOBJECTREQUEST']._serialized_start=12369 + _globals['_UPDATEOBJECTREQUEST']._serialized_end=12864 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_start=12866 + _globals['_GETSERVICEACCOUNTREQUEST']._serialized_end=12962 + _globals['_CREATEHMACKEYREQUEST']._serialized_start=12965 + _globals['_CREATEHMACKEYREQUEST']._serialized_end=13093 + _globals['_CREATEHMACKEYRESPONSE']._serialized_start=13095 + _globals['_CREATEHMACKEYRESPONSE']._serialized_end=13198 + _globals['_DELETEHMACKEYREQUEST']._serialized_start=13200 + _globals['_DELETEHMACKEYREQUEST']._serialized_end=13316 + _globals['_GETHMACKEYREQUEST']._serialized_start=13318 + _globals['_GETHMACKEYREQUEST']._serialized_end=13431 + _globals['_LISTHMACKEYSREQUEST']._serialized_start=13434 + _globals['_LISTHMACKEYSREQUEST']._serialized_end=13622 + _globals['_LISTHMACKEYSRESPONSE']._serialized_start=13624 + _globals['_LISTHMACKEYSRESPONSE']._serialized_end=13726 + _globals['_UPDATEHMACKEYREQUEST']._serialized_start=13729 + _globals['_UPDATEHMACKEYREQUEST']._serialized_end=13859 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=13861 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=13985 + _globals['_SERVICECONSTANTS']._serialized_start=13988 + _globals['_SERVICECONSTANTS']._serialized_end=14702 + _globals['_SERVICECONSTANTS_VALUES']._serialized_start=14009 + _globals['_SERVICECONSTANTS_VALUES']._serialized_end=14702 + _globals['_BUCKET']._serialized_start=14705 + _globals['_BUCKET']._serialized_end=18307 + _globals['_BUCKET_BILLING']._serialized_start=16146 + _globals['_BUCKET_BILLING']._serialized_end=16179 + _globals['_BUCKET_CORS']._serialized_start=16181 + _globals['_BUCKET_CORS']._serialized_end=16269 + _globals['_BUCKET_ENCRYPTION']._serialized_start=16271 + _globals['_BUCKET_ENCRYPTION']._serialized_end=16348 + _globals['_BUCKET_IAMCONFIG']._serialized_start=16351 + _globals['_BUCKET_IAMCONFIG']._serialized_end=16587 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=16497 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=16587 + _globals['_BUCKET_LIFECYCLE']._serialized_start=16590 + _globals['_BUCKET_LIFECYCLE']._serialized_end=17345 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=16660 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=17345 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=16804 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=16849 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=16852 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=17345 + _globals['_BUCKET_LOGGING']._serialized_start=17347 + _globals['_BUCKET_LOGGING']._serialized_end=17403 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=17406 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=17549 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=17552 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=17729 + _globals['_BUCKET_VERSIONING']._serialized_start=17731 + _globals['_BUCKET_VERSIONING']._serialized_end=17760 + _globals['_BUCKET_WEBSITE']._serialized_start=17762 + _globals['_BUCKET_WEBSITE']._serialized_end=17821 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=17823 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=17870 + _globals['_BUCKET_AUTOCLASS']._serialized_start=17873 + _globals['_BUCKET_AUTOCLASS']._serialized_end=18140 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=18142 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=18187 + _globals['_BUCKET_LABELSENTRY']._serialized_start=18189 + _globals['_BUCKET_LABELSENTRY']._serialized_end=18234 + _globals['_BUCKETACCESSCONTROL']._serialized_start=18310 + _globals['_BUCKETACCESSCONTROL']._serialized_end=18516 + _globals['_CHECKSUMMEDDATA']._serialized_start=18518 + _globals['_CHECKSUMMEDDATA']._serialized_end=18591 + _globals['_OBJECTCHECKSUMS']._serialized_start=18593 + _globals['_OBJECTCHECKSUMS']._serialized_end=18660 + _globals['_HMACKEYMETADATA']._serialized_start=18663 + _globals['_HMACKEYMETADATA']._serialized_end=18964 + _globals['_NOTIFICATIONCONFIG']._serialized_start=18967 + _globals['_NOTIFICATIONCONFIG']._serialized_end=19390 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_start=19208 + _globals['_NOTIFICATIONCONFIG_CUSTOMATTRIBUTESENTRY']._serialized_end=19263 + _globals['_CUSTOMERENCRYPTION']._serialized_start=19392 + _globals['_CUSTOMERENCRYPTION']._serialized_end=19468 + _globals['_OBJECT']._serialized_start=19471 + _globals['_OBJECT']._serialized_end=20795 + _globals['_OBJECT_METADATAENTRY']._serialized_start=20685 + _globals['_OBJECT_METADATAENTRY']._serialized_end=20732 + _globals['_OBJECTACCESSCONTROL']._serialized_start=20798 + _globals['_OBJECTACCESSCONTROL']._serialized_end=21004 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=21006 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=21114 + _globals['_PROJECTTEAM']._serialized_start=21116 + _globals['_PROJECTTEAM']._serialized_end=21167 + _globals['_SERVICEACCOUNT']._serialized_start=21169 + _globals['_SERVICEACCOUNT']._serialized_end=21208 + _globals['_OWNER']._serialized_start=21210 + _globals['_OWNER']._serialized_end=21252 + _globals['_CONTENTRANGE']._serialized_start=21254 + _globals['_CONTENTRANGE']._serialized_end=21321 + _globals['_STORAGE']._serialized_start=21324 + _globals['_STORAGE']._serialized_end=26514 # @@protoc_insertion_point(module_scope) diff --git a/setup.py b/setup.py index 2193bdfa..ec7a8f09 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ install_requires=[ "grpcio==1.62.2", "grpcio-status==1.62.2", + "grpcio-tools==1.62.2", "googleapis-common-protos==1.63.0", "protobuf==4.25.3", "flask==3.0.3", diff --git a/update-protos.sh b/update-protos.sh index 525cf110..cc9a0408 100755 --- a/update-protos.sh +++ b/update-protos.sh @@ -16,13 +16,16 @@ set -euo pipefail -if [[ $# -ne 1 ]]; then - echo "Usage: $(basename "$0") " +if [[ $# -eq 0 ]]; then + readonly GOOGLEAPIS_ROOT=".googleapis" +elif [[ $# -eq 1 ]]; then + readonly GOOGLEAPIS_ROOT="$1" +else + echo "Usage: $(basename "$0") [googleapis-root-directory]" exit 1 fi readonly PROGRAM_PATH="$0" -readonly GOOGLEAPIS_ROOT="$1" readonly INPUTS=( google/iam/v1/iam_policy.proto google/iam/v1/options.proto @@ -39,7 +42,8 @@ else git -C "${GOOGLEAPIS_ROOT}" checkout master git -C "${GOOGLEAPIS_ROOT}" pull fi -env -C .googleapis patch -p1 <$PWD/bidi-streaming-read.patch +env -C "${GOOGLEAPIS_ROOT}" patch -p1 <$PWD/bidi-streaming-read.patch +env -C "${GOOGLEAPIS_ROOT}" patch -p1 <$PWD/bidi-appendable-write.patch for input in "${INPUTS[@]}"; do python -m grpc_tools.protoc -I"${GOOGLEAPIS_ROOT}" \ From f67c33d469a88cb6082b6f41ba3ae68a90f5e475 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Tue, 24 Sep 2024 16:38:26 -0400 Subject: [PATCH 11/39] fix: Correctly handle aborts with multiple ranges. (#16) We never polled the `responses` queue after an `"abort"` message was dequeued. That can stop us from ever joining `gather_thread` if another range enqueues a response first, because the queue capacity is fixed. We want to keep the queue capacity fixed so that we can increase the likelihood of interleaving responses from multiple ranges. Fix by draining the queue in the `finally` block before reraising. Also, correct `abort` to `abort_with_status`: if the error is a `grpc.Status`, we're meant to call `context.abort_with_status` rather than `context.abort`. --- testbench/grpc_server.py | 16 +++++++--- tests/test_grpc_server.py | 66 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index fd8cffb2..d885a253 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -635,7 +635,7 @@ def process_read_range(range): range, grpc.StatusCode.OUT_OF_RANGE ) grpc_status = rpc_status.to_status(status_msg) - responses.put(("abort", grpc_status)) + responses.put(("abort_with_status", grpc_status)) return if range.read_limit > 0: @@ -681,18 +681,24 @@ def gather_requests(initial_ranges): gather_thread = Thread( target=gather_requests, args=(first_message.read_ranges,) ) + + poll_queue = True try: gather_thread.start() - while True: + while poll_queue: action, resp = responses.get() if action == "terminate": - break + poll_queue = False elif action == "respond": yield response(resp) - elif action == "abort": - context.abort(resp) + elif action == "abort_with_status": + context.abort_with_status(resp) finally: + while poll_queue: + action, _ = responses.get() + if action == "terminate": + poll_queue = False gather_thread.join() def _to_read_range_error_proto(self, range, status_code): diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index f802fb1e..31268106 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2483,19 +2483,77 @@ def test_bidi_read_out_of_range_error(self): for request in [r1, r2]: context = unittest.mock.Mock() - context.abort = unittest.mock.MagicMock() - context.abort.side_effect = grpc.RpcError() + context.abort_with_status = unittest.mock.MagicMock() + context.abort_with_status.side_effect = grpc.RpcError() with self.assertRaises(grpc.RpcError): streamer = self.grpc.BidiReadObject([request], context=context) list(streamer) - context.abort.assert_called_once() - abort_status = context.abort.call_args[0][0] + context.abort_with_status.assert_called_once() + abort_status = context.abort_with_status.call_args[0][0] grpc_status_details_bin = abort_status.trailing_metadata[0][1] self.assertIsInstance(abort_status, grpc_status.rpc_status._Status) self.assertIn(grpc.StatusCode.OUT_OF_RANGE, abort_status) self.assertIn(b"BidiReadObjectError", grpc_status_details_bin) + def test_bidi_read_one_out_of_range_one_in_range_error(self): + # Create object in database to read. + media = TestGrpc._create_block(1024 * 1024).encode("utf-8") + request = testbench.common.FakeRequest( + args={"name": "object-name"}, data=media, headers={}, environ={} + ) + blob, _ = gcs.object.Object.init_media(request, self.bucket.metadata) + self.db.insert_object("bucket-name", blob, None) + + # Test out-of-range offset. + offset_1 = 8 * 1024 * 1024 + limit_1 = 1024 + read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + ], + ) + # Test in-range offset. + offset_2 = 0 + limit_2 = 10 + read_id_2 = read_id_1 + 1 + r2 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_2, + read_limit=limit_2, + read_id=read_id_2, + ), + ], + ) + + context = unittest.mock.Mock() + context.abort_with_status = unittest.mock.MagicMock() + context.abort_with_status.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiReadObject([r1, r2], context=context) + list(streamer) + + context.abort_with_status.assert_called_once() + abort_status = context.abort_with_status.call_args[0][0] + grpc_status_details_bin = abort_status.trailing_metadata[0][1] + self.assertIsInstance(abort_status, grpc_status.rpc_status._Status) + self.assertIn(grpc.StatusCode.OUT_OF_RANGE, abort_status) + self.assertIn(b"BidiReadObjectError", grpc_status_details_bin) + if __name__ == "__main__": unittest.main() From 1bc75053b71954b8d9f6f37ff3a410d1f0fd1a77 Mon Sep 17 00:00:00 2001 From: shubham-diwakar Date: Tue, 1 Oct 2024 15:22:28 +0530 Subject: [PATCH 12/39] feat(grpc_retry): support retry bidi read object for conformance test. (#15) * pull last changes * add retry for bidi-read * remove venv * add abort * fix: Correctly handle aborts with multiple ranges. (#16) We never polled the `responses` queue after an `"abort"` message was dequeued. That can stop us from ever joining `gather_thread` if another range enqueues a response first, because the queue capacity is fixed. We want to keep the queue capacity fixed so that we can increase the likelihood of interleaving responses from multiple ranges. Fix by draining the queue in the `finally` block before reraising. Also, correct `abort` to `abort_with_status`: if the error is a `grpc.Status`, we're meant to call `context.abort_with_status` rather than `context.abort`. * push chris patch * modify tests * pull last changes * remove venv * remove lint issues * remove lint issues1 * remove lint issues2 * bring broken_stream down for better readability * remove venv --------- Co-authored-by: Chris Carlon --- testbench/grpc_server.py | 80 +++++++++++++++++++++++--------- tests/test_testbench_retry.py | 87 ++++++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 24 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index d885a253..9cff71d9 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -17,6 +17,7 @@ import functools import json import re +import sys import types import uuid from collections.abc import Iterable @@ -582,6 +583,7 @@ def ReadObject(self, request, context): content_range = None start = start + size + @retry_test(method="storage.objects.get") def BidiReadObject(self, request_iterator, context): # handle first message try: @@ -644,28 +646,15 @@ def process_read_range(range): while start < read_end: end = min(start + size, read_end) - chunk = blob.media[start:end] # Verify if there are no more bytes to read for the given ReadRange. range_end = end == read_end - res = response( - storage_pb2.BidiReadObjectResponse( - object_data_ranges=[ - storage_pb2.ObjectRangeData( - checksummed_data=storage_pb2.ChecksummedData( - content=chunk, - crc32c=crc32c.crc32c(chunk), - ), - read_range=storage_pb2.ReadRange( - read_offset=start, - read_limit=range.read_limit, - read_id=read_id, - ), - range_end=range_end, - ), - ], - ) - ) - responses.put(("respond", res)) + chunk = blob.media[start:end] + read_range = { + "read_offset": start, + "read_limit": range.read_limit, + "read_id": read_id, + } + responses.put(("respond", (chunk, range_end, read_range))) start = end def gather_requests(initial_ranges): @@ -683,17 +672,62 @@ def gather_requests(initial_ranges): ) poll_queue = True + + # Check retry test broken-stream instructions. + test_id = testbench.common.get_retry_test_id_from_context(context) + broken_stream_after_bytes = 0 + method = "storage.objects.get" + if test_id and self.db.has_instructions_retry_test( + test_id, method, transport="GRPC" + ): + next_instruction = self.db.peek_next_instruction(test_id, method) + broken_stream_after_bytes = testbench.common.get_broken_stream_after_bytes( + next_instruction + ) + + returnable = ( + broken_stream_after_bytes if broken_stream_after_bytes else sys.maxsize + ) try: gather_thread.start() while poll_queue: - action, resp = responses.get() + action, arg = responses.get() if action == "terminate": poll_queue = False elif action == "respond": - yield response(resp) + chunk, range_end, read_range = arg + count = len(chunk) + if returnable < count: + count = returnable + chunk = chunk[:count] + returnable -= count + yield response( + storage_pb2.BidiReadObjectResponse( + object_data_ranges=[ + storage_pb2.ObjectRangeData( + checksummed_data=storage_pb2.ChecksummedData( + content=chunk, + crc32c=crc32c.crc32c(chunk), + ), + read_range=read_range, + range_end=range_end, + ), + ], + ) + ) + if not returnable: + self.db.dequeue_next_instruction(test_id, method) + context.abort( + grpc.StatusCode.UNAVAILABLE, + "Injected 'broken stream' fault", + ) elif action == "abort_with_status": - context.abort_with_status(resp) + context.abort_with_status(arg) + elif action == "abort": + context.abort(*arg) + else: + raise f"Unexpected action {action}" finally: while poll_queue: action, _ = responses.get() diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index 28dcbb84..451f713f 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -23,7 +23,7 @@ import unittest.mock import crc32c -from grpc import StatusCode +from grpc import RpcError, StatusCode import gcs import testbench @@ -860,6 +860,91 @@ def test_grpc_bidiwrite_return_error_after_bytes(self): self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") self.assertEqual(blob.size, 2 * UPLOAD_QUANTUM) + def test_grpc_bidiread_retry_broken_stream(self): + # Use the XML API to inject an object with some data. + media = self._create_block(5 * 1024 * 1024) + response = self.rest_client.put( + "/bucket-name/512k.txt", + content_type="text/plain", + data=media, + ) + self.assertEqual(response.status_code, 200) + + # Setup a return-broken-stream failure for reading back the object. + response = self.rest_client.post( + "/retry_test", + data=json.dumps( + { + "instructions": {"storage.objects.get": ["return-broken-stream"]}, + "transport": "GRPC", + }, + ), + ) + self.assertEqual(response.status_code, 200) + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = RpcError() + context.invocation_metadata = unittest.mock.Mock( + return_value=(("x-retry-test-id", create_rest.get("id")),) + ) + + # Test one range in stream with limit more than 256kb. + offset_1 = 0 + limit_1 = 4 * 1024 * 1024 + read_id_1 = 1 + + r1 = storage_pb2.BidiReadObjectRequest( + read_object_spec=storage_pb2.BidiReadObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="512k.txt", + ), + read_ranges=[ + storage_pb2.ReadRange( + read_offset=offset_1, + read_limit=limit_1, + read_id=read_id_1, + ), + ], + ) + with self.assertRaises(RpcError): + response = self.grpc.BidiReadObject([r1], context) + list(response) + context.abort.assert_called_with( + StatusCode.UNAVAILABLE, "Injected 'broken stream' fault" + ) + + # Setup a return-broken-stream-after-256K failure for reading back the object. + response = self.rest_client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.get": ["return-broken-stream-after-256K"] + }, + "transport": "GRPC", + }, + ), + ) + self.assertEqual(response.status_code, 200) + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + + context = unittest.mock.Mock() + context.abort = unittest.mock.MagicMock() + context.abort.side_effect = RpcError() + context.invocation_metadata = unittest.mock.Mock( + return_value=(("x-retry-test-id", create_rest.get("id")),) + ) + with self.assertRaises(RpcError): + response = self.grpc.BidiReadObject([r1], context) + list(response) + context.abort.assert_called_with( + StatusCode.UNAVAILABLE, "Injected 'broken stream' fault" + ) + if __name__ == "__main__": unittest.main() From 39850acd851bd87dac3dbcb35a7ac3bd064ba9ba Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Fri, 4 Oct 2024 18:05:38 -0400 Subject: [PATCH 13/39] fix: Support client cancellation in BidiReadObject (#17) Client cancellation surfaces as an exception in `next(request_iterator)`. That wasn't handled before, so gather_thread simply failed and never put the `"terminate"` action on the response queue. --- testbench/grpc_server.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 9cff71d9..33959912 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -660,11 +660,14 @@ def process_read_range(range): def gather_requests(initial_ranges): nonlocal responses with futures.ThreadPoolExecutor() as readers: - for range in initial_ranges: - readers.submit(process_read_range, range) - for request in request_iterator: - for range in request.read_ranges: + try: + for range in initial_ranges: readers.submit(process_read_range, range) + for request in request_iterator: + for range in request.read_ranges: + readers.submit(process_read_range, range) + except Exception as e: + responses.put(("raise", e)) responses.put(("terminate", None)) gather_thread = Thread( @@ -724,8 +727,8 @@ def gather_requests(initial_ranges): ) elif action == "abort_with_status": context.abort_with_status(arg) - elif action == "abort": - context.abort(*arg) + elif action == "raise": + raise arg else: raise f"Unexpected action {action}" finally: From 26ef0db6b8f1400b7fca070821cb81ad12f23152 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 7 Oct 2024 10:23:38 -0400 Subject: [PATCH 14/39] feat: Handle appendable objects in BidiWriteObject (#18) Appendable objects extend BidiWriteObject calls. This is a refactor and a mostly-accurate implementation of appendable objects in the testbench. There's a key difference - this simulates true appendable using resumable uploads, which are not visible in ListObjects or similar calls in the same way that appendable objects are. That's sufficient for current testing. --- gcs/upload.py | 214 +++++++++++++++++++++++--------------- tests/test_grpc_server.py | 109 +++++++++++++++++-- tests/test_upload.py | 51 ++++++--- 3 files changed, 271 insertions(+), 103 deletions(-) diff --git a/gcs/upload.py b/gcs/upload.py index f1af0b1e..f0450fee 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -15,6 +15,7 @@ """Helper class to hold data during an upload.""" import hashlib +import itertools import json import types import uuid @@ -285,39 +286,83 @@ def init_write_object_grpc(cls, db, request_iterator, context): @classmethod def process_bidi_write_object_grpc(cls, db, request_iterator, context): """Process a BidiWriteObject streaming RPC, and yield a stream of responses.""" - upload, object_checksums, is_resumable = None, None, False + # Many tests use a list as the request_iterator + request_iterator = iter(request_iterator) + upload, object_checksums, is_resumable, is_appendable = None, None, False, False + appendable_metadata_in_first_response = False + try: + first_msg = next(request_iterator) + except StopIteration: + # At least one message is required. This function raises. + testbench.error.invalid("Missing BidiWriteObjectRequest", context) + + write_type = first_msg.WhichOneof("first_message") + if write_type == "upload_id": # resumable upload + upload = db.get_upload(first_msg.upload_id, context) + if upload.complete: + # Resuming an already finalized object will result with a response + # containing the uploaded object's metadata. + yield storage_pb2.BidiWriteObjectResponse(resource=upload.blob.metadata) + return + is_resumable = True + elif write_type == "write_object_spec": # new object + bucket = db.get_bucket( + first_msg.write_object_spec.resource.bucket, context + ).metadata + upload = cls.__init_first_write_grpc(first_msg, bucket, context) + if first_msg.write_object_spec.appendable: + is_appendable = True + appendable_metadata_in_first_response = True + db.insert_upload(upload) + elif write_type == "append_object_spec": + is_appendable = True + upload = db.get_upload( + first_msg.append_object_spec.write_handle.handle.decode("utf-8"), + context, + ) + else: + testbench.error.invalid("Upload missing a first_message field", context) + + if first_msg.HasField("object_checksums"): + object_checksums = first_msg.object_checksums + + # Treat the rest of the first message as a data request, then keep + # pulling from request_iterator + first_msg.ClearField("first_message") + first_msg.ClearField("object_checksums") + request_iterator = itertools.chain([first_msg], request_iterator) + + first_response = True + + def response(msg): + nonlocal first_response + if first_response: + first_response = False + if is_appendable and appendable_metadata_in_first_response: + # For simplicity in the testbench implementation, just use + # the database's upload_id as the appendable handle. + msg.write_handle.handle = bytes(upload.upload_id, "utf-8") + # Appendable objects also exist at creation time. That's not + # fully supported in the testbench, but we can at least + # return the object metadata. + obj_len = msg.persisted_size + msg.resource.CopyFrom(upload.metadata) + msg.resource.size = obj_len + return msg + for request in request_iterator: - first_message = request.WhichOneof("first_message") - if first_message == "upload_id": # resumable upload - upload = db.get_upload(request.upload_id, context) - if upload.complete: - # Resuming an already finalized object will result with a response - # containing the uploaded object's metadata. - yield storage_pb2.BidiWriteObjectResponse( - resource=upload.blob.metadata - ) - is_resumable = True - elif ( - first_message == "write_object_spec" - ): # one shot upload (non-resumable) - bucket = db.get_bucket( - request.write_object_spec.resource.bucket, context - ).metadata - upload = cls.__init_first_write_grpc(request, bucket, context) - elif upload is None: - return testbench.error.invalid( - "Upload missing a first_message field", context - ) + if request.HasField("first_message"): + testbench.error.invalid("Multiple first_message", context) if request.HasField("object_checksums"): # The object checksums may appear only in the first message *or* the last message, but not both - if first_message is None and request.finish_write == False: - return testbench.error.invalid( + if not request.finish_write: + testbench.error.invalid( "Object checksums can be included only in the first or last message", context, ) if object_checksums is not None: - return testbench.error.invalid( + testbench.error.invalid( "Duplicate object checksums in upload", context, ) @@ -326,75 +371,75 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): data = request.WhichOneof("data") if data == "checksummed_data": checksummed_data = request.checksummed_data - elif data is None and request.finish_write: - # Handles final message with no data to insert. - upload.complete = True - continue - else: - return testbench.error.invalid("Invalid data field in upload", context) - - content = checksummed_data.content - crc32c_hash = ( - checksummed_data.crc32c if checksummed_data.HasField("crc32c") else None - ) - if crc32c_hash is not None: - actual_crc32c = crc32c.crc32c(content) - if actual_crc32c != crc32c_hash: - return testbench.error.mismatch( - "crc32c in checksummed data", - crc32c_hash, - actual_crc32c, - context, - ) - - # Handle retry test return-X-after-YK failures if applicable. - ( - rest_code, - after_bytes, - test_id, - ) = testbench.common.get_retry_uploads_error_after_bytes( - db, request, context=context, transport="GRPC" - ) - expected_persisted_size = request.write_offset + len(content) - if rest_code: - testbench.common.handle_grpc_retry_uploads_error_after_bytes( - context, - upload, - content, - db, + content = checksummed_data.content + crc32c_hash = ( + checksummed_data.crc32c + if checksummed_data.HasField("crc32c") + else None + ) + if crc32c_hash is not None: + actual_crc32c = crc32c.crc32c(content) + if actual_crc32c != crc32c_hash: + testbench.error.mismatch( + "crc32c in checksummed data", + crc32c_hash, + actual_crc32c, + context, + ) + + # Handle retry test return-X-after-YK failures if applicable. + ( rest_code, after_bytes, - write_offset=request.write_offset, - persisted_size=len(upload.media), - expected_persisted_size=expected_persisted_size, - test_id=test_id, + test_id, + ) = testbench.common.get_retry_uploads_error_after_bytes( + db, request, context=context, transport="GRPC" ) + expected_persisted_size = request.write_offset + len(content) + if rest_code: + testbench.common.handle_grpc_retry_uploads_error_after_bytes( + context, + upload, + content, + db, + rest_code, + after_bytes, + write_offset=request.write_offset, + persisted_size=len(upload.media), + expected_persisted_size=expected_persisted_size, + test_id=test_id, + ) + + # The testbench should ignore any request bytes that have already been persisted, + # thus we validate write_offset against persisted_size. + # https://github.com/googleapis/googleapis/blob/15b48f9ed0ae8b034e753c6895eb045f436e257c/google/storage/v2/storage.proto#L320-L329 + if request.write_offset < len(upload.media): + range_start = len(upload.media) - request.write_offset + content = testbench.common.partial_media( + content, range_end=len(content), range_start=range_start + ) + # Currently, the testbench will always checkpoint and flush data for testing purposes, + # instead of the 15 seconds interval used in the GCS server. + # TODO(#592): Refactor testbench checkpointing to more closely follow GCS server behavior. + upload.media += content + elif not (data is None and request.finish_write): + # The only other allowed case is finish_write=True with no data. + testbench.error.invalid("Invalid data field in upload", context) - # The testbench should ignore any request bytes that have already been persisted, - # thus we validate write_offset against persisted_size. - # https://github.com/googleapis/googleapis/blob/15b48f9ed0ae8b034e753c6895eb045f436e257c/google/storage/v2/storage.proto#L320-L329 - if request.write_offset < len(upload.media): - range_start = len(upload.media) - request.write_offset - content = testbench.common.partial_media( - content, range_end=len(content), range_start=range_start - ) - # Currently, the testbench will always checkpoint and flush data for testing purposes, - # instead of the 15 seconds interval used in the GCS server. - # TODO(#592): Refactor testbench checkpointing to more closely follow GCS server behavior. - upload.media += content if request.finish_write: upload.complete = True + break elif request.state_lookup: # For uploads not yet completed, yield response with persisted_size. # For uploads that are complete, finalize the upload outside the request loop by # storing full object checksums, creating new object, and yielding response with # object metadata. - yield storage_pb2.BidiWriteObjectResponse( - persisted_size=len(upload.media) + yield response( + storage_pb2.BidiWriteObjectResponse( + persisted_size=len(upload.media) + ) ) - if upload is None: - return testbench.error.invalid("Missing BidiWriteObjectRequest", context) if object_checksums is None: upload.metadata.metadata["x_emulator_no_crc32c"] = "true" upload.metadata.metadata["x_emulator_no_md5"] = "true" @@ -432,10 +477,9 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): context=context, preconditions=upload.preconditions, ) - yield storage_pb2.BidiWriteObjectResponse(resource=blob.metadata) - else: - if not is_resumable: - return testbench.error.missing("finish_write in request", context) + yield response(storage_pb2.BidiWriteObjectResponse(resource=blob.metadata)) + elif not is_resumable and not is_appendable: + testbench.error.missing("finish_write in request", context) def resumable_status_rest(self, override_308=False): response = flask.make_response() diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 31268106..0565f83d 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2120,6 +2120,10 @@ def test_echo_metadata(self): server.stop(grace=0) def test_bidi_write_object(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + QUANTUM = 256 * 1024 media = TestGrpc._create_block(2 * QUANTUM + QUANTUM / 2).encode("utf-8") @@ -2162,7 +2166,7 @@ def test_bidi_write_object(self): ), finish_write=True, ) - streamer = self.grpc.BidiWriteObject([r1, r2, r3], context=self.mock_context()) + streamer = self.grpc.BidiWriteObject([r1, r2, r3], context=context) responses = list(streamer) # We expect a total of 3 responses with state_lookup set to True. self.assertEqual(len(responses), 3) @@ -2174,6 +2178,10 @@ def test_bidi_write_object(self): self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") def test_bidi_write_object_resumable(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + start = self.grpc.StartResumableWrite( storage_pb2.StartResumableWriteRequest( write_object_spec=storage_pb2.WriteObjectSpec( @@ -2182,7 +2190,7 @@ def test_bidi_write_object_resumable(self): ) ) ), - context=unittest.mock.MagicMock(), + context=context, ) self.assertIsNotNone(start.upload_id) @@ -2202,7 +2210,6 @@ def test_bidi_write_object_resumable(self): offset = QUANTUM content = media[QUANTUM : 2 * QUANTUM] r2 = storage_pb2.BidiWriteObjectRequest( - upload_id=start.upload_id, write_offset=offset, checksummed_data=storage_pb2.ChecksummedData( content=content, crc32c=crc32c.crc32c(content) @@ -2211,7 +2218,7 @@ def test_bidi_write_object_resumable(self): state_lookup=True, finish_write=False, ) - streamer = self.grpc.BidiWriteObject([r1, r2], "fake-context") + streamer = self.grpc.BidiWriteObject([r1, r2], context=context) responses = list(streamer) # We only expect 1 response with r2 state_lookup set to True. self.assertEqual(len(responses), 1) @@ -2220,7 +2227,7 @@ def test_bidi_write_object_resumable(self): status = self.grpc.QueryWriteStatus( storage_pb2.QueryWriteStatusRequest(upload_id=start.upload_id), - "fake-context", + context=context, ) self.assertEqual(status.persisted_size, 2 * QUANTUM) @@ -2234,13 +2241,103 @@ def test_bidi_write_object_resumable(self): ), finish_write=True, ) - streamer = self.grpc.BidiWriteObject([r3], "fake-context") + streamer = self.grpc.BidiWriteObject([r3], context=context) responses = list(streamer) self.assertEqual(len(responses), 1) blob = responses[0].resource self.assertEqual(blob.name, "object-name") self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + def test_bidi_write_object_appendable(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + + QUANTUM = 256 * 1024 + media = TestGrpc._create_block(2 * QUANTUM + QUANTUM / 2).encode("utf-8") + offset = 0 + content = media[0:QUANTUM] + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/bucket-name" + ), + appendable=True, + ), + write_offset=offset, + checksummed_data=storage_pb2.ChecksummedData( + content=content, crc32c=crc32c.crc32c(content) + ), + flush=True, + ) + offset += QUANTUM + content = media[offset : offset + QUANTUM] + r2 = storage_pb2.BidiWriteObjectRequest( + write_offset=offset, + checksummed_data=storage_pb2.ChecksummedData( + content=content, crc32c=crc32c.crc32c(content) + ), + flush=True, + state_lookup=True, + ) + streamer = self.grpc.BidiWriteObject([r1, r2], context=context) + responses = list(streamer) + # We only expect 1 response with r2 state_lookup set to True. + self.assertEqual(len(responses), 1) + self.assertIsNotNone(responses[0]) + # For appendable objects, we expect the object metadata in the first + # response rather than the persisted_size. + self.assertEqual(responses[0].resource.size, 2 * QUANTUM) + self.assertEqual(responses[0].resource.bucket, "projects/_/buckets/bucket-name") + self.assertEqual(responses[0].resource.name, "object-name") + + bucket = responses[0].resource.bucket + name = responses[0].resource.name + generation = responses[0].resource.generation + write_handle = responses[0].write_handle + + offset += QUANTUM + content = media[offset : offset + 1] + r3 = storage_pb2.BidiWriteObjectRequest( + append_object_spec=storage_pb2.AppendObjectSpec( + bucket=bucket, + object=name, + generation=generation, + write_handle=write_handle, + ), + write_offset=offset, + checksummed_data=storage_pb2.ChecksummedData( + content=content, crc32c=crc32c.crc32c(content) + ), + flush=True, + state_lookup=True, + ) + offset += 1 + content = media[offset:] + r4 = storage_pb2.BidiWriteObjectRequest( + write_offset=offset, + checksummed_data=storage_pb2.ChecksummedData( + content=content, crc32c=crc32c.crc32c(content) + ), + finish_write=True, + ) + streamer = self.grpc.BidiWriteObject([r3, r4], context=context) + responses = list(streamer) + self.assertEqual(len(responses), 2) + self.assertEqual(responses[0].persisted_size, 2 * QUANTUM + 1) + blob = responses[1].resource + self.assertEqual(responses[1].resource.size, 2 * QUANTUM + QUANTUM / 2) + self.assertEqual(blob.name, "object-name") + self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + + def test_bidi_write_object_no_requests(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiWriteObject([], context=context) + responses = list(streamer) + def test_bidi_read_object(self): # Create object in database to read. media = TestGrpc._create_block(5 * 1024 * 1024).encode("utf-8") diff --git a/tests/test_upload.py b/tests/test_upload.py index 429d62ea..b3c326c7 100644 --- a/tests/test_upload.py +++ b/tests/test_upload.py @@ -17,6 +17,7 @@ """Tests for the Object class (see gcs/object.py).""" import base64 +import copy import hashlib import json import unittest @@ -749,6 +750,7 @@ def test_process_bidi_write_grpc_resumable(self): ), finish_write=True, ) + r2 = copy.deepcopy(r1) db = unittest.mock.Mock() db.get_bucket = unittest.mock.MagicMock(return_value=bucket) db.get_upload = unittest.mock.MagicMock(return_value=upload) @@ -763,7 +765,7 @@ def test_process_bidi_write_grpc_resumable(self): # Test resuming an already finalized object will result with # a response containing the finalized object's metadata. context = self.mock_context() - streamer = gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context) + streamer = gcs.upload.Upload.process_bidi_write_object_grpc(db, [r2], context) responses = list(streamer) blob = responses[0].resource self.assertEqual(blob.name, "object") @@ -779,8 +781,11 @@ def test_process_bidi_write_grpc_missing_first_message(self): finish_write=True, ) db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) @@ -798,8 +803,11 @@ def test_process_bidi_write_grpc_missing_finish_write(self): finish_write=False, ) db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) @@ -834,10 +842,15 @@ def test_process_bidi_write_grpc_missing_checksum_at_invalid_place(self): finish_write=True, ) db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list( - gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1, r2, r3], context) - ) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list( + gcs.upload.Upload.process_bidi_write_object_grpc( + db, [r1, r2, r3], context + ) + ) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) @@ -875,10 +888,15 @@ def test_process_bidi_write_grpc_checksum_duplicated(self): finish_write=True, ) db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list( - gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1, r2, r3], context) - ) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list( + gcs.upload.Upload.process_bidi_write_object_grpc( + db, [r1, r2, r3], context + ) + ) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) @@ -899,8 +917,11 @@ def test_process_bidi_write_grpc_invalid_checksum(self): finish_write=True, ) db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) context.abort.assert_called_once_with( grpc.StatusCode.FAILED_PRECONDITION, unittest.mock.ANY ) @@ -976,8 +997,11 @@ def test_process_bidi_write_grpc_checksums(self): def test_process_bidi_write_grpc_empty(self): db = unittest.mock.Mock() + # The code depends on `context.abort()` raising an exception. context = self.mock_context() - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [], context)) + context.abort.side_effect = grpc.RpcError() + with self.assertRaises(grpc.RpcError): + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [], context)) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) @@ -1042,11 +1066,14 @@ def test_process_bidi_write_grpc_message_invalid_data(self): write_offset=0, finish_write=False, ) + # The code depends on `context.abort()` raising an exception. context = self.mock_context() + context.abort.side_effect = grpc.RpcError() db = unittest.mock.Mock() db.get_bucket = unittest.mock.MagicMock(return_value=bucket) db.get_upload = unittest.mock.MagicMock(return_value=upload) - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) + with self.assertRaises(grpc.RpcError): + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) context.abort.assert_called_once_with( grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) From c91004d8721bc5baf155a99cab058507cea9893d Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 7 Oct 2024 12:56:32 -0400 Subject: [PATCH 15/39] fix: Correct BidiReadObject early termination. (#19) When a stream ends with early termination, but we still return some bytes, the response should be consistent with the actual bytes returned. Specifically, we adjust the read_limit to match the actual range returned, and adjust the range_end bool to indicate that we know there is more data to request. --- testbench/grpc_server.py | 10 ++++++---- tests/test_testbench_retry.py | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 33959912..a0f24fc1 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -701,9 +701,11 @@ def gather_requests(initial_ranges): elif action == "respond": chunk, range_end, read_range = arg count = len(chunk) - if returnable < count: - count = returnable - chunk = chunk[:count] + excess = count - returnable + if excess > 0: + chunk = chunk[:returnable] + range_end = False + read_range["read_limit"] -= excess returnable -= count yield response( storage_pb2.BidiReadObjectResponse( @@ -719,7 +721,7 @@ def gather_requests(initial_ranges): ], ) ) - if not returnable: + if returnable <= 0: self.db.dequeue_next_instruction(test_id, method) context.abort( grpc.StatusCode.UNAVAILABLE, diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index 451f713f..f0a23de6 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -893,7 +893,7 @@ def test_grpc_bidiread_retry_broken_stream(self): # Test one range in stream with limit more than 256kb. offset_1 = 0 - limit_1 = 4 * 1024 * 1024 + limit_1 = 1 * 1024 * 1024 read_id_1 = 1 r1 = storage_pb2.BidiReadObjectRequest( @@ -938,12 +938,26 @@ def test_grpc_bidiread_retry_broken_stream(self): context.invocation_metadata = unittest.mock.Mock( return_value=(("x-retry-test-id", create_rest.get("id")),) ) + responses = [] with self.assertRaises(RpcError): response = self.grpc.BidiReadObject([r1], context) - list(response) + # Gather all the responses that arrive before the context abort + for r in response: + responses.append(r) context.abort.assert_called_with( StatusCode.UNAVAILABLE, "Injected 'broken stream' fault" ) + # Verify the early break occurred after exactly 256K + self.assertEqual(len(responses), 1) + self.assertEqual(len(responses[0].object_data_ranges), 1) + odr = responses[0].object_data_ranges[0] + EXPECTED_LEN = 256 * 1024 + self.assertEqual(len(odr.checksummed_data.content), EXPECTED_LEN) + self.assertEqual(odr.read_range.read_id, read_id_1) + self.assertEqual(odr.read_range.read_offset, offset_1) + self.assertEqual(odr.read_range.read_limit, offset_1 + EXPECTED_LEN) + # Because we requested 1 MiB, but only got back 256KiB + self.assertFalse(odr.range_end) if __name__ == "__main__": From 81e9e43fad513608b085c8dc999641a3bc910c8c Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 16 Oct 2024 23:14:34 -0400 Subject: [PATCH 16/39] fix: Don't raise a bare string (#21) This was a bug - I should have raised a RuntimeError. It doesn't come up because it's meant to be an impossible codepath, but it's nicer to raise a real error in that case. --- testbench/grpc_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index a0f24fc1..6c86bd6d 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -732,7 +732,7 @@ def gather_requests(initial_ranges): elif action == "raise": raise arg else: - raise f"Unexpected action {action}" + raise RuntimeError(f"Unexpected action {action}") finally: while poll_queue: action, _ = responses.get() From 57aec0caafc4c92edad62cfa867718a267bfb68c Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 16 Oct 2024 23:58:05 -0400 Subject: [PATCH 17/39] fix: Allow BidiWriteObjectRequest with no data. (#22) BidiWriteObjectRequest is allowed to contain no checksummed_data. --- gcs/upload.py | 3 +-- tests/test_upload.py | 33 --------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/gcs/upload.py b/gcs/upload.py index f0450fee..cdb5516a 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -422,8 +422,7 @@ def response(msg): # instead of the 15 seconds interval used in the GCS server. # TODO(#592): Refactor testbench checkpointing to more closely follow GCS server behavior. upload.media += content - elif not (data is None and request.finish_write): - # The only other allowed case is finish_write=True with no data. + elif data is not None: testbench.error.invalid("Invalid data field in upload", context) if request.finish_write: diff --git a/tests/test_upload.py b/tests/test_upload.py index b3c326c7..a6f8a900 100644 --- a/tests/test_upload.py +++ b/tests/test_upload.py @@ -1046,39 +1046,6 @@ def test_process_bidi_write_grpc_final_message_empty_data(self): self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") self.assertTrue(upload.complete) - def test_process_bidi_write_grpc_message_invalid_data(self): - request = testbench.common.FakeRequest( - args={}, data=json.dumps({"name": "bucket-name"}) - ) - bucket, _ = gcs.bucket.Bucket.init(request, None) - request = storage_pb2.StartResumableWriteRequest( - write_object_spec=storage_pb2.WriteObjectSpec( - resource={"name": "object", "bucket": "projects/_/buckets/bucket-name"} - ) - ) - context = self.mock_context() - upload = gcs.upload.Upload.init_resumable_grpc( - request, bucket.metadata, context - ) - - r1 = storage_pb2.BidiWriteObjectRequest( - upload_id=upload.upload_id, - write_offset=0, - finish_write=False, - ) - # The code depends on `context.abort()` raising an exception. - context = self.mock_context() - context.abort.side_effect = grpc.RpcError() - db = unittest.mock.Mock() - db.get_bucket = unittest.mock.MagicMock(return_value=bucket) - db.get_upload = unittest.mock.MagicMock(return_value=upload) - with self.assertRaises(grpc.RpcError): - list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - self.assertFalse(upload.complete) - if __name__ == "__main__": unittest.main() From 86db6be456de03dbb55cf04d49febbf4939d454f Mon Sep 17 00:00:00 2001 From: cojenco Date: Tue, 22 Oct 2024 11:06:55 -0700 Subject: [PATCH 18/39] build: update cloudbuild for private images (#23) --- cloudbuild.yaml => cloudbuild_prelaunch.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) rename cloudbuild.yaml => cloudbuild_prelaunch.yaml (58%) diff --git a/cloudbuild.yaml b/cloudbuild_prelaunch.yaml similarity index 58% rename from cloudbuild.yaml rename to cloudbuild_prelaunch.yaml index 0e9bf62f..21eb939f 100644 --- a/cloudbuild.yaml +++ b/cloudbuild_prelaunch.yaml @@ -1,4 +1,4 @@ -# Copyright 2021 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,17 +15,20 @@ timeout: 7200s # 2 hours steps: - name: gcr.io/cloud-builders/docker - args: ["build", "-t", "gcr.io/cloud-devrel-public-resources/storage-testbench:$TAG_NAME", "."] + args: ["build", "-t", "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA", "."] dir: . - id: storage-testbench-build + id: storage-testbench-prelaunch-build - name: gcr.io/cloud-builders/docker args: [ "tag", - "gcr.io/cloud-devrel-public-resources/storage-testbench:$TAG_NAME", - "gcr.io/cloud-devrel-public-resources/storage-testbench:latest", + "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA", + "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest", ] images: - - gcr.io/cloud-devrel-public-resources/storage-testbench:$TAG_NAME - - gcr.io/cloud-devrel-public-resources/storage-testbench:latest + - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA + - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest + +options: + logging: CLOUD_LOGGING_ONLY \ No newline at end of file From 298b19bbcc670ed17e179da5f2fb02c1785b932f Mon Sep 17 00:00:00 2001 From: cojenco Date: Thu, 24 Oct 2024 15:41:15 -0700 Subject: [PATCH 19/39] chore: merge from public circa 2024-10-24 (#25) * chore: merge from public circa 2024-10-24 * chore: remove Notification, HMAC, SA grpc support (#693) * chore: remove Notification, HMAC, SA grpc support * fix lint * feat: add write stall support (#684) * add code for write stall * fix test * remove unnecessary files * remove unnecessary files * write test * undo test changes to remove unnecessary changes * Update test_testbench_retry.py * add test * remove .idea files * write stall changes * remove .idea file * Update test_testbench_retry.py * test * stall once for identiacal req * add comment * remove .idea file * fix unit test * fix unit test * test changes * test changes * review comments * remove .idea files * lint fixes * lint fixes * lint fixes * lint fixes * lint fixes * code patch fix * support full uploads * remove unnecessary things * remove unnecessary things * remove unnecessary things * adding comment * lint fix * lint fix * stall should not happen if uploaded less amount of data then stall size * stall should not happen if uploaded less amount of data then stall size * remove last two commit changes * remove env files * lint fix * lint fix * review comment and adding scenario where upload size is less then stall byte size in single shot * lint fix * lint fix * chore: remove Notification, HMAC, SA grpc support (#693) --------- Co-authored-by: Mend Renovate Co-authored-by: Tulsi Shah <46474643+Tulsishah@users.noreply.github.com> --- README.md | 4 +- setup.py | 2 +- testbench/common.py | 58 ++++- testbench/database.py | 6 + testbench/grpc_server.py | 183 ------------- testbench/rest_server.py | 30 +++ tests/test_grpc_server.py | 466 ---------------------------------- tests/test_testbench_retry.py | 225 ++++++++++++++++ 8 files changed, 315 insertions(+), 659 deletions(-) diff --git a/README.md b/README.md index a6c7b757..c648aa7f 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 | return-broken-stream | [HTTP] Testbench will fail after a few downloaded bytes
[GRPC] Testbench will fail with `UNAVAILABLE` after a few downloaded bytes | return-broken-stream-after-YK | [HTTP] Testbench will fail after YKiB of downloaded data
[GRPC] Testbench will fail with `UNAVAILABLE` after YKiB of downloaded data | return-reset-connection | [HTTP] Testbench will fail with a reset connection
[GRPC] Testbench will fail the RPC with `UNAVAILABLE` -| stall-for-Ts-after-YK | [HTTP] Testbench will stall for T second after reading YKiB of downloaded data, e.g. stall-for-10s-after-12K stalls after reading 12KiB of data
[GRPC] Not supported +| stall-for-Ts-after-YK | [HTTP] Testbench will stall for T second after reading YKiB of downloaded/uploaded data, e.g. stall-for-10s-after-12K stalls after reading/writing 12KiB of data
[GRPC] Not supported ## Releasing the testbench @@ -258,4 +258,4 @@ Steps: 1. Title "v0.x.x" 1. Click Generate release notes 1. Make sure "Set as the latest release" is checked -1. Click "Publish Release" to release +1. Click "Publish Release" to release \ No newline at end of file diff --git a/setup.py b/setup.py index 4099cba0..e7b7e2fa 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ ], python_requires=">=3.8", install_requires=[ - "grpcio==1.66.1", + "grpcio==1.67.0", "grpcio-status==1.66.1", "grpcio-tools==1.66.1", "googleapis-common-protos==1.65.0", diff --git a/testbench/common.py b/testbench/common.py index 678a5d82..5f7399ca 100644 --- a/testbench/common.py +++ b/testbench/common.py @@ -844,11 +844,17 @@ def handle_retry_test_instruction(database, request, socket_closer, method): broken_stream_after_bytes = ( testbench.common.retry_return_broken_stream_after_bytes.match(next_instruction) ) + if broken_stream_after_bytes and method == "storage.objects.get": + items = list(broken_stream_after_bytes.groups()) + after_bytes = int(items[0]) * 1024 + return __get_streamer_response_fn( + database, method, socket_closer, test_id, limit=after_bytes + ) retry_stall_after_bytes_matches = testbench.common.retry_stall_after_bytes.match( next_instruction ) - if retry_stall_after_bytes_matches: + if retry_stall_after_bytes_matches and method != "storage.objects.insert": items = list(retry_stall_after_bytes_matches.groups()) stall_time = int(items[0]) after_bytes = int(items[1]) * 1024 @@ -856,12 +862,6 @@ def handle_retry_test_instruction(database, request, socket_closer, method): database, method, test_id, limit=after_bytes, stall_time_sec=stall_time ) - if broken_stream_after_bytes and method == "storage.objects.get": - items = list(broken_stream_after_bytes.groups()) - after_bytes = int(items[0]) * 1024 - return __get_streamer_response_fn( - database, method, socket_closer, test_id, limit=after_bytes - ) retry_return_short_response = testbench.common.retry_return_short_response.match( next_instruction ) @@ -895,6 +895,30 @@ def wrapper(*args, **kwargs): return retry_test +def get_stall_uploads_after_bytes(database, request, context=None, transport="HTTP"): + """Retrieve stall time and #bytes corresponding to uploads from retry test instructions.""" + method = "storage.objects.insert" + test_id = request.headers.get("x-retry-test-id", None) + if not test_id: + return 0, 0, "" + next_instruction = None + if database.has_instructions_retry_test(test_id, method, transport=transport): + next_instruction = database.peek_next_instruction(test_id, method) + if not next_instruction: + return 0, 0, "" + + stall_after_byte_matches = testbench.common.retry_stall_after_bytes.match( + next_instruction + ) + if stall_after_byte_matches: + items = list(stall_after_byte_matches.groups()) + stall_time = int(items[0]) + after_bytes = int(items[1]) * 1024 + return stall_time, after_bytes, test_id + + return 0, 0, "" + + def get_retry_uploads_error_after_bytes( database, request, context=None, transport="HTTP" ): @@ -919,9 +943,29 @@ def get_retry_uploads_error_after_bytes( error_code = int(items[0]) after_bytes = int(items[1]) * 1024 return error_code, after_bytes, test_id + return 0, 0, "" +def handle_stall_uploads_after_bytes( + upload, + data, + database, + stall_time, + after_bytes, + test_id=0, +): + """ + Handle stall-after-bytes instructions for resumable uploads. + Stall happens after given value of bytes. + e.g. We are uploading 120K of data then, stall-2s-after-100K will stall the request. + """ + if len(upload.media) <= after_bytes and len(upload.media) + len(data) > after_bytes: + if test_id: + database.dequeue_next_instruction(test_id, "storage.objects.insert") + time.sleep(stall_time) + + def handle_retry_uploads_error_after_bytes( upload, data, diff --git a/testbench/database.py b/testbench/database.py index 30cd0284..65412f11 100644 --- a/testbench/database.py +++ b/testbench/database.py @@ -606,6 +606,11 @@ def __validate_grpc_method_implemented_retry(self, method): "storage.default_object_acl.insert", "storage.default_object_acl.patch", "storage.default_object_acl.update", + "storage.hmacKey.create", + "storage.hmacKey.delete", + "storage.hmacKey.get", + "storage.hmacKey.list", + "storage.hmacKey.update", "storage.object_acl.get", "storage.object_acl.list", "storage.object_acl.delete", @@ -616,6 +621,7 @@ def __validate_grpc_method_implemented_retry(self, method): "storage.notifications.get", "storage.notifications.insert", "storage.notifications.list", + "storage.serviceaccount.get", } if method in not_supported_grpc_w_retry: testbench.error.unimplemented( diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index fa15a0b1..4cca0343 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -358,72 +358,6 @@ def UpdateBucket(self, request, context): bucket.metadata.update_time.FromDatetime(now) return bucket.metadata - def _notification_from_rest(self, rest, bucket_name): - # We need to make a copy before changing any values - rest = rest.copy() - rest.pop("kind") - rest["name"] = bucket_name + "/notificationConfigs/" + rest.pop("id") - rest["topic"] = "//pubsub.googleapis.com/" + rest["topic"] - return json_format.ParseDict(rest, storage_pb2.NotificationConfig()) - - def _decompose_notification_name(self, notification_name, context): - loc = notification_name.find("/notificationConfigs/") - if loc == -1: - testbench.error.invalid( - "GetNotificationConfig() malformed notification name [%s]" - % notification_name, - context, - ) - return (None, None) - bucket_name = notification_name[:loc] - notification_id = notification_name[loc + len("/notificationConfigs/") :] - return (bucket_name, notification_id) - - def DeleteNotificationConfig(self, request, context): - bucket_name, notification_id = self._decompose_notification_name( - request.name, context - ) - if bucket_name is None: - return None - bucket = self.db.get_bucket(bucket_name, context) - bucket.delete_notification(notification_id, context) - return empty_pb2.Empty() - - def GetNotificationConfig(self, request, context): - bucket_name, notification_id = self._decompose_notification_name( - request.name, context - ) - if bucket_name is None: - return None - bucket = self.db.get_bucket(bucket_name, context) - rest = bucket.get_notification(notification_id, context) - return self._notification_from_rest(rest, bucket_name) - - def CreateNotificationConfig(self, request, context): - pattern = "^//pubsub.googleapis.com/projects/[^/]+/topics/[^/]+$" - if re.match(pattern, request.notification_config.topic) is None: - return testbench.error.invalid( - "topic names must be in" - + " //pubsub.googleapis.com/projects/{project-identifier}/topics/{my-topic}" - + " format, got=%s" % request.notification_config.topic, - context, - ) - bucket = self.db.get_bucket(request.parent, context) - notification = json_format.MessageToDict(request.notification_config) - # Convert topic names to REST format - notification["topic"] = notification["topic"][len("//pubsub.googleapis.com/") :] - rest = bucket.insert_notification(json.dumps(notification), context) - return self._notification_from_rest(rest, request.parent) - - def ListNotificationConfigs(self, request, context): - bucket = self.db.get_bucket(request.parent, context) - items = bucket.list_notifications(context).get("items", []) - return storage_pb2.ListNotificationConfigsResponse( - notification_configs=[ - self._notification_from_rest(r, request.parent) for r in items - ] - ) - @retry_test(method="storage.objects.compose") def ComposeObject(self, request, context): if len(request.source_objects) == 0: @@ -1003,123 +937,6 @@ def QueryWriteStatus(self, request, context): return storage_pb2.QueryWriteStatusResponse(resource=upload.blob.metadata) return storage_pb2.QueryWriteStatusResponse(persisted_size=len(upload.media)) - @retry_test("storage.serviceaccount.get") - def GetServiceAccount(self, request, context): - if not request.project.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % request.project, - context, - ) - project_id = request.project[len("projects/") :] - project = self.db.get_project(project_id) - return storage_pb2.ServiceAccount(email_address=project.service_account_email()) - - def _hmac_key_metadata_from_rest(self, rest): - rest = rest.copy() - rest.pop("kind", None) - rest["project"] = "projects/" + rest.pop("projectId") - rest["create_time"] = rest.pop("timeCreated") - rest["update_time"] = rest.pop("updated") - return json_format.ParseDict(rest, storage_pb2.HmacKeyMetadata()) - - @retry_test(method="storage.hmacKey.create") - def CreateHmacKey(self, request, context): - if not request.project.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % request.project, - context, - ) - if request.service_account_email == "": - return testbench.error.invalid( - "service account email must be non-empty", context - ) - project_id = request.project[len("projects/") :] - project = self.db.get_project(project_id) - rest = project.insert_hmac_key(request.service_account_email) - return storage_pb2.CreateHmacKeyResponse( - secret_key_bytes=base64.b64decode(rest.get("secret").encode("utf-8")), - metadata=self._hmac_key_metadata_from_rest(rest.get("metadata")), - ) - - @retry_test(method="storage.hmacKey.delete") - def DeleteHmacKey(self, request, context): - if not request.project.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % request.project, - context, - ) - project_id = request.project[len("projects/") :] - project = self.db.get_project(project_id) - project.delete_hmac_key(request.access_id, context) - return empty_pb2.Empty() - - @retry_test("storage.hmacKey.get") - def GetHmacKey(self, request, context): - if not request.project.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % request.project, - context, - ) - project_id = request.project[len("projects/") :] - project = self.db.get_project(project_id) - rest = project.get_hmac_key(request.access_id, context) - return self._hmac_key_metadata_from_rest(rest) - - @retry_test("storage.hmacKey.list") - def ListHmacKeys(self, request, context): - if not request.project.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % request.project, - context, - ) - project_id = request.project[len("projects/") :] - project = self.db.get_project(project_id) - - items = [] - sa_email = request.service_account_email - if len(sa_email) != 0: - service_account = project.service_account(sa_email) - if service_account: - items = service_account.key_items() - else: - for sa in project.service_accounts.values(): - items.extend(sa.key_items()) - - state_filter = lambda x: x.get("state") != "DELETED" - if request.show_deleted_keys: - state_filter = lambda x: True - - return storage_pb2.ListHmacKeysResponse( - hmac_keys=[ - self._hmac_key_metadata_from_rest(i) for i in items if state_filter(i) - ] - ) - - @retry_test(method="storage.hmacKey.update") - def UpdateHmacKey(self, request, context): - if request.update_mask.paths == []: - return testbench.error.invalid( - "UpdateHmacKey() with an empty update mask", context - ) - if request.update_mask.paths != ["state"]: - return testbench.error.invalid( - "UpdateHmacKey() only the `state` field can be modified [%s]" - % ",".join(request.update_mask.paths), - context, - ) - project_id = request.hmac_key.project - if not project_id.startswith("projects/"): - return testbench.error.invalid( - "project name must start with projects/, got=%s" % project_id, context - ) - project_id = project_id[len("projects/") :] - project = self.db.get_project(project_id) - payload = {"state": request.hmac_key.state} - if request.hmac_key.etag != "": - payload["etag"] = request.hmac_key.etag - rest = project.update_hmac_key(request.hmac_key.access_id, payload, context) - return self._hmac_key_metadata_from_rest(rest) - def run(port, database, echo_metadata=False): server = grpc.server(futures.ThreadPoolExecutor(max_workers=1)) diff --git a/testbench/rest_server.py b/testbench/rest_server.py index 96308406..72a0ae88 100644 --- a/testbench/rest_server.py +++ b/testbench/rest_server.py @@ -16,6 +16,7 @@ import datetime import json import logging +import time import flask from google.protobuf import json_format @@ -978,6 +979,18 @@ def object_insert(bucket_name): blob, projection = gcs_type.object.Object.init_media(flask.request, bucket) elif upload_type == "multipart": blob, projection = gcs_type.object.Object.init_multipart(flask.request, bucket) + # Handle stall for full uploads. + testbench.common.extract_instruction(request, context=None) + ( + stall_time, + after_bytes, + test_id, + ) = testbench.common.get_stall_uploads_after_bytes(db, request) + if stall_time and len(blob.media) >= after_bytes: + if test_id: + db.dequeue_next_instruction(test_id, "storage.objects.insert") + time.sleep(stall_time) + db.insert_object( bucket_name, blob, @@ -1104,6 +1117,23 @@ def resumable_upload_chunk(bucket_name): chunk_last_byte, test_id, ) + + testbench.common.extract_instruction(request, context=None) + ( + stall_time, + after_bytes, + test_id, + ) = testbench.common.get_stall_uploads_after_bytes(db, request) + + if stall_time: + testbench.common.handle_stall_uploads_after_bytes( + upload, + data, + db, + stall_time, + after_bytes, + test_id, + ) # The testbench should ignore any request bytes that have already been persisted, # to be aligned with GCS behavior (https://cloud.google.com/storage/docs/resumable-uploads#resent-data). # Thus we validate chunk_first_byte against last_byte_persisted. diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index a73f35d7..303b2a99 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -641,180 +641,6 @@ def test_update_bucket_soft_delete(self): grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) - def test_delete_notification(self): - context = unittest.mock.Mock() - create = self.grpc.CreateNotificationConfig( - storage_pb2.CreateNotificationConfigRequest( - parent="projects/_/buckets/bucket-name", - notification_config=storage_pb2.NotificationConfig( - topic="//pubsub.googleapis.com/projects/test-project-id/topics/test-topic", - custom_attributes={"key": "value"}, - payload_format="JSON_API_V1", - ), - ), - context, - ) - self.assertTrue( - create.name.startswith( - "projects/_/buckets/bucket-name/notificationConfigs/" - ), - msg=create, - ) - - context = unittest.mock.Mock() - _ = self.grpc.DeleteNotificationConfig( - storage_pb2.GetNotificationConfigRequest(name=create.name), context - ) - context.abort.assert_not_called() - - # The code depends on `context.abort()` raising an exception. - context = unittest.mock.Mock() - context.abort = unittest.mock.MagicMock() - context.abort.side_effect = grpc.RpcError() - with self.assertRaises(grpc.RpcError): - _ = self.grpc.GetNotificationConfig( - storage_pb2.GetNotificationConfigRequest(name=create.name), context - ) - context.abort.assert_called_once_with( - grpc.StatusCode.NOT_FOUND, unittest.mock.ANY - ) - - def test_delete_notification_malformed(self): - context = unittest.mock.Mock() - _ = self.grpc.DeleteNotificationConfig( - storage_pb2.GetNotificationConfigRequest(name=""), context - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_get_notification(self): - context = unittest.mock.Mock() - topic_name = ( - "//pubsub.googleapis.com/projects/test-project-id/topics/test-topic" - ) - response = self.grpc.CreateNotificationConfig( - storage_pb2.CreateNotificationConfigRequest( - parent="projects/_/buckets/bucket-name", - notification_config=storage_pb2.NotificationConfig( - topic=topic_name, - custom_attributes={"key": "value"}, - payload_format="JSON_API_V1", - ), - ), - context, - ) - self.assertTrue( - response.name.startswith( - "projects/_/buckets/bucket-name/notificationConfigs/" - ), - msg=response, - ) - - context = unittest.mock.Mock() - get = self.grpc.GetNotificationConfig( - storage_pb2.GetNotificationConfigRequest(name=response.name), context - ) - self.assertEqual(get, response) - self.assertEqual(get.topic, topic_name) - - def test_get_notification_malformed(self): - context = unittest.mock.Mock() - _ = self.grpc.GetNotificationConfig( - storage_pb2.GetNotificationConfigRequest( - name="projects/_/buckets/bucket-name/" - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_create_notification(self): - topic_name = ( - "//pubsub.googleapis.com/projects/test-project-id/topics/test-topic" - ) - context = unittest.mock.Mock() - response = self.grpc.CreateNotificationConfig( - storage_pb2.CreateNotificationConfigRequest( - parent="projects/_/buckets/bucket-name", - notification_config=storage_pb2.NotificationConfig( - topic=topic_name, - custom_attributes={"key": "value"}, - payload_format="JSON_API_V1", - ), - ), - context, - ) - self.assertTrue( - response.name.startswith( - "projects/_/buckets/bucket-name/notificationConfigs/" - ), - msg=response, - ) - self.assertEqual(response.topic, topic_name) - - # Invalid topic names return an error - invalid_topic_names = [ - "", - "//pubsub.googleapis.com", - "//pubsub.googleapis.com/", - "//pubsub.googleapis.com/projects", - "//pubsub.googleapis.com/projects/", - "//pubsub.googleapis.com/projects/test-project-id", - "//pubsub.googleapis.com/projects/test-project-id/", - "//pubsub.googleapis.com/projects/test-project-id/topics", - "//pubsub.googleapis.com/projects/test-project-id/topics/", - ] - for topic in invalid_topic_names: - context = unittest.mock.Mock() - context.abort = unittest.mock.MagicMock() - context.abort.side_effect = grpc.RpcError() - with self.assertRaises(grpc.RpcError): - _ = self.grpc.CreateNotificationConfig( - storage_pb2.CreateNotificationConfigRequest( - parent="projects/_/buckets/bucket-name", - notification_config=storage_pb2.NotificationConfig( - topic=topic, payload_format="JSON_API_V1" - ), - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_list_notifications(self): - expected = set() - topics = [ - "//pubsub.googleapis.com/projects/test-project-id/topics/test-topic-1", - "//pubsub.googleapis.com/projects/test-project-id/topics/test-topic-2", - ] - for topic in topics: - context = unittest.mock.Mock() - response = self.grpc.CreateNotificationConfig( - storage_pb2.CreateNotificationConfigRequest( - parent="projects/_/buckets/bucket-name", - notification_config=storage_pb2.NotificationConfig( - topic=topic, - custom_attributes={"key": "value"}, - payload_format="JSON_API_V1", - ), - ), - context, - ) - expected.add(response.name) - - context = unittest.mock.Mock() - response = self.grpc.ListNotificationConfigs( - storage_pb2.ListNotificationConfigsRequest( - parent="projects/_/buckets/bucket-name" - ), - context, - ) - names = {n.name for n in response.notification_configs} - self.assertEqual(names, expected) - def test_compose_object(self): payloads = { "fox": b"The quick brown fox jumps over the lazy dog\n", @@ -1870,298 +1696,6 @@ def test_list_objects_trailing_delimiters(self): response_names = [o.name for o in response.objects] self.assertEqual(response_names, case["expected"], msg=case) - def test_get_service_account(self): - context = unittest.mock.Mock() - response = self.grpc.GetServiceAccount( - storage_pb2.GetServiceAccountRequest(project="projects/test-project"), - context, - ) - self.assertIn("@", response.email_address) - - def test_get_service_account_failure(self): - context = unittest.mock.Mock() - _ = self.grpc.GetServiceAccount( - storage_pb2.GetServiceAccountRequest(project="invalid-format"), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_create_hmac_key(self): - sa_email = "test-sa@test-project-id.iam.gserviceaccount.com" - context = unittest.mock.Mock() - response = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa_email, - ), - context, - ) - self.assertNotEqual(response.secret_key_bytes, "") - self.assertNotEqual(response.metadata.id, "") - self.assertNotEqual(response.metadata.access_id, "") - self.assertEqual(response.metadata.service_account_email, sa_email) - self.assertNotEqual(response.metadata.etag, "") - - context = unittest.mock.Mock() - _ = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="invalid-project-name-format", - service_account_email=sa_email, - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - # Missing service account emails should fail - context = unittest.mock.Mock() - _ = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_delete_hmac_key(self): - sa_email = "test-sa@test-project-id.iam.gserviceaccount.com" - context = unittest.mock.Mock() - create = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa_email, - ), - context, - ) - - metadata = storage_pb2.HmacKeyMetadata() - metadata.CopyFrom(create.metadata) - metadata.state = "INACTIVE" - - context = unittest.mock.Mock() - response = self.grpc.UpdateHmacKey( - storage_pb2.UpdateHmacKeyRequest( - hmac_key=metadata, update_mask=field_mask_pb2.FieldMask(paths=["state"]) - ), - context, - ) - self.assertEqual(response.state, "INACTIVE") - - context = unittest.mock.Mock() - _ = self.grpc.DeleteHmacKey( - storage_pb2.DeleteHmacKeyRequest( - access_id=metadata.access_id, project=metadata.project - ), - context, - ) - context.abort.assert_not_called() - - # The code depends on `context.abort()` raising an exception. - context.abort = unittest.mock.MagicMock() - context.abort.side_effect = grpc.RpcError() - with self.assertRaises(grpc.RpcError): - _ = self.grpc.GetHmacKey( - storage_pb2.GetHmacKeyRequest( - access_id=metadata.access_id, project="projects/test-project-id" - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.NOT_FOUND, unittest.mock.ANY - ) - - # Missing or malformed project id is an error - context = unittest.mock.Mock() - _ = self.grpc.DeleteHmacKey( - storage_pb2.DeleteHmacKeyRequest(access_id=metadata.access_id), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_get_hmac_key(self): - sa_email = "test-sa@test-project-id.iam.gserviceaccount.com" - context = unittest.mock.Mock() - create = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa_email, - ), - context, - ) - - context = unittest.mock.Mock() - response = self.grpc.GetHmacKey( - storage_pb2.GetHmacKeyRequest( - access_id=create.metadata.access_id, project="projects/test-project-id" - ), - context, - ) - self.assertEqual(response, create.metadata) - - # Missing or malformed project id is an error - context = unittest.mock.Mock() - _ = self.grpc.GetHmacKey( - storage_pb2.GetHmacKeyRequest(access_id=create.metadata.access_id), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_list_hmac_keys(self): - # Create several keys for two different projects. - expected = [] - sa_emails = [ - "test-sa-1@test-project-id.iam.gserviceaccount.com", - "test-sa-2@test-project-id.iam.gserviceaccount.com", - ] - for sa in sa_emails: - for _ in [1, 2]: - context = unittest.mock.Mock() - create = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa, - ), - context, - ) - expected.append(create.metadata) - - # First test without any filtering - context = unittest.mock.Mock() - response = self.grpc.ListHmacKeys( - storage_pb2.ListHmacKeysRequest(project="projects/test-project-id"), - context, - ) - expected_access_ids = {k.access_id for k in expected} - self.assertEqual({k.access_id for k in response.hmac_keys}, expected_access_ids) - - # Then only for one of the sa emails - context = unittest.mock.Mock() - sa_filter = sa_emails[0] - response = self.grpc.ListHmacKeys( - storage_pb2.ListHmacKeysRequest( - project="projects/test-project-id", service_account_email=sa_filter - ), - context, - ) - expected_access_ids = { - k.access_id for k in expected if k.service_account_email == sa_filter - } - self.assertEqual({k.access_id for k in response.hmac_keys}, expected_access_ids) - - # Include deleted accounts (there are none, but should work) - context = unittest.mock.Mock() - sa_filter = sa_emails[0] - response = self.grpc.ListHmacKeys( - storage_pb2.ListHmacKeysRequest( - project="projects/test-project-id", - service_account_email=sa_filter, - show_deleted_keys=True, - ), - context, - ) - expected_access_ids = { - k.access_id for k in expected if k.service_account_email == sa_filter - } - self.assertEqual({k.access_id for k in response.hmac_keys}, expected_access_ids) - - # Missing or malformed project id is an error - context = unittest.mock.Mock() - _ = self.grpc.ListHmacKeys(storage_pb2.ListHmacKeysRequest(), context) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_update_hmac_key(self): - sa_email = "test-sa@test-project-id.iam.gserviceaccount.com" - context = unittest.mock.Mock() - create = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa_email, - ), - context, - ) - - metadata = storage_pb2.HmacKeyMetadata() - metadata.CopyFrom(create.metadata) - metadata.state = "INACTIVE" - - context = unittest.mock.Mock() - response = self.grpc.UpdateHmacKey( - storage_pb2.UpdateHmacKeyRequest( - hmac_key=metadata, update_mask=field_mask_pb2.FieldMask(paths=["state"]) - ), - context, - ) - self.assertEqual(response.id, metadata.id) - self.assertEqual(response.access_id, metadata.access_id) - self.assertEqual(response.project, metadata.project) - self.assertEqual(response.service_account_email, metadata.service_account_email) - self.assertEqual(response.state, metadata.state) - self.assertEqual(response.create_time, metadata.create_time) - - # Verify a missing, empty, or invalid update mask returns an error - for mask in [[], ["not-state"], ["state", "and-more"]]: - context = unittest.mock.Mock() - _ = self.grpc.UpdateHmacKey( - storage_pb2.UpdateHmacKeyRequest( - hmac_key=metadata, update_mask=field_mask_pb2.FieldMask(paths=mask) - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - # An empty metadata attribute is also an error - context = unittest.mock.Mock() - _ = self.grpc.UpdateHmacKey( - storage_pb2.UpdateHmacKeyRequest( - hmac_key=storage_pb2.HmacKeyMetadata(), - update_mask=field_mask_pb2.FieldMask(paths=["state"]), - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY - ) - - def test_update_hmac_key_bad_etag(self): - sa_email = "test-sa@test-project-id.iam.gserviceaccount.com" - context = unittest.mock.Mock() - create = self.grpc.CreateHmacKey( - storage_pb2.CreateHmacKeyRequest( - project="projects/test-project-id", - service_account_email=sa_email, - ), - context, - ) - - metadata = storage_pb2.HmacKeyMetadata() - metadata.CopyFrom(create.metadata) - metadata.state = "INACTIVE" - metadata.etag = "test-only-invalid" - - context = unittest.mock.Mock() - response = self.grpc.UpdateHmacKey( - storage_pb2.UpdateHmacKeyRequest( - hmac_key=metadata, update_mask=field_mask_pb2.FieldMask(paths=["state"]) - ), - context, - ) - context.abort.assert_called_once_with( - grpc.StatusCode.FAILED_PRECONDITION, unittest.mock.ANY - ) - def test_run(self): port, server = testbench.grpc_server.run(0, self.db) self.assertNotEqual(port, 0) diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index c56f0ccd..253a47a0 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -30,6 +30,7 @@ import testbench from google.storage.v2 import storage_pb2 from testbench import rest_server +from tests.format_multipart_upload import format_multipart_upload UPLOAD_QUANTUM = 256 * 1024 @@ -655,6 +656,230 @@ def test_retry_test_return_error_after_bytes(self): self.assertIn("size", create_rest) self.assertEqual(int(create_rest.get("size")), 2 * UPLOAD_QUANTUM) + def test_write_retry_test_stall_after_bytes(self): + # Create a new bucket + response = self.client.post( + "/storage/v1/b", data=json.dumps({"name": "bucket-name"}) + ) + self.assertEqual(response.status_code, 200) + + # Setup a stall for reading back the object. + response = self.client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "stall-for-1s-after-250K", + "stall-for-1s-after-300K", + ] + } + } + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + self.assertTrue( + response.headers.get("content-type").startswith("application/json") + ) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + test_id = create_rest.get("id") + + # Initiate resumable upload + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "resumable", "name": "stall"}, + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + + location = response.headers.get("location") + self.assertIn("upload_id=", location) + match = re.search(r"[&?]upload_id=([^&]+)", location) + self.assertIsNotNone(match, msg=location) + upload_id = match.group(1) + + # Upload the first 256KiB chunk of data and trigger the stall. + chunk = self._create_block(UPLOAD_QUANTUM) + self.assertEqual(len(chunk), UPLOAD_QUANTUM) + + start_time = time.perf_counter() + response = self.client.put( + f"/upload/storage/v1/b/bucket-name/o", + query_string={"upload_id": upload_id}, + headers={ + "content-range": "bytes 0-{len:d}/{obj_size:d}".format( + len=UPLOAD_QUANTUM - 1, obj_size=2 * UPLOAD_QUANTUM + ), + "x-retry-test-id": test_id, + }, + data=chunk, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertGreater(elapsed_time, 1) + self.assertEqual(response.status_code, 308) + + # Upload the second 256KiB chunk of data and trigger the stall again. + start_time = time.perf_counter() + chunk = self._create_block(UPLOAD_QUANTUM) + self.assertEqual(len(chunk), UPLOAD_QUANTUM) + response = self.client.put( + "/upload/storage/v1/b/bucket-name/o", + query_string={"upload_id": upload_id}, + headers={ + "content-range": "bytes 0-{len:d}/{obj_size:d}".format( + len=2 * UPLOAD_QUANTUM - 1, obj_size=2 * UPLOAD_QUANTUM + ), + "x-retry-test-id": test_id, + }, + data=chunk, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertGreater(elapsed_time, 1) + self.assertEqual(response.status_code, 200, msg=response.data) + + # Upload the second 256KiB chunk of data and check that stall not happen + start_time = time.perf_counter() + chunk = self._create_block(UPLOAD_QUANTUM) + self.assertEqual(len(chunk), UPLOAD_QUANTUM) + response = self.client.put( + "/upload/storage/v1/b/bucket-name/o", + query_string={"upload_id": upload_id}, + headers={ + "content-range": "bytes 0-{len:d}/{obj_size:d}".format( + len=2 * UPLOAD_QUANTUM - 1, obj_size=2 * UPLOAD_QUANTUM + ), + "x-retry-test-id": test_id, + }, + data=chunk, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertLess(elapsed_time, 1) + self.assertEqual(response.status_code, 200, msg=response.data) + + def test_write_retry_test_stall_single_shot(self): + # Create a new bucket + response = self.client.post( + "/storage/v1/b", data=json.dumps({"name": "bucket-name"}) + ) + self.assertEqual(response.status_code, 200) + + # Setup a stall for reading back the object. + response = self.client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "stall-for-1s-after-250K", + ] + } + } + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + self.assertTrue( + response.headers.get("content-type").startswith("application/json") + ) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + test_id = create_rest.get("id") + + # Upload the 256KiB of data and trigger the stall. + data = self._create_block(UPLOAD_QUANTUM) + self.assertEqual(len(data), UPLOAD_QUANTUM) + + start_time = time.perf_counter() + boundary, payload = format_multipart_upload({}, data) + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "stall"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertEqual(response.status_code, 200) + self.assertGreater(elapsed_time, 1) + + # Upload the data again and check that stall not happen. + start_time = time.perf_counter() + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "stall"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertLess(elapsed_time, 1) + self.assertEqual(response.status_code, 200) + + def test_write_retry_test_stall_single_shot_while_upload_size_less_than_stall_size( + self, + ): + # Create a new bucket + response = self.client.post( + "/storage/v1/b", data=json.dumps({"name": "bucket-name"}) + ) + self.assertEqual(response.status_code, 200) + + # Setup a stall for reading back the object. + response = self.client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "stall-for-1s-after-250K", + ] + } + } + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + self.assertTrue( + response.headers.get("content-type").startswith("application/json") + ) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + test_id = create_rest.get("id") + + # Upload the 200KiB of data and check stall not happen. + data = self._create_block(200 * 1024) + self.assertEqual(len(data), 200 * 1024) + + start_time = time.perf_counter() + boundary, payload = format_multipart_upload({}, data) + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "stall"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + end_time = time.perf_counter() + elapsed_time = end_time - start_time + self.assertEqual(response.status_code, 200) + self.assertLess(elapsed_time, 1) + class TestTestbenchRetryGrpc(unittest.TestCase): def setUp(self): From cc704ab42cf5489703db9d77ecbbd4ac9e9a21b5 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Fri, 25 Oct 2024 09:49:42 -0700 Subject: [PATCH 20/39] test: enable GCS bucket logs (#26) * use gcs for logs instead * enable both gcs bucket and monitoring --- cloudbuild_prelaunch.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cloudbuild_prelaunch.yaml b/cloudbuild_prelaunch.yaml index ed44005f..864fbd18 100644 --- a/cloudbuild_prelaunch.yaml +++ b/cloudbuild_prelaunch.yaml @@ -30,5 +30,6 @@ images: - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest -options: - logging: CLOUD_LOGGING_ONLY +# If you do not set `logging` option, Cloud Build stores the +# logs in both Cloud Logging and Cloud Storage. +logsBucket: 'gs://gcs-sdk-cloud-builds-logs' From 7b509661bea7f0f2078b8f36bbd786b154f63eb3 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 30 Oct 2024 11:36:27 -0400 Subject: [PATCH 21/39] feat(append): Import new proto patch. (#29) Internally generated the public proto as if all Bidi APIs were external, and regenerated this patch against .googleapis. Kept everything in one patch for simplicity. --- ...aming-read.patch => bidi-api-updates.patch | 160 +++++++++--- bidi-appendable-write.patch | 116 --------- google/storage/v2/storage_pb2.py | 240 +++++++++--------- google/storage/v2/storage_pb2_grpc.py | 12 +- update-protos.sh | 5 +- 5 files changed, 244 insertions(+), 289 deletions(-) rename bidi-streaming-read.patch => bidi-api-updates.patch (67%) delete mode 100644 bidi-appendable-write.patch diff --git a/bidi-streaming-read.patch b/bidi-api-updates.patch similarity index 67% rename from bidi-streaming-read.patch rename to bidi-api-updates.patch index 47db6565..a71513bf 100644 --- a/bidi-streaming-read.patch +++ b/bidi-api-updates.patch @@ -19,7 +19,7 @@ index 8fa25cc09..c17d0fe82 100644 ], ) diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index 0f9758f19..c9c027345 100644 +index c7229d4..c36fb4c 100644 --- a/google/storage/v2/storage.proto +++ b/google/storage/v2/storage.proto @@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; @@ -30,20 +30,10 @@ index 0f9758f19..c9c027345 100644 import "google/type/date.proto"; option go_package = "cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb"; -@@ -274,6 +275,26 @@ service Storage { +@@ -235,6 +236,16 @@ service Storage { option (google.api.method_signature) = "bucket,object,generation"; } -+ // Reads an object's data. -+ // -+ // This is a bi-directional API with the added support for reading multiple -+ // ranges within one stream both within and across multiple messages. This can -+ // improve performance compared with performing individual range read RPCs. -+ // If the server encountered an error for any of the inputs, the stream will -+ // be closed with the relevant error code. -+ // Because the API allows for multiple outstanding requests, when the stream -+ // is closed the error response will contain a BidiReadObjectRangesError proto -+ // in the error extension describing the error for each outstanding read_id. + rpc BidiReadObject(stream BidiReadObjectRequest) + returns (stream BidiReadObjectResponse) { + option (google.api.routing) = { @@ -57,22 +47,20 @@ index 0f9758f19..c9c027345 100644 // Updates an object's metadata. // Equivalent to JSON API's storage.objects.patch. rpc UpdateObject(UpdateObjectRequest) returns (Object) { -@@ -995,6 +1016,236 @@ message ReadObjectResponse { +@@ -847,6 +858,253 @@ message ReadObjectResponse { Object metadata = 4; } +// Describes the object to read in a BidiReadObject request. +message BidiReadObjectSpec { -+ // The name of the bucket containing the object to read. ++ // Required. The name of the bucket containing the object to read. + string bucket = 1 [ + (google.api.field_behavior) = REQUIRED, -+ (google.api.resource_reference).type = "storage.googleapis.com/Bucket" ++ (google.api.resource_reference) = { type: "storage.googleapis.com/Bucket" } + ]; + -+ // The name of the object to read. -+ string object = 2 [ -+ (google.api.field_behavior) = REQUIRED -+ ]; ++ // Required. The name of the object to read. ++ string object = 2 [(google.api.field_behavior) = REQUIRED]; + + // If present, selects a specific revision of this object (as opposed + // to the latest version, the default). @@ -98,9 +86,6 @@ index 0f9758f19..c9c027345 100644 + optional int64 if_metageneration_not_match = 7; + + // A set of parameters common to Storage API requests concerning an object. -+ // (-- api-linter: core::0131::request-unknown-fields=disabled -+ // aip.dev/not-precedent: All Cloud Storage object requests share a common -+ // set of parameters to handle billing and other per-request concerns. --) + CommonObjectRequestParams common_object_request_params = 8; + + // Mask specifying which fields to read. @@ -108,7 +93,10 @@ index 0f9758f19..c9c027345 100644 + // If no mask is specified, will default to all fields except metadata.owner + // and metadata.acl. + // * may be used to mean "all fields". -+ optional google.protobuf.FieldMask read_mask = 12; ++ // As per https://google.aip.dev/161, this field is deprecated. ++ // As an alternative, grpc metadata can be used: ++ // https://cloud.google.com/apis/docs/system-parameters#definitions ++ optional google.protobuf.FieldMask read_mask = 12 [deprecated = true]; + + // The client can optionally set this field. The read handle is an optimized + // way of creating new streams. Read handles are generated and periodically @@ -122,12 +110,9 @@ index 0f9758f19..c9c027345 100644 + +// Request message for BidiReadObject. +message BidiReadObjectRequest { -+ + // The first message of each stream must set this field. The stream returns an + // error if any subsequent message sets this field, or if the first message + // does not set the field. -+ // TODO(b/340927727): The oneof will be removed once the field is no longer -+ // referenced + oneof first_message { + // Describes the object to read + BidiReadObjectSpec read_spec = 6 [deprecated = true]; @@ -172,15 +157,13 @@ index 0f9758f19..c9c027345 100644 + // empty for any given `ReadResponse`. This enables the service to inform the + // client that the request is still live while it is running an operation to + // generate more data. -+ ChecksummedData checksummed_data = 1 -+ [deprecated = true]; ++ ChecksummedData checksummed_data = 1 [deprecated = true]; + + // The checksums of the complete object regardless of data range. If the + // object is downloaded in full, the client should compute one of these + // checksums over the downloaded object and compare it against the value + // provided here. -+ ObjectChecksums object_checksums = 2 -+ [deprecated = true]; ++ ObjectChecksums object_checksums = 2 [deprecated = true]; + + // If read_offset and or read_limit was specified on the + // ReadObjectRequest, ContentRange will be populated on the first @@ -213,7 +196,6 @@ index 0f9758f19..c9c027345 100644 +// Error proto containing details for a redirected read. This error is only +// returned on initial open in case of a redirect. +message BidiReadObjectRedirectedError { -+ + // The read handle for the redirected read. The client can use this for the + // subsequent open. + BidiReadHandle read_handle = 1; @@ -222,6 +204,22 @@ index 0f9758f19..c9c027345 100644 + optional string routing_token = 2; +} + ++// Error proto containing details for a redirected write. This error is only ++// returned on initial open in case of a redirect. ++message BidiWriteObjectRedirectedError { ++ // The routing token that should be used when reopening the write stream. ++ optional string routing_token = 1; ++ ++ // Opaque value describing a previous write. ++ optional BidiWriteHandle write_handle = 2; ++ ++ // The generation of the object that triggered the redirect. ++ // Note that if this error was returned as part of an appendable object ++ // create, this object generation is now successfully created and ++ // append_object_spec should be used when reconnecting. ++ optional int64 generation = 3; ++} ++ +// Error extension proto containing details for all outstanding reads on the +// failed stream +message BidiReadObjectError { @@ -233,14 +231,15 @@ index 0f9758f19..c9c027345 100644 +message ReadRangeError { + // The id of the corresponding read_range + int64 read_id = 1; ++ + // The status which should be an enum value of [google.rpc.Code]. + google.rpc.Status status = 2; +} + +// Describes a range of bytes to read in a BidiReadObjectRanges request. +message ReadRange { -+ // The offset for the first byte to return in the read, relative to the start -+ // of the object. ++ // Required. The offset for the first byte to return in the read, relative to ++ // the start of the object. + // + // A negative read_offset value will be interpreted as the number of bytes + // back from the end of the object to be returned. For example, if an object's @@ -251,19 +250,19 @@ index 0f9758f19..c9c027345 100644 + // will result in an OutOfRange error. + int64 read_offset = 1 [(google.api.field_behavior) = REQUIRED]; + -+ // The maximum number of data bytes the server is allowed to return across -+ // all response messages with the same read_id. A read_limit of zero ++ // Optional. The maximum number of data bytes the server is allowed to return ++ // across all response messages with the same read_id. A read_limit of zero + // indicates that there is no limit, and a negative read_limit will cause an + // error. If the stream returns fewer bytes than allowed by the read_limit + // and no error occurred, the stream includes all data from the read_offset + // to the resource end. + int64 read_limit = 2 [(google.api.field_behavior) = OPTIONAL]; + -+ // Read identifier provided by the client. When the client issues more than -+ // one outstanding ReadRange on the same stream, responses can be mapped back -+ // to their corresponding requests using this value. Clients must ensure that -+ // all outstanding requests have different read_id values. The server may -+ // close the stream with an error if this condition is not met. ++ // Required. Read identifier provided by the client. When the client issues ++ // more than one outstanding ReadRange on the same stream, responses can be ++ // mapped back to their corresponding requests using this value. Clients must ++ // ensure that all outstanding requests have different read_id values. The ++ // server may close the stream with an error if this condition is not met. + int64 read_id = 3 [(google.api.field_behavior) = REQUIRED]; +} + @@ -287,10 +286,89 @@ index 0f9758f19..c9c027345 100644 +// invocation. The client can use this instead of BidiReadObjectSpec as an +// optimized way of opening subsequent bidirectional streams to the same object. +message BidiReadHandle { -+ // Opaque value describing a previous read. ++ // Required. Opaque value describing a previous read. + bytes handle = 1 [(google.api.field_behavior) = REQUIRED]; +} ++ ++// BidiWriteHandle contains a handle from a previous BidiWriteObject ++// invocation. The client can use this as an optimized way of opening subsequent ++// bidirectional streams to the same object. ++message BidiWriteHandle { ++ // Opaque value describing a previous write. ++ bytes handle = 1; ++} + // Describes an attempt to insert an object, possibly over multiple requests. message WriteObjectSpec { // Required. Destination object, including its name and its metadata. +@@ -884,6 +1142,10 @@ message WriteObjectSpec { + // you must start the upload over from scratch, this time sending the correct + // number of bytes. + optional int64 object_size = 8; ++ ++ // If true, the object will be created in appendable mode. ++ // This field may only be set when using BidiWriteObject. ++ optional bool appendable = 9; + } + + // Request message for WriteObject. +@@ -953,6 +1215,37 @@ message WriteObjectResponse { + } + } + ++// Describes an attempt to append to an object, possibly over multiple requests. ++message AppendObjectSpec { ++ // Required. The name of the bucket containing the object to write. ++ string bucket = 1 [ ++ (google.api.field_behavior) = REQUIRED, ++ (google.api.resource_reference) = { type: "storage.googleapis.com/Bucket" } ++ ]; ++ ++ // Required. The name of the object to open for writing. ++ string object = 2 [(google.api.field_behavior) = REQUIRED]; ++ ++ // Required. The generation number of the object to open for writing. ++ int64 generation = 3 [(google.api.field_behavior) = REQUIRED]; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration matches the given value. ++ optional int64 if_metageneration_match = 4; ++ ++ // Makes the operation conditional on whether the object's current ++ // metageneration does not match the given value. ++ optional int64 if_metageneration_not_match = 5; ++ ++ // An optional routing token that influences request routing for the stream. ++ // Must be provided if a BidiWriteObjectRedirectedError is returned. ++ optional string routing_token = 6; ++ ++ // An optional write handle returned from a previous BidiWriteObjectResponse ++ // message or a BidiWriteObjectRedirectedError error. ++ optional BidiWriteHandle write_handle = 7; ++} ++ + // Request message for BidiWriteObject. + message BidiWriteObjectRequest { + // The first message of each stream should set one of the following. +@@ -964,6 +1257,9 @@ message BidiWriteObjectRequest { + // For non-resumable uploads. Describes the overall upload, including the + // destination bucket and object name, preconditions, etc. + WriteObjectSpec write_object_spec = 2; ++ ++ // For appendable uploads. Describes the object to append to. ++ AppendObjectSpec append_object_spec = 11; + } + + // Required. The offset from the beginning of the object at which the data +@@ -1035,6 +1331,11 @@ message BidiWriteObjectResponse { + // the upload has finalized. + Object resource = 2; + } ++ ++ // An optional write handle that will periodically be present in response ++ // messages. Clients should save it for later use in establishing a new stream ++ // if a connection is interrupted. ++ optional BidiWriteHandle write_handle = 3; + } + + // Request message for ListObjects. diff --git a/bidi-appendable-write.patch b/bidi-appendable-write.patch deleted file mode 100644 index 143eb3a5..00000000 --- a/bidi-appendable-write.patch +++ /dev/null @@ -1,116 +0,0 @@ -diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index c9c027345..0bcd970e0 100644 ---- a/google/storage/v2/storage.proto -+++ b/google/storage/v2/storage.proto -@@ -1177,6 +1171,22 @@ message BidiReadObjectRedirectedError { - optional string routing_token = 2; - } - -+// Error proto containing details for a redirected write. This error is only -+// returned on initial open in case of a redirect. -+message BidiWriteObjectRedirectedError { -+ // The routing token that should be used when reopening the write stream. -+ optional string routing_token = 1; -+ -+ // Opaque value describing a previous write. -+ optional BidiWriteHandle write_handle = 2; -+ -+ // The generation of the object that triggered the redirect. -+ // Note that if this error was returned as part of an appendable object -+ // create, this object generation is now successfully created and -+ // append_object_spec should be used when reconnecting. -+ optional int64 generation = 3; -+} -+ - // Error extension proto containing details for all outstanding reads on the - // failed stream - message BidiReadObjectError { -@@ -1246,6 +1262,14 @@ message BidiReadHandle { - bytes handle = 1 [(google.api.field_behavior) = REQUIRED]; - } - -+// BidiWriteHandle contains a handle from a previous BidiWriteObject -+// invocation. The client can use this as an optimized way of opening subsequent -+// bidirectional streams to the same object. -+message BidiWriteHandle { -+ // Opaque value describing a previous write. -+ bytes handle = 1; -+} -+ - // Describes an attempt to insert an object, possibly over multiple requests. - message WriteObjectSpec { - // Required. Destination object, including its name and its metadata. -@@ -1283,6 +1307,12 @@ message WriteObjectSpec { - // you must start the upload over from scratch, this time sending the correct - // number of bytes. - optional int64 object_size = 8; -+ -+ // If true, the object will be created in appendable mode. -+ // This field may only be set when using BidiWriteObject. -+ optional bool appendable = 9; -+ -+ reserved 2; - } - - // Request message for WriteObject. -@@ -1352,6 +1382,38 @@ message WriteObjectResponse { - } - } - -+// Describes an attempt to append to an object, possibly over multiple requests. -+message AppendObjectSpec { -+ // The name of the bucket containing the object to write. -+ string bucket = 1 [ -+ (google.api.resource_reference).type = "storage.googleapis.com/Bucket" -+ ]; -+ -+ // The name of the object to open for writing. -+ string object = 2 [ -+ (google.api.field_behavior) = REQUIRED -+ ]; -+ -+ // The generation number of the object to open for writing. -+ int64 generation = 3 [(google.api.field_behavior) = REQUIRED]; -+ -+ // Makes the operation conditional on whether the object's current -+ // metageneration matches the given value. -+ optional int64 if_metageneration_match = 4; -+ -+ // Makes the operation conditional on whether the object's current -+ // metageneration does not match the given value. -+ optional int64 if_metageneration_not_match = 5; -+ -+ // An optional routing token that influences request routing for the stream. -+ // Must be provided if a BidiWriteObjectRedirectedError is returned. -+ optional string routing_token = 6; -+ -+ // An optional write handle returned from a previous BidiWriteObjectResponse -+ // message or a BidiWriteObjectRedirectedError error. -+ optional BidiWriteHandle write_handle = 7; -+} -+ - // Request message for BidiWriteObject. - message BidiWriteObjectRequest { - // The first message of each stream should set one of the following. -@@ -1363,6 +1434,9 @@ message BidiWriteObjectRequest { - // For non-resumable uploads. Describes the overall upload, including the - // destination bucket and object name, preconditions, etc. - WriteObjectSpec write_object_spec = 2; -+ -+ // For appendable uploads. Describes the object to append to. -+ AppendObjectSpec append_object_spec = 11; - } - - // Required. The offset from the beginning of the object at which the data -@@ -1435,6 +1509,11 @@ message BidiWriteObjectResponse { - // the upload has finalized. - Object resource = 2; - } -+ -+ // An optional write handle that will periodically be present in response -+ // messages. Clients should save it for later use in establishing a new stream -+ // if a connection is interrupted. -+ optional BidiWriteHandle write_handle = 3; - } - - // Request message for ListObjects. diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index 9e28b3ad..57a33868 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -50,7 +50,7 @@ from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x8d\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xbb\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendableJ\x04\x08\x02\x10\x03\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xfe\x02\n\x10\x41ppendObjectSpec\x12\x32\n\x06\x62ucket\x18\x01 \x01(\tB\"\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xdf\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xa8\x1d\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x91\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x36\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x02\x18\x01H\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xb5\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendable\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\x81\x03\n\x10\x41ppendObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xdf\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xa8\x1d\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -110,6 +110,8 @@ _globals['_BIDIREADOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._loaded_options = None _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['read_mask']._loaded_options = None + _globals['_BIDIREADOBJECTSPEC'].fields_by_name['read_mask']._serialized_options = b'\030\001' _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._loaded_options = None _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._serialized_options = b'\030\001' _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._loaded_options = None @@ -137,7 +139,7 @@ _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._loaded_options = None _globals['_WRITEOBJECTREQUEST'].fields_by_name['write_offset']._serialized_options = b'\340A\002' _globals['_APPENDOBJECTSPEC'].fields_by_name['bucket']._loaded_options = None - _globals['_APPENDOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\372A\037\n\035storage.googleapis.com/Bucket' + _globals['_APPENDOBJECTSPEC'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' _globals['_APPENDOBJECTSPEC'].fields_by_name['object']._loaded_options = None _globals['_APPENDOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' _globals['_APPENDOBJECTSPEC'].fields_by_name['generation']._loaded_options = None @@ -329,121 +331,121 @@ _globals['_READOBJECTRESPONSE']._serialized_start=4901 _globals['_READOBJECTRESPONSE']._serialized_end=5146 _globals['_BIDIREADOBJECTSPEC']._serialized_start=5149 - _globals['_BIDIREADOBJECTSPEC']._serialized_end=5802 - _globals['_BIDIREADOBJECTREQUEST']._serialized_start=5805 - _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6074 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6077 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=6484 - _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=6487 - _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=6620 - _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_start=6623 - _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_end=6821 - _globals['_BIDIREADOBJECTERROR']._serialized_start=6823 - _globals['_BIDIREADOBJECTERROR']._serialized_end=6906 - _globals['_READRANGEERROR']._serialized_start=6908 - _globals['_READRANGEERROR']._serialized_end=6977 - _globals['_READRANGE']._serialized_start=6979 - _globals['_READRANGE']._serialized_end=7063 - _globals['_OBJECTRANGEDATA']._serialized_start=7066 - _globals['_OBJECTRANGEDATA']._serialized_end=7214 - _globals['_BIDIREADHANDLE']._serialized_start=7216 - _globals['_BIDIREADHANDLE']._serialized_end=7253 - _globals['_BIDIWRITEHANDLE']._serialized_start=7255 - _globals['_BIDIWRITEHANDLE']._serialized_end=7288 - _globals['_WRITEOBJECTSPEC']._serialized_start=7291 - _globals['_WRITEOBJECTSPEC']._serialized_end=7734 - _globals['_WRITEOBJECTREQUEST']._serialized_start=7737 - _globals['_WRITEOBJECTREQUEST']._serialized_end=8127 - _globals['_WRITEOBJECTRESPONSE']._serialized_start=8129 - _globals['_WRITEOBJECTRESPONSE']._serialized_end=8239 - _globals['_APPENDOBJECTSPEC']._serialized_start=8242 - _globals['_APPENDOBJECTSPEC']._serialized_end=8624 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8627 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=9125 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=9128 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9322 - _globals['_LISTOBJECTSREQUEST']._serialized_start=9325 - _globals['_LISTOBJECTSREQUEST']._serialized_end=9754 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9757 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9890 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9892 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=10007 - _globals['_REWRITEOBJECTREQUEST']._serialized_start=10010 - _globals['_REWRITEOBJECTREQUEST']._serialized_end=11330 - _globals['_REWRITERESPONSE']._serialized_start=11333 - _globals['_REWRITERESPONSE']._serialized_end=11484 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11487 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11729 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11731 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11779 - _globals['_UPDATEOBJECTREQUEST']._serialized_start=11782 - _globals['_UPDATEOBJECTREQUEST']._serialized_end=12277 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12279 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12403 - _globals['_SERVICECONSTANTS']._serialized_start=12406 - _globals['_SERVICECONSTANTS']._serialized_end=13120 - _globals['_SERVICECONSTANTS_VALUES']._serialized_start=12427 - _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13120 - _globals['_BUCKET']._serialized_start=13123 - _globals['_BUCKET']._serialized_end=16742 - _globals['_BUCKET_BILLING']._serialized_start=14564 - _globals['_BUCKET_BILLING']._serialized_end=14597 - _globals['_BUCKET_CORS']._serialized_start=14599 - _globals['_BUCKET_CORS']._serialized_end=14687 - _globals['_BUCKET_ENCRYPTION']._serialized_start=14689 - _globals['_BUCKET_ENCRYPTION']._serialized_end=14766 - _globals['_BUCKET_IAMCONFIG']._serialized_start=14769 - _globals['_BUCKET_IAMCONFIG']._serialized_end=15005 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=14915 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15005 - _globals['_BUCKET_LIFECYCLE']._serialized_start=15008 - _globals['_BUCKET_LIFECYCLE']._serialized_end=15763 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15078 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=15763 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15222 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15267 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15270 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=15763 - _globals['_BUCKET_LOGGING']._serialized_start=15765 - _globals['_BUCKET_LOGGING']._serialized_end=15821 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=15824 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=15967 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=15970 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16147 - _globals['_BUCKET_VERSIONING']._serialized_start=16149 - _globals['_BUCKET_VERSIONING']._serialized_end=16178 - _globals['_BUCKET_WEBSITE']._serialized_start=16180 - _globals['_BUCKET_WEBSITE']._serialized_end=16239 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16241 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16288 - _globals['_BUCKET_AUTOCLASS']._serialized_start=16291 - _globals['_BUCKET_AUTOCLASS']._serialized_end=16558 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=16560 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=16605 - _globals['_BUCKET_LABELSENTRY']._serialized_start=16607 - _globals['_BUCKET_LABELSENTRY']._serialized_end=16652 - _globals['_BUCKETACCESSCONTROL']._serialized_start=16745 - _globals['_BUCKETACCESSCONTROL']._serialized_end=16951 - _globals['_CHECKSUMMEDDATA']._serialized_start=16953 - _globals['_CHECKSUMMEDDATA']._serialized_end=17026 - _globals['_OBJECTCHECKSUMS']._serialized_start=17028 - _globals['_OBJECTCHECKSUMS']._serialized_end=17095 - _globals['_CUSTOMERENCRYPTION']._serialized_start=17097 - _globals['_CUSTOMERENCRYPTION']._serialized_end=17173 - _globals['_OBJECT']._serialized_start=17176 - _globals['_OBJECT']._serialized_end=18551 - _globals['_OBJECT_METADATAENTRY']._serialized_start=18423 - _globals['_OBJECT_METADATAENTRY']._serialized_end=18470 - _globals['_OBJECTACCESSCONTROL']._serialized_start=18554 - _globals['_OBJECTACCESSCONTROL']._serialized_end=18760 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=18762 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=18870 - _globals['_PROJECTTEAM']._serialized_start=18872 - _globals['_PROJECTTEAM']._serialized_end=18923 - _globals['_OWNER']._serialized_start=18925 - _globals['_OWNER']._serialized_end=18967 - _globals['_CONTENTRANGE']._serialized_start=18969 - _globals['_CONTENTRANGE']._serialized_end=19036 - _globals['_STORAGE']._serialized_start=19039 - _globals['_STORAGE']._serialized_end=22791 + _globals['_BIDIREADOBJECTSPEC']._serialized_end=5806 + _globals['_BIDIREADOBJECTREQUEST']._serialized_start=5809 + _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6078 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6081 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=6488 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=6491 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=6624 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_start=6627 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_end=6825 + _globals['_BIDIREADOBJECTERROR']._serialized_start=6827 + _globals['_BIDIREADOBJECTERROR']._serialized_end=6910 + _globals['_READRANGEERROR']._serialized_start=6912 + _globals['_READRANGEERROR']._serialized_end=6981 + _globals['_READRANGE']._serialized_start=6983 + _globals['_READRANGE']._serialized_end=7067 + _globals['_OBJECTRANGEDATA']._serialized_start=7070 + _globals['_OBJECTRANGEDATA']._serialized_end=7218 + _globals['_BIDIREADHANDLE']._serialized_start=7220 + _globals['_BIDIREADHANDLE']._serialized_end=7257 + _globals['_BIDIWRITEHANDLE']._serialized_start=7259 + _globals['_BIDIWRITEHANDLE']._serialized_end=7292 + _globals['_WRITEOBJECTSPEC']._serialized_start=7295 + _globals['_WRITEOBJECTSPEC']._serialized_end=7732 + _globals['_WRITEOBJECTREQUEST']._serialized_start=7735 + _globals['_WRITEOBJECTREQUEST']._serialized_end=8125 + _globals['_WRITEOBJECTRESPONSE']._serialized_start=8127 + _globals['_WRITEOBJECTRESPONSE']._serialized_end=8237 + _globals['_APPENDOBJECTSPEC']._serialized_start=8240 + _globals['_APPENDOBJECTSPEC']._serialized_end=8625 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8628 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=9126 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=9129 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9323 + _globals['_LISTOBJECTSREQUEST']._serialized_start=9326 + _globals['_LISTOBJECTSREQUEST']._serialized_end=9755 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9758 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9891 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9893 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=10008 + _globals['_REWRITEOBJECTREQUEST']._serialized_start=10011 + _globals['_REWRITEOBJECTREQUEST']._serialized_end=11331 + _globals['_REWRITERESPONSE']._serialized_start=11334 + _globals['_REWRITERESPONSE']._serialized_end=11485 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11488 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11730 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11732 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11780 + _globals['_UPDATEOBJECTREQUEST']._serialized_start=11783 + _globals['_UPDATEOBJECTREQUEST']._serialized_end=12278 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12280 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12404 + _globals['_SERVICECONSTANTS']._serialized_start=12407 + _globals['_SERVICECONSTANTS']._serialized_end=13121 + _globals['_SERVICECONSTANTS_VALUES']._serialized_start=12428 + _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13121 + _globals['_BUCKET']._serialized_start=13124 + _globals['_BUCKET']._serialized_end=16743 + _globals['_BUCKET_BILLING']._serialized_start=14565 + _globals['_BUCKET_BILLING']._serialized_end=14598 + _globals['_BUCKET_CORS']._serialized_start=14600 + _globals['_BUCKET_CORS']._serialized_end=14688 + _globals['_BUCKET_ENCRYPTION']._serialized_start=14690 + _globals['_BUCKET_ENCRYPTION']._serialized_end=14767 + _globals['_BUCKET_IAMCONFIG']._serialized_start=14770 + _globals['_BUCKET_IAMCONFIG']._serialized_end=15006 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=14916 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15006 + _globals['_BUCKET_LIFECYCLE']._serialized_start=15009 + _globals['_BUCKET_LIFECYCLE']._serialized_end=15764 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15079 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=15764 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15223 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15268 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15271 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=15764 + _globals['_BUCKET_LOGGING']._serialized_start=15766 + _globals['_BUCKET_LOGGING']._serialized_end=15822 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=15825 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=15968 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=15971 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16148 + _globals['_BUCKET_VERSIONING']._serialized_start=16150 + _globals['_BUCKET_VERSIONING']._serialized_end=16179 + _globals['_BUCKET_WEBSITE']._serialized_start=16181 + _globals['_BUCKET_WEBSITE']._serialized_end=16240 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16242 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16289 + _globals['_BUCKET_AUTOCLASS']._serialized_start=16292 + _globals['_BUCKET_AUTOCLASS']._serialized_end=16559 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=16561 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=16606 + _globals['_BUCKET_LABELSENTRY']._serialized_start=16608 + _globals['_BUCKET_LABELSENTRY']._serialized_end=16653 + _globals['_BUCKETACCESSCONTROL']._serialized_start=16746 + _globals['_BUCKETACCESSCONTROL']._serialized_end=16952 + _globals['_CHECKSUMMEDDATA']._serialized_start=16954 + _globals['_CHECKSUMMEDDATA']._serialized_end=17027 + _globals['_OBJECTCHECKSUMS']._serialized_start=17029 + _globals['_OBJECTCHECKSUMS']._serialized_end=17096 + _globals['_CUSTOMERENCRYPTION']._serialized_start=17098 + _globals['_CUSTOMERENCRYPTION']._serialized_end=17174 + _globals['_OBJECT']._serialized_start=17177 + _globals['_OBJECT']._serialized_end=18552 + _globals['_OBJECT_METADATAENTRY']._serialized_start=18424 + _globals['_OBJECT_METADATAENTRY']._serialized_end=18471 + _globals['_OBJECTACCESSCONTROL']._serialized_start=18555 + _globals['_OBJECTACCESSCONTROL']._serialized_end=18761 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=18763 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=18871 + _globals['_PROJECTTEAM']._serialized_start=18873 + _globals['_PROJECTTEAM']._serialized_end=18924 + _globals['_OWNER']._serialized_start=18926 + _globals['_OWNER']._serialized_end=18968 + _globals['_CONTENTRANGE']._serialized_start=18970 + _globals['_CONTENTRANGE']._serialized_end=19037 + _globals['_STORAGE']._serialized_start=19040 + _globals['_STORAGE']._serialized_end=22792 # @@protoc_insertion_point(module_scope) diff --git a/google/storage/v2/storage_pb2_grpc.py b/google/storage/v2/storage_pb2_grpc.py index ce4a19a7..a1c453b0 100644 --- a/google/storage/v2/storage_pb2_grpc.py +++ b/google/storage/v2/storage_pb2_grpc.py @@ -342,17 +342,7 @@ def ReadObject(self, request, context): raise NotImplementedError('Method not implemented!') def BidiReadObject(self, request_iterator, context): - """Reads an object's data. - - This is a bi-directional API with the added support for reading multiple - ranges within one stream both within and across multiple messages. This can - improve performance compared with performing individual range read RPCs. - If the server encountered an error for any of the inputs, the stream will - be closed with the relevant error code. - Because the API allows for multiple outstanding requests, when the stream - is closed the error response will contain a BidiReadObjectRangesError proto - in the error extension describing the error for each outstanding read_id. - """ + """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') diff --git a/update-protos.sh b/update-protos.sh index cc9a0408..c8773363 100755 --- a/update-protos.sh +++ b/update-protos.sh @@ -42,8 +42,9 @@ else git -C "${GOOGLEAPIS_ROOT}" checkout master git -C "${GOOGLEAPIS_ROOT}" pull fi -env -C "${GOOGLEAPIS_ROOT}" patch -p1 <$PWD/bidi-streaming-read.patch -env -C "${GOOGLEAPIS_ROOT}" patch -p1 <$PWD/bidi-appendable-write.patch +for f in "${PWD}"/*.patch ; do + env -C "${GOOGLEAPIS_ROOT}" patch -p1 <$PWD/*.patch +done for input in "${INPUTS[@]}"; do python -m grpc_tools.protoc -I"${GOOGLEAPIS_ROOT}" \ From 47c63fa7aeaccea2e66d86ca5fbf8f08a5cb75d9 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 4 Nov 2024 14:19:31 -0500 Subject: [PATCH 22/39] feat: Only RAPID supports appendable objects. (#30) * feat: Only RAPID supports appendable objects. This restriction is subject to change. * address lint issues --- gcs/upload.py | 5 +++++ tests/test_grpc_server.py | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/gcs/upload.py b/gcs/upload.py index cdb5516a..a593072a 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -311,6 +311,11 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): ).metadata upload = cls.__init_first_write_grpc(first_msg, bucket, context) if first_msg.write_object_spec.appendable: + if bucket.storage_class != "RAPID": + testbench.error.invalid( + f"Appendable object in {bucket.storage_class} storage class", + context, + ) is_appendable = True appendable_metadata_in_first_response = True db.insert_upload(upload) diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 303b2a99..f8306649 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -1859,11 +1859,39 @@ def test_bidi_write_object_resumable(self): self.assertEqual(blob.name, "object-name") self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + def test_bidi_write_object_appendable_unsupported(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + req = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/bucket-name" + ), + appendable=True, + ), + ) + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiWriteObject([req], context=context) + responses = list(streamer) + def test_bidi_write_object_appendable(self): # The code depends on `context.abort()` raising an exception. context = self.mock_context() context.abort.side_effect = grpc.RpcError() + # Only the RAPID storage class supports appendable objects at this time. + self.grpc.CreateBucket( + storage_pb2.CreateBucketRequest( + parent="projects/test-project", + bucket_id="rapid-bucket", + bucket=storage_pb2.Bucket( + storage_class="RAPID", + ), + ), + context, + ) + QUANTUM = 256 * 1024 media = TestGrpc._create_block(2 * QUANTUM + QUANTUM / 2).encode("utf-8") offset = 0 @@ -1871,7 +1899,7 @@ def test_bidi_write_object_appendable(self): r1 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/bucket-name" + name="object-name", bucket="projects/_/buckets/rapid-bucket" ), appendable=True, ), @@ -1899,7 +1927,9 @@ def test_bidi_write_object_appendable(self): # For appendable objects, we expect the object metadata in the first # response rather than the persisted_size. self.assertEqual(responses[0].resource.size, 2 * QUANTUM) - self.assertEqual(responses[0].resource.bucket, "projects/_/buckets/bucket-name") + self.assertEqual( + responses[0].resource.bucket, "projects/_/buckets/rapid-bucket" + ) self.assertEqual(responses[0].resource.name, "object-name") bucket = responses[0].resource.bucket @@ -1939,7 +1969,7 @@ def test_bidi_write_object_appendable(self): blob = responses[1].resource self.assertEqual(responses[1].resource.size, 2 * QUANTUM + QUANTUM / 2) self.assertEqual(blob.name, "object-name") - self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + self.assertEqual(blob.bucket, "projects/_/buckets/rapid-bucket") def test_bidi_write_object_no_requests(self): # The code depends on `context.abort()` raising an exception. From 5dc6590213565349aab6a68d7cf8acb5a35cab22 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 6 Nov 2024 21:01:03 -0500 Subject: [PATCH 23/39] feat(append): Support instructions for redirect. (#31) Appendable objects support a redirection protocol. Support instructions to force redirection errors. The redirection string itself is opaque, so for caller convenience we allow any hyphen-separated string of lowercase alphabetic characters. --- README.md | 19 ++++ testbench/common.py | 33 ++++++- testbench/database.py | 2 + testbench/grpc_server.py | 34 +++++++ tests/test_testbench_retry.py | 168 ++++++++++++++++++++++++++++++++++ 5 files changed, 253 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c648aa7f..c24769e1 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ is expected to be used by Storage library maintainers. - [stall-at-256KiB](#stall-at-256kib) - [return-503-after-256K](#return-503-after-256k) - [return-503-after-256K/retry-N](#return-503-after-256kretry-n) + - [redirect-send-token-T](#redirect-send-token-t) + - [redirect-expect-token-T](#redirect-expect-token-t) - [Retry Test API](#retry-test-api) - [Creating a new Retry Test](#creating-a-new-retry-test) - [Get a Retry Test resource](#get-a-retry-test-resource) @@ -176,6 +178,22 @@ failure instruction and return successfully. This is used to test failures durin retry, the client cooperates by sending the retry counter in the failure instructions. +### redirect-send-token-T + +In gRPC, set initial metadata with `x-goog-emulator-instructions: redirect-send-token-tokenval`. +Testbench will fail redirectable RPCs with `routing_token` set to the value `T` +(`tokenval` in the example). + +### redirect-expect-token-T + +In gRPC, set initial metadata with `x-goog-emulator-instructions: redirect-expect-token-tokenval`. +Testbench will consume the instruction if the RPC also specifies +`x-goog-request-params: routing_token=T` (`routing_token=tokenval` in the +example). + +Note that `x-goog-request-params` supports multiple key-value pairs, encoded +like URL query parameters. + ## Retry Test API @@ -247,6 +265,7 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 | return-broken-stream-after-YK | [HTTP] Testbench will fail after YKiB of downloaded data
[GRPC] Testbench will fail with `UNAVAILABLE` after YKiB of downloaded data | return-reset-connection | [HTTP] Testbench will fail with a reset connection
[GRPC] Testbench will fail the RPC with `UNAVAILABLE` | stall-for-Ts-after-YK | [HTTP] Testbench will stall for T second after reading YKiB of downloaded/uploaded data, e.g. stall-for-10s-after-12K stalls after reading/writing 12KiB of data
[GRPC] Not supported +| redirect-send-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. ## Releasing the testbench diff --git a/testbench/common.py b/testbench/common.py index 5f7399ca..ca6077dd 100644 --- a/testbench/common.py +++ b/testbench/common.py @@ -48,6 +48,8 @@ r"return-broken-stream-after-([0-9]+)K$" ) retry_stall_after_bytes = re.compile(r"stall-for-([0-9]+)s-after-([0-9]+)K$") +retry_return_redirection_token = re.compile(r"redirect-send-token-([a-z\-]+)$") +retry_expect_redirection_token = re.compile(r"redirect-expect-token-([a-z\-]+)$") content_range_split = re.compile(r"bytes (\*|[0-9]+-[0-9]+|[0-9]+-\*)\/(\*|[0-9]+)") @@ -1039,17 +1041,26 @@ def handle_grpc_retry_uploads_error_after_bytes( testbench.error.inject_error(context, rest_code, grpc_code, msg=msg) -def get_retry_test_id_from_context(context): - """Get the retry test id from context; returns None if not found.""" +def _get_invocation_metadata_value_from_context(context, k): if context is not None: if hasattr(context, "invocation_metadata") and isinstance( context.invocation_metadata(), tuple # Handle mocks in tests ): for key, value in context.invocation_metadata(): - if key == "x-retry-test-id": + if key == k: return value +def get_retry_test_id_from_context(context): + """Get the retry test id from context; returns None if not found.""" + return _get_invocation_metadata_value_from_context(context, "x-retry-test-id") + + +def get_context_request_params(context): + """Get gRPC request parameters from context; returns None if not found.""" + return _get_invocation_metadata_value_from_context(context, "x-goog-request-params") + + def get_broken_stream_after_bytes(instruction): """Get after_bytes for return-broken-stream retry instructions; returns 0 if instructions do not apply.""" after_bytes = 0 @@ -1070,6 +1081,22 @@ def get_broken_stream_after_bytes(instruction): return after_bytes +def get_return_redirect_token(instruction): + retry_redirection_token_matches = ( + testbench.common.retry_return_redirection_token.match(instruction) + ) + if retry_redirection_token_matches: + return list(retry_redirection_token_matches.groups())[0] + + +def get_expect_redirect_token(instruction): + retry_expect_redirection_token_matches = ( + testbench.common.retry_expect_redirection_token.match(instruction) + ) + if retry_expect_redirection_token_matches: + return list(retry_expect_redirection_token_matches.groups())[0] + + def handle_gzip_request(request): """ Handle gzip compressed JSON payloads when Content-Encoding: gzip is present on metadata requests. diff --git a/testbench/database.py b/testbench/database.py index 65412f11..b220ae07 100644 --- a/testbench/database.py +++ b/testbench/database.py @@ -585,6 +585,8 @@ def __validate_injected_failure_description(self, failure): testbench.common.retry_return_short_response, testbench.common.retry_return_broken_stream_after_bytes, testbench.common.retry_stall_after_bytes, + testbench.common.retry_return_redirection_token, + testbench.common.retry_expect_redirection_token, ]: if expr.match(failure) is not None: return diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 4cca0343..51199d31 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -845,6 +845,40 @@ def WriteObject(self, request_iterator, context): @retry_test(method="storage.objects.insert") def BidiWriteObject(self, request_iterator, context): + test_id = testbench.common.get_retry_test_id_from_context(context) + method = "storage.objects.insert" + if test_id and self.db.has_instructions_retry_test( + test_id, method, transport="GRPC" + ): + next_instruction = self.db.peek_next_instruction(test_id, method) + expected_redirect_token = testbench.common.get_expect_redirect_token( + next_instruction + ) + if expected_redirect_token: + request_params = testbench.common.get_context_request_params(context) + if ( + request_params + and f"routing_token={expected_redirect_token}" in request_params + ): + self.db.dequeue_next_instruction(test_id, method) + return_redirect_token = testbench.common.get_return_redirect_token( + next_instruction + ) + if return_redirect_token: + detail = any_pb2.Any() + detail.Pack( + storage_pb2.BidiWriteObjectRedirectedError( + routing_token=return_redirect_token + ) + ) + status_proto = status_pb2.Status( + code=grpc.StatusCode.ABORTED.value[0], + message=grpc.StatusCode.ABORTED.value[1], + details=[detail], + ) + self.db.dequeue_next_instruction(test_id, method) + context.abort_with_status(rpc_status.to_status(status_proto)) + return gcs.upload.Upload.process_bidi_write_object_grpc( self.db, request_iterator, context ) diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index 253a47a0..8042d994 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -18,13 +18,16 @@ import json import os +import random import re +import string import time import unittest import unittest.mock import crc32c from grpc import RpcError, StatusCode +from grpc_status import rpc_status import gcs import testbench @@ -1176,6 +1179,171 @@ def test_grpc_bidiwrite_return_error_after_bytes(self): self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") self.assertEqual(blob.size, 2 * UPLOAD_QUANTUM) + def test_grpc_bidiwrite_redirect_expect_token_match(self): + token = "".join(random.choice(string.ascii_lowercase) for _ in range(5)) + response = self.rest_client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + f"redirect-expect-token-{token}", + ], + }, + "transport": "GRPC", + } + ), + ) + self.assertEqual(response.status_code, 200) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + id = create_rest.get("id") + + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/bucket-name" + ), + appendable=True, + ), + ) + r2 = storage_pb2.BidiWriteObjectRequest() + r2.CopyFrom(r1) + + context = unittest.mock.Mock() + # The code depends on `context.abort_with_status()` raising an exception. + context.abort_with_status = unittest.mock.MagicMock() + context.abort_with_status.side_effect = RpcError() + + # With an incorrect routing token, we still have an instruction + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + "bucket=projects/_/buckets/bucket-name&routing_token=incorrect_token", + ), + ) + ) + _ = list(self.grpc.BidiWriteObject([r1], context=context)) + self.assertIsNotNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + + # With the correct routing token, we no longer have a problem. + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + f"bucket=projects/_/buckets/bucket-name&routing_token={token}", + ), + ) + ) + _ = list(self.grpc.BidiWriteObject([r2], context=context)) + self.assertIsNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + + class _StatusAsCall: + """_StatusAsCall wraps a status and pretends it is a client-side call""" + + def __init__(self, grpc_status): + self._grpc_status = grpc_status + + def trailing_metadata(self): + return self._grpc_status.trailing_metadata + + def code(self): + return self._grpc_status.code + + def details(self): + return self._grpc_status.details + + def _unpack_details(self, status, msg): + status_proto = rpc_status.from_call(self._StatusAsCall(status)) + self.assertEqual(len(status_proto.details), 1) + status_proto.details[0].Unpack(msg) + + def test_grpc_bidiwrite_create_routing_only_redirect(self): + response = self.rest_client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "redirect-send-token-sometoken", + "redirect-expect-token-sometoken", + ], + }, + "transport": "GRPC", + } + ), + ) + self.assertEqual(response.status_code, 200) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + id = create_rest.get("id") + + context = unittest.mock.Mock() + # The code depends on `context.abort_with_status()` raising an exception. + context.abort_with_status = unittest.mock.MagicMock() + context.abort_with_status.side_effect = RpcError() + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/bucket-name" + ), + appendable=True, + ), + ) + r2 = storage_pb2.BidiWriteObjectRequest() + r2.CopyFrom(r1) + + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + "bucket=projects/_/buckets/bucket-name", + ), + ) + ) + with self.assertRaises(RpcError): + streamer = self.grpc.BidiWriteObject([r1], context=context) + responses = list(streamer) + + context.abort_with_status.assert_called() + status = context.abort_with_status.call_args.args[0] + self.assertEqual(status.code, StatusCode.ABORTED) + redirect_error = storage_pb2.BidiWriteObjectRedirectedError() + self._unpack_details(status, redirect_error) + + self.assertFalse(redirect_error.HasField("generation")) + self.assertFalse(redirect_error.HasField("write_handle")) + self.assertEqual(redirect_error.routing_token, "sometoken") + + # If we set the right routing token, it should consume instructions. + self.assertIsNotNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + f"bucket=projects/_/buckets/bucket-name&routing_token={redirect_error.routing_token}", + ), + ) + ) + streamer = self.grpc.BidiWriteObject([r2], context=context) + responses = list(streamer) + self.assertIsNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + def test_grpc_bidiread_retry_broken_stream(self): # Use the XML API to inject an object with some data. media = self._create_block(5 * 1024 * 1024) From d6183b472f6a056ede3afdede82d0a5c931c2668 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Fri, 8 Nov 2024 23:39:27 -0500 Subject: [PATCH 24/39] feat(append): Redirect-with-handle instructions. (#32) Redirection may or may not include a write_handle. This supports instructions for returning a redirect that _does_ include the write_handle. --- README.md | 9 ++++ gcs/upload.py | 25 +++++++++++ testbench/common.py | 44 ++++++++++++++----- testbench/database.py | 1 + testbench/grpc_server.py | 57 +++++++++++------------- tests/test_testbench_retry.py | 83 +++++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index c24769e1..ccfe5ca9 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ is expected to be used by Storage library maintainers. - [return-503-after-256K](#return-503-after-256k) - [return-503-after-256K/retry-N](#return-503-after-256kretry-n) - [redirect-send-token-T](#redirect-send-token-t) + - [redirect-send-handle-and-token-T](#redirect-send-handle-and-token-t) - [redirect-expect-token-T](#redirect-expect-token-t) - [Retry Test API](#retry-test-api) - [Creating a new Retry Test](#creating-a-new-retry-test) @@ -184,6 +185,13 @@ In gRPC, set initial metadata with `x-goog-emulator-instructions: redirect-send- Testbench will fail redirectable RPCs with `routing_token` set to the value `T` (`tokenval` in the example). +### redirect-send-handle-and-token-T + +In gRPC, set initial metadata with `x-goog-emulator-instructions: redirect-send-handle-and-token-tokenval`. +Testbench will fail redirectable RPCs with `routing_token` set to the value `T` +(`tokenval` in the example) and a `write_handle` (`read_handle` is not currently +supported). + ### redirect-expect-token-T In gRPC, set initial metadata with `x-goog-emulator-instructions: redirect-expect-token-tokenval`. @@ -266,6 +274,7 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 | return-reset-connection | [HTTP] Testbench will fail with a reset connection
[GRPC] Testbench will fail the RPC with `UNAVAILABLE` | stall-for-Ts-after-YK | [HTTP] Testbench will stall for T second after reading YKiB of downloaded/uploaded data, e.g. stall-for-10s-after-12K stalls after reading/writing 12KiB of data
[GRPC] Not supported | redirect-send-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. +| redirect-send-handle-and-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. ## Releasing the testbench diff --git a/gcs/upload.py b/gcs/upload.py index a593072a..a9411fc4 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -22,7 +22,11 @@ import crc32c import flask +import google.protobuf.any_pb2 as any_pb2 +import grpc from google.protobuf import json_format +from google.rpc import status_pb2 +from grpc_status import rpc_status import gcs import testbench @@ -318,6 +322,7 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): ) is_appendable = True appendable_metadata_in_first_response = True + upload.metadata.generation = gcs.object.make_generation() db.insert_upload(upload) elif write_type == "append_object_spec": is_appendable = True @@ -331,6 +336,23 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): if first_msg.HasField("object_checksums"): object_checksums = first_msg.object_checksums + return_redirect_token = testbench.common.get_return_handle_and_redirect_token( + db, context + ) + if return_redirect_token: + err = storage_pb2.BidiWriteObjectRedirectedError() + err.generation = upload.metadata.generation + err.write_handle.handle = bytes(upload.upload_id, "utf-8") + err.routing_token = return_redirect_token + detail = any_pb2.Any() + detail.Pack(err) + status_proto = status_pb2.Status( + code=grpc.StatusCode.ABORTED.value[0], + message=grpc.StatusCode.ABORTED.value[1], + details=[detail], + ) + context.abort_with_status(rpc_status.to_status(status_proto)) + # Treat the rest of the first message as a data request, then keep # pulling from request_iterator first_msg.ClearField("first_message") @@ -466,6 +488,7 @@ def response(msg): # Create a new object when the write is completed. if upload.complete: + generation = upload.metadata.generation blob, _ = gcs.object.Object.init( upload.request, upload.metadata, @@ -474,6 +497,8 @@ def response(msg): False, context, ) + if generation: + blob.metadata.generation = generation upload.blob = blob db.insert_object( upload.bucket.name, diff --git a/testbench/common.py b/testbench/common.py index ca6077dd..81cabad7 100644 --- a/testbench/common.py +++ b/testbench/common.py @@ -49,6 +49,9 @@ ) retry_stall_after_bytes = re.compile(r"stall-for-([0-9]+)s-after-([0-9]+)K$") retry_return_redirection_token = re.compile(r"redirect-send-token-([a-z\-]+)$") +retry_return_handle_and_redirection_token = re.compile( + r"redirect-send-handle-and-token-([a-z\-]+)$" +) retry_expect_redirection_token = re.compile(r"redirect-expect-token-([a-z\-]+)$") content_range_split = re.compile(r"bytes (\*|[0-9]+-[0-9]+|[0-9]+-\*)\/(\*|[0-9]+)") @@ -1081,20 +1084,41 @@ def get_broken_stream_after_bytes(instruction): return after_bytes -def get_return_redirect_token(instruction): - retry_redirection_token_matches = ( - testbench.common.retry_return_redirection_token.match(instruction) +def _get_grpc_instruction_match(db, context, method, rexp, dequeue=True): + test_id = get_retry_test_id_from_context(context) + if not ( + test_id and db.has_instructions_retry_test(test_id, method, transport="GRPC") + ): + return None + + instruction = db.peek_next_instruction(test_id, method) + matches = rexp.match(instruction) + if matches: + if dequeue: + db.dequeue_next_instruction(test_id, method) + return list(matches.groups())[0] + + +def get_return_redirect_token(db, context): + return _get_grpc_instruction_match( + db, context, "storage.objects.insert", retry_return_redirection_token + ) + + +def get_return_handle_and_redirect_token(db, context): + return _get_grpc_instruction_match( + db, context, "storage.objects.insert", retry_return_handle_and_redirection_token ) - if retry_redirection_token_matches: - return list(retry_redirection_token_matches.groups())[0] -def get_expect_redirect_token(instruction): - retry_expect_redirection_token_matches = ( - testbench.common.retry_expect_redirection_token.match(instruction) +def get_expect_redirect_token(db, context): + return _get_grpc_instruction_match( + db, + context, + "storage.objects.insert", + retry_expect_redirection_token, + dequeue=False, ) - if retry_expect_redirection_token_matches: - return list(retry_expect_redirection_token_matches.groups())[0] def handle_gzip_request(request): diff --git a/testbench/database.py b/testbench/database.py index b220ae07..42d237d4 100644 --- a/testbench/database.py +++ b/testbench/database.py @@ -586,6 +586,7 @@ def __validate_injected_failure_description(self, failure): testbench.common.retry_return_broken_stream_after_bytes, testbench.common.retry_stall_after_bytes, testbench.common.retry_return_redirection_token, + testbench.common.retry_return_handle_and_redirection_token, testbench.common.retry_expect_redirection_token, ]: if expr.match(failure) is not None: diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 51199d31..3d0dda7a 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -845,39 +845,34 @@ def WriteObject(self, request_iterator, context): @retry_test(method="storage.objects.insert") def BidiWriteObject(self, request_iterator, context): - test_id = testbench.common.get_retry_test_id_from_context(context) - method = "storage.objects.insert" - if test_id and self.db.has_instructions_retry_test( - test_id, method, transport="GRPC" - ): - next_instruction = self.db.peek_next_instruction(test_id, method) - expected_redirect_token = testbench.common.get_expect_redirect_token( - next_instruction + expected_redirect_token = testbench.common.get_expect_redirect_token( + self.db, context + ) + if expected_redirect_token: + request_params = testbench.common.get_context_request_params(context) + if ( + request_params + and f"routing_token={expected_redirect_token}" in request_params + ): + test_id = testbench.common.get_retry_test_id_from_context(context) + self.db.dequeue_next_instruction(test_id, "storage.objects.insert") + + return_redirect_token = testbench.common.get_return_redirect_token( + self.db, context + ) + if return_redirect_token: + detail = any_pb2.Any() + detail.Pack( + storage_pb2.BidiWriteObjectRedirectedError( + routing_token=return_redirect_token + ) ) - if expected_redirect_token: - request_params = testbench.common.get_context_request_params(context) - if ( - request_params - and f"routing_token={expected_redirect_token}" in request_params - ): - self.db.dequeue_next_instruction(test_id, method) - return_redirect_token = testbench.common.get_return_redirect_token( - next_instruction + status_proto = status_pb2.Status( + code=grpc.StatusCode.ABORTED.value[0], + message=grpc.StatusCode.ABORTED.value[1], + details=[detail], ) - if return_redirect_token: - detail = any_pb2.Any() - detail.Pack( - storage_pb2.BidiWriteObjectRedirectedError( - routing_token=return_redirect_token - ) - ) - status_proto = status_pb2.Status( - code=grpc.StatusCode.ABORTED.value[0], - message=grpc.StatusCode.ABORTED.value[1], - details=[detail], - ) - self.db.dequeue_next_instruction(test_id, method) - context.abort_with_status(rpc_status.to_status(status_proto)) + context.abort_with_status(rpc_status.to_status(status_proto)) return gcs.upload.Upload.process_bidi_write_object_grpc( self.db, request_iterator, context diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index 8042d994..b629cb49 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -1344,6 +1344,89 @@ def test_grpc_bidiwrite_create_routing_only_redirect(self): rest_server.db.peek_next_instruction(id, "storage.objects.insert") ) + def test_grpc_bidiwrite_create_redirect(self): + response = self.rest_client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "redirect-send-handle-and-token-sometoken", + "redirect-expect-token-sometoken", + ], + }, + "transport": "GRPC", + } + ), + ) + self.assertEqual(response.status_code, 200) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + id = create_rest.get("id") + + context = unittest.mock.Mock() + # The code depends on `context.abort_with_status()` raising an exception. + context.abort_with_status = unittest.mock.MagicMock() + context.abort_with_status.side_effect = RpcError() + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/bucket-name" + ), + appendable=True, + ), + ) + + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + "bucket=projects/_/buckets/bucket-name", + ), + ) + ) + with self.assertRaises(RpcError): + streamer = self.grpc.BidiWriteObject([r1], context=context) + responses = list(streamer) + + context.abort_with_status.assert_called() + status = context.abort_with_status.call_args.args[0] + self.assertEqual(status.code, StatusCode.ABORTED) + redirect_error = storage_pb2.BidiWriteObjectRedirectedError() + self._unpack_details(status, redirect_error) + + self.assertTrue(redirect_error.HasField("write_handle")) + self.assertEqual(redirect_error.routing_token, "sometoken") + + # If we set the right routing token, it should consume instructions. + self.assertIsNotNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + r2 = storage_pb2.BidiWriteObjectRequest( + append_object_spec=storage_pb2.AppendObjectSpec( + bucket="projects/_/buckets/bucket-name", + object="object-name", + generation=redirect_error.generation, + write_handle=redirect_error.write_handle, + ), + ) + context.invocation_metadata = unittest.mock.Mock( + return_value=( + ("x-retry-test-id", id), + ( + "x-goog-request-params", + f"bucket=projects/_/buckets/bucket-name&routing_token={redirect_error.routing_token}", + ), + ) + ) + streamer = self.grpc.BidiWriteObject([r2], context=context) + responses = list(streamer) + self.assertIsNone( + rest_server.db.peek_next_instruction(id, "storage.objects.insert") + ) + def test_grpc_bidiread_retry_broken_stream(self): # Use the XML API to inject an object with some data. media = self._create_block(5 * 1024 * 1024) From 0a4b165b615bae4e8024fae167595af6bfca0c9a Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 11 Nov 2024 17:59:42 -0500 Subject: [PATCH 25/39] feat(append): Update Object with finalize_time. (#33) finalize_time can be used to identify unfinalized objects, i.e. appendable objects. --- bidi-api-updates.patch | 25 +++++++++++++++++++++-- google/storage/v2/storage_pb2.py | 34 +++++++++++++++++--------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/bidi-api-updates.patch b/bidi-api-updates.patch index a71513bf..a2972569 100644 --- a/bidi-api-updates.patch +++ b/bidi-api-updates.patch @@ -19,7 +19,7 @@ index 8fa25cc09..c17d0fe82 100644 ], ) diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index c7229d4..c36fb4c 100644 +index c7229d4e9..c56e7375e 100644 --- a/google/storage/v2/storage.proto +++ b/google/storage/v2/storage.proto @@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; @@ -360,7 +360,17 @@ index c7229d4..c36fb4c 100644 } // Required. The offset from the beginning of the object at which the data -@@ -1035,6 +1331,11 @@ message BidiWriteObjectResponse { +@@ -990,7 +1286,8 @@ message BidiWriteObjectRequest { + + // Checksums for the complete object. If the checksums computed by the service + // don't match the specified checksums the call will fail. May only be +- // provided in last request (with finish_write set). ++ // provided in the first request or the ++ // last request (with finish_write set). + ObjectChecksums object_checksums = 6; + + // For each BidiWriteObjectRequest where state_lookup is `true` or the client +@@ -1035,6 +1332,11 @@ message BidiWriteObjectResponse { // the upload has finalized. Object resource = 2; } @@ -372,3 +382,14 @@ index c7229d4..c36fb4c 100644 } // Request message for ListObjects. +@@ -2055,6 +2357,10 @@ message Object { + google.protobuf.Timestamp delete_time = 12 + [(google.api.field_behavior) = OUTPUT_ONLY]; + ++ // Output only. The time when the object was finalized. ++ google.protobuf.Timestamp finalize_time = 36 ++ [(google.api.field_behavior) = OUTPUT_ONLY]; ++ + // Content-Type of the object data, matching + // [https://tools.ietf.org/html/rfc7231#section-3.1.1.5][RFC 7231 §3.1.1.5]. + // If an object is stored without a Content-Type, it is served as diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index 57a33868..1039d29a 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -50,7 +50,7 @@ from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x91\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x36\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x02\x18\x01H\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xb5\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendable\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\x81\x03\n\x10\x41ppendObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\xdf\n\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xa8\x1d\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x91\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x36\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x02\x18\x01H\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xb5\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendable\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\x81\x03\n\x10\x41ppendObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\x97\x0b\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x36\n\rfinalize_time\x18$ \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xa8\x1d\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -232,6 +232,8 @@ _globals['_OBJECT'].fields_by_name['size']._serialized_options = b'\340A\003' _globals['_OBJECT'].fields_by_name['delete_time']._loaded_options = None _globals['_OBJECT'].fields_by_name['delete_time']._serialized_options = b'\340A\003' + _globals['_OBJECT'].fields_by_name['finalize_time']._loaded_options = None + _globals['_OBJECT'].fields_by_name['finalize_time']._serialized_options = b'\340A\003' _globals['_OBJECT'].fields_by_name['create_time']._loaded_options = None _globals['_OBJECT'].fields_by_name['create_time']._serialized_options = b'\340A\003' _globals['_OBJECT'].fields_by_name['component_count']._loaded_options = None @@ -433,19 +435,19 @@ _globals['_CUSTOMERENCRYPTION']._serialized_start=17098 _globals['_CUSTOMERENCRYPTION']._serialized_end=17174 _globals['_OBJECT']._serialized_start=17177 - _globals['_OBJECT']._serialized_end=18552 - _globals['_OBJECT_METADATAENTRY']._serialized_start=18424 - _globals['_OBJECT_METADATAENTRY']._serialized_end=18471 - _globals['_OBJECTACCESSCONTROL']._serialized_start=18555 - _globals['_OBJECTACCESSCONTROL']._serialized_end=18761 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=18763 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=18871 - _globals['_PROJECTTEAM']._serialized_start=18873 - _globals['_PROJECTTEAM']._serialized_end=18924 - _globals['_OWNER']._serialized_start=18926 - _globals['_OWNER']._serialized_end=18968 - _globals['_CONTENTRANGE']._serialized_start=18970 - _globals['_CONTENTRANGE']._serialized_end=19037 - _globals['_STORAGE']._serialized_start=19040 - _globals['_STORAGE']._serialized_end=22792 + _globals['_OBJECT']._serialized_end=18608 + _globals['_OBJECT_METADATAENTRY']._serialized_start=18480 + _globals['_OBJECT_METADATAENTRY']._serialized_end=18527 + _globals['_OBJECTACCESSCONTROL']._serialized_start=18611 + _globals['_OBJECTACCESSCONTROL']._serialized_end=18817 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=18819 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=18927 + _globals['_PROJECTTEAM']._serialized_start=18929 + _globals['_PROJECTTEAM']._serialized_end=18980 + _globals['_OWNER']._serialized_start=18982 + _globals['_OWNER']._serialized_end=19024 + _globals['_CONTENTRANGE']._serialized_start=19026 + _globals['_CONTENTRANGE']._serialized_end=19093 + _globals['_STORAGE']._serialized_start=19096 + _globals['_STORAGE']._serialized_end=22848 # @@protoc_insertion_point(module_scope) From 32029d2757707c8ec33506377ed5fd0847df1b3c Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Tue, 12 Nov 2024 17:40:24 -0500 Subject: [PATCH 26/39] feat(append): Appendable object creation. (#34) Insert appendable objects into metadata immediately upon creation. This is not quite full appendable object semantics, but it's sufficient to test preconditions. --- gcs/object.py | 6 ++- gcs/upload.py | 114 +++++++++++++++++++++++++++++++++------- testbench/common.py | 1 + testbench/database.py | 26 ++++++--- testbench/proto2rest.py | 1 + tests/test_object.py | 1 + 6 files changed, 123 insertions(+), 26 deletions(-) diff --git a/gcs/object.py b/gcs/object.py index de0ff152..888da989 100644 --- a/gcs/object.py +++ b/gcs/object.py @@ -87,7 +87,9 @@ def _metadata_etag(cls, metadata): return hashlib.md5(("%d" % metadata.metageneration).encode("utf-8")).hexdigest() @classmethod - def init(cls, request, metadata, media, bucket, is_destination, context): + def init( + cls, request, metadata, media, bucket, is_destination, context, finalize=True + ): instruction = testbench.common.extract_instruction(request, context) if instruction == "inject-upload-data-error": media = testbench.common.corrupt_media(media) @@ -111,6 +113,8 @@ def init(cls, request, metadata, media, bucket, is_destination, context): metadata.checksums.crc32c = actual_crc32c metadata.create_time.FromDatetime(timestamp) metadata.update_time.FromDatetime(timestamp) + if finalize: + metadata.finalize_time.FromDatetime(timestamp) if bucket.HasField("retention_policy"): retention_expiration_time = timestamp + datetime.timedelta( seconds=bucket.retention_policy.retention_duration.seconds diff --git a/gcs/upload.py b/gcs/upload.py index a9411fc4..942b8816 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -14,6 +14,7 @@ """Helper class to hold data during an upload.""" +import datetime import hashlib import itertools import json @@ -287,6 +288,48 @@ def init_write_object_grpc(cls, db, request_iterator, context): upload.metadata.metadata["x_emulator_no_md5"] = "true" return upload, is_resumable + @classmethod + def _insert_empty_appendable_object(cls, db, upload, spec, context): + # Construct the appendable object unfinalized in metadata. The upload + # will reflect the insertion-time generation. + blob, _ = gcs.object.Object.init( + upload.request, + upload.metadata, + upload.media, + upload.bucket, + False, + context, + finalize=False, + ) + + def insert_if_latest_is_unfinalized(latest_blob, live_generation): + if latest_blob is not None and latest_blob.metadata.HasField( + "finalize_time" + ): + # The live generation exists but is unfinalized, return an + # error. This is slightly different behavior from the real + # implementation, but it is sufficient for testing. + context.abort( + grpc.StatusCode.FAILED_PRECONDITION, + "Attempting to overwrite an unfinalized object", + ) + db.insert_object( + upload.bucket.name, + blob, + context=context, + preconditions=upload.preconditions, + ) + return blob + + return db.do_update_object( + upload.bucket.name, + blob.metadata.name, + update_fn=insert_if_latest_is_unfinalized, + context=context, + preconditions=upload.preconditions, + require_live_current_generation=False, + ) + @classmethod def process_bidi_write_object_grpc(cls, db, request_iterator, context): """Process a BidiWriteObject streaming RPC, and yield a stream of responses.""" @@ -322,7 +365,10 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): ) is_appendable = True appendable_metadata_in_first_response = True - upload.metadata.generation = gcs.object.make_generation() + blob = cls._insert_empty_appendable_object( + db, upload, first_msg.write_object_spec, context + ) + upload.blob = blob db.insert_upload(upload) elif write_type == "append_object_spec": is_appendable = True @@ -330,6 +376,21 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): first_msg.append_object_spec.write_handle.handle.decode("utf-8"), context, ) + preconditions = testbench.common.make_grpc_preconditions( + first_msg.append_object_spec + ) + blob = db.get_object( + first_msg.append_object_spec.bucket, + first_msg.append_object_spec.object, + context=context, + generation=first_msg.append_object_spec.generation, + preconditions=preconditions, + ) + if blob.metadata.HasField("finalize_time"): + context.abort( + grpc.StatusCode.FAILED_PRECONDITION, + "Attempting to append to already-finalized object", + ) else: testbench.error.invalid("Upload missing a first_message field", context) @@ -488,24 +549,39 @@ def response(msg): # Create a new object when the write is completed. if upload.complete: - generation = upload.metadata.generation - blob, _ = gcs.object.Object.init( - upload.request, - upload.metadata, - upload.media, - upload.bucket, - False, - context, - ) - if generation: - blob.metadata.generation = generation - upload.blob = blob - db.insert_object( - upload.bucket.name, - blob, - context=context, - preconditions=upload.preconditions, - ) + if upload.metadata.generation: + + def finalize_blob(blob, unused_generation): + blob.media = upload.media + blob.metadata.finalize_time.FromDatetime( + datetime.datetime.now(datetime.timezone.utc) + ) + blob.metadata.size = len(upload.media) + return blob + + blob = db.do_update_object( + upload.bucket.name, + upload.metadata.name, + update_fn=finalize_blob, + context=context, + generation=upload.metadata.generation, + ) + else: + blob, _ = gcs.object.Object.init( + upload.request, + upload.metadata, + upload.media, + upload.bucket, + False, + context, + ) + upload.blob = blob + db.insert_object( + upload.bucket.name, + blob, + context=context, + preconditions=upload.preconditions, + ) yield response(storage_pb2.BidiWriteObjectResponse(resource=blob.metadata)) elif not is_resumable and not is_appendable: testbench.error.missing("finish_write in request", context) diff --git a/testbench/common.py b/testbench/common.py index 81cabad7..248cbe23 100644 --- a/testbench/common.py +++ b/testbench/common.py @@ -1220,6 +1220,7 @@ def preprocess_object_metadata(metadata): "kind": lambda x: (None, None), "id": lambda x: (None, None), "timeCreated": lambda x: ("createTime", x), + "timeFinalized": lambda x: ("finalizeTime", x), "updated": lambda x: ("updateTime", x), "kmsKeyName": lambda x: ("kmsKey", x), "retentionExpirationTime": lambda x: ("retentionExpireTime", x), diff --git a/testbench/database.py b/testbench/database.py index 42d237d4..d768298f 100644 --- a/testbench/database.py +++ b/testbench/database.py @@ -331,7 +331,13 @@ def list_object(self, request, bucket_name, context): return items, sorted(list(prefixes)) def __get_object( - self, bucket_name, object_name, context=None, generation=None, preconditions=[] + self, + bucket_name, + object_name, + context=None, + generation=None, + preconditions=[], + require_live_current_generation=True, ): bucket_key = self.__bucket_key(bucket_name, context) if bucket_key not in self._live_generations: @@ -342,10 +348,12 @@ def __get_object( if generation is None or int(generation) == 0: # We are looking for the latest "live" version, but there is none. if live_generation is None: - return testbench.error.notfound( - "Live version of object %s/%s" % (bucket_name, object_name), - context, - ) + if require_live_current_generation: + return testbench.error.notfound( + "Live version of object %s/%s" % (bucket_name, object_name), + context, + ) + return None, None lookup_generation = int(live_generation) else: lookup_generation = int(generation) @@ -452,10 +460,16 @@ def do_update_object( context=None, generation=None, preconditions=[], + require_live_current_generation=True, ) -> T: with self._resources_lock: blob, live_generation = self.__get_object( - bucket_name, object_name, context, generation, preconditions + bucket_name, + object_name, + context, + generation, + preconditions, + require_live_current_generation=require_live_current_generation, ) return update_fn(blob, live_generation) diff --git a/testbench/proto2rest.py b/testbench/proto2rest.py index 5c8b9ccd..0c1a7f71 100644 --- a/testbench/proto2rest.py +++ b/testbench/proto2rest.py @@ -246,6 +246,7 @@ def __postprocess_object_rest(metadata): { "bucket": lambda x: ("bucket", bucket_id), "createTime": lambda x: ("timeCreated", x), + "finalizeTime": lambda x: ("timeFinalized", x), "updateTime": lambda x: ("updated", x), "kmsKey": lambda x: ("kmsKeyName", x), "retentionExpireTime": lambda x: ("retentionExpirationTime", x), diff --git a/tests/test_object.py b/tests/test_object.py index 8a345678..48300e5c 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -276,6 +276,7 @@ def test_init_xml_crc32c(self): "owner", "timeCreated", "timeDeleted", + "timeFinalized", "timeStorageClassUpdated", "updated", ] From 3041f73c75678447859e1313e4ccba3edd442fcd Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 13 Nov 2024 16:14:12 -0500 Subject: [PATCH 27/39] fix: Correct finalize condition. (#35) Uploads sometimes have nonzero metadata, e.g. when a test upload specifies generation -1. We really wanted to finalize appendable uploads, so fix the condition to be explicit. --- gcs/upload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcs/upload.py b/gcs/upload.py index 942b8816..025b8345 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -549,7 +549,7 @@ def response(msg): # Create a new object when the write is completed. if upload.complete: - if upload.metadata.generation: + if is_appendable: def finalize_blob(blob, unused_generation): blob.media = upload.media From 6027b39fee945fc24d963c2065ba2f0fd136ab5d Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 13 Nov 2024 16:14:54 -0500 Subject: [PATCH 28/39] feat(append): Add tests for finalizing appends. (#36) This surfaced a bug when checking that the live version is finalized before allowing an overwrite: I had incorrectly applied De Morgan's Law. --- gcs/upload.py | 2 +- tests/test_grpc_server.py | 144 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/gcs/upload.py b/gcs/upload.py index 025b8345..123cbe46 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -303,7 +303,7 @@ def _insert_empty_appendable_object(cls, db, upload, spec, context): ) def insert_if_latest_is_unfinalized(latest_blob, live_generation): - if latest_blob is not None and latest_blob.metadata.HasField( + if latest_blob is not None and not latest_blob.metadata.HasField( "finalize_time" ): # The live generation exists but is unfinalized, return an diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index f8306649..4fc052c3 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -1971,6 +1971,150 @@ def test_bidi_write_object_appendable(self): self.assertEqual(blob.name, "object-name") self.assertEqual(blob.bucket, "projects/_/buckets/rapid-bucket") + def test_bidi_write_object_appendable_already_finalized(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + + # Only the RAPID storage class supports appendable objects at this time. + self.grpc.CreateBucket( + storage_pb2.CreateBucketRequest( + parent="projects/test-project", + bucket_id="rapid-bucket", + bucket=storage_pb2.Bucket( + storage_class="RAPID", + ), + ), + context, + ) + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/rapid-bucket" + ), + appendable=True, + ), + finish_write=True, + ) + streamer = self.grpc.BidiWriteObject([r1], context=context) + responses = list(streamer) + self.assertEqual(len(responses), 1) + self.assertTrue(responses[0].resource.HasField("finalize_time")) + self.assertNotEqual(0, responses[0].resource.generation) + + r2 = storage_pb2.BidiWriteObjectRequest( + append_object_spec=storage_pb2.AppendObjectSpec( + bucket="projects/_/buckets/rapid-bucket", + object="object-name", + generation=responses[0].resource.generation, + write_handle=responses[0].write_handle, + ), + ) + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiWriteObject([r2], context=context) + responses = list(streamer) + context.abort.assert_called_once_with( + grpc.StatusCode.FAILED_PRECONDITION, + "Attempting to append to already-finalized object", + ) + + def test_bidi_write_object_appendable_live_generation_unfinalized(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + + # Only the RAPID storage class supports appendable objects at this time. + self.grpc.CreateBucket( + storage_pb2.CreateBucketRequest( + parent="projects/test-project", + bucket_id="rapid-bucket", + bucket=storage_pb2.Bucket( + storage_class="RAPID", + ), + ), + context, + ) + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/rapid-bucket" + ), + appendable=True, + ), + state_lookup=True, + ) + streamer = self.grpc.BidiWriteObject([r1], context=context) + responses = list(streamer) + self.assertEqual(len(responses), 1) + self.assertFalse(responses[0].resource.HasField("finalize_time")) + self.assertNotEqual(0, responses[0].resource.generation) + + r2 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/rapid-bucket" + ), + appendable=True, + ), + state_lookup=True, + ) + + with self.assertRaises(grpc.RpcError): + streamer = self.grpc.BidiWriteObject([r2], context=context) + responses = list(streamer) + context.abort.assert_called_once_with( + grpc.StatusCode.FAILED_PRECONDITION, + "Attempting to overwrite an unfinalized object", + ) + + def test_bidi_write_object_appendable_live_generation_finalized(self): + # The code depends on `context.abort()` raising an exception. + context = self.mock_context() + context.abort.side_effect = grpc.RpcError() + + # Only the RAPID storage class supports appendable objects at this time. + self.grpc.CreateBucket( + storage_pb2.CreateBucketRequest( + parent="projects/test-project", + bucket_id="rapid-bucket", + bucket=storage_pb2.Bucket( + storage_class="RAPID", + ), + ), + context, + ) + r1 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/rapid-bucket" + ), + appendable=True, + ), + finish_write=True, + ) + streamer = self.grpc.BidiWriteObject([r1], context=context) + responses = list(streamer) + self.assertEqual(len(responses), 1) + self.assertTrue(responses[0].resource.HasField("finalize_time")) + self.assertNotEqual(0, responses[0].resource.generation) + + r2 = storage_pb2.BidiWriteObjectRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource=storage_pb2.Object( + name="object-name", bucket="projects/_/buckets/rapid-bucket" + ), + appendable=True, + ), + state_lookup=True, + ) + streamer = self.grpc.BidiWriteObject([r2], context=context) + responses2 = list(streamer) + self.assertEqual(len(responses2), 1) + self.assertFalse(responses2[0].resource.HasField("finalize_time")) + self.assertNotEqual( + responses[0].resource.generation, responses2[0].resource.generation + ) + def test_bidi_write_object_no_requests(self): # The code depends on `context.abort()` raising an exception. context = self.mock_context() From d6fe248654804cf8b8ff8f3f330355d250464a52 Mon Sep 17 00:00:00 2001 From: cojenco Date: Thu, 21 Nov 2024 15:10:55 -0800 Subject: [PATCH 29/39] fix: signal terminate in BidiReadObject (#37) --- testbench/grpc_server.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 3d0dda7a..32d43e70 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -23,7 +23,7 @@ from collections.abc import Iterable from concurrent import futures from queue import Queue -from threading import Thread +from threading import Thread, Timer import crc32c import google.protobuf.any_pb2 as any_pb2 @@ -609,6 +609,12 @@ def gather_requests(initial_ranges): target=gather_requests, args=(first_message.read_ranges,) ) + def terminate_w_timer(): + nonlocal responses + responses.put(("terminate", None)) + + timer_thread = Timer(10, terminate_w_timer) + poll_queue = True # Check retry test broken-stream instructions. @@ -628,6 +634,7 @@ def gather_requests(initial_ranges): ) try: gather_thread.start() + timer_thread.start() while poll_queue: action, arg = responses.get() @@ -673,7 +680,7 @@ def gather_requests(initial_ranges): action, _ = responses.get() if action == "terminate": poll_queue = False - gather_thread.join() + gather_thread.join(timeout=10) def _to_read_range_error_proto(self, range, status_code): return storage_pb2.ReadRangeError( From e96974db6f64d2810d749deb0d8d8192ad544a93 Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 22 Nov 2024 15:16:12 -0800 Subject: [PATCH 30/39] docs: how to merge from public upstream (#40) * docs: how to merge from public upstream * update contents --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index ccfe5ca9..5fe10070 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ is expected to be used by Storage library maintainers. - [Run the testbench](#run-the-testbench) - [Start the gRPC server](#start-the-gRPC-server) - [Check that the testbench is running](#check-that-the-testbench-is-running) - - [Updating Proto Files](#updating-proto-files) - [Force Failures](#force-failures) - [return-broken-stream](#return-broken-stream) - [return-corrupted-data](#return-corrupted-data) @@ -35,6 +34,8 @@ is expected to be used by Storage library maintainers. - [Delete a Retry Test resource](#delete-a-retry-test-resource) - [Causing a failure using x-retry-test-id header](#causing-a-failure-using-x-retry-test-id-header) - [Forced Failures Supported](#forced-failures-supported) + - [Merging from Upstream](#merging-from-upstream) + - [Updating Proto Files](#updating-proto-files) - [Releasing the testbench](#releasing-the-testbench) ## Issue Policy @@ -120,24 +121,6 @@ The response you get should be: `OK` Now you can use the testbench (while it's running) with the client libraries. -## Updating Proto Files - -From time to time you may need to update the files generated by protobuf and -gRPC. To do so, clone the [protos](https://github.com/googleapis/googleapis) and -run the grpc_tools generator: - -```shell -cd $HOME/storage-testbench -pip install --no-deps grpcio-tools -./update-protos.sh $PWD/.googleapis -``` - -Then commit the files generated in `google/**`: - -```shell -git commit -m"chore: update protos" google -``` - ## Force Failures You can force the following failures by using the `x-goog-emulator-instructions` header. @@ -276,6 +259,78 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 | redirect-send-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. | redirect-send-handle-and-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. +## How-to Guide: maintaining the pre-launch branch(es) + +### Merging from Upstream + +Clone a repository (you may already have one) that has both the public and +`*-prelaunch` repos as remotes. We choose a configuration that makes it really +hard to accidentally push prelaunch code to the public repo: + +```shell +git clone git@github.com:googleapis/storage-testbench.git +cd storage-testbench +git remote add prelaunch git@github.com:googleapis/storage-testbench-prelaunch.git +``` + +Update your clone to the latest versions: + +```shell +git fetch prelaunch +git fetch origin +``` + +Find out the latest commit from the public repo already present in the +`*-prelaunch` repo: + +```shell +A=$(git rev-parse prelaunch/upstream) +``` + +Find out the latest commit from the public repo main branch: + +```shell +B=$(git rev-parse origin/main) +``` + +Update the `upstream` branch on the `*-prelaunch` repository: + +```shell +git push prelaunch origin/main:upstream +``` + +You can use a separate workspace for the next steps: + +```shell +cd $HOME/ +git clone git@github.com:googleapis/storage-testbench-prelaunch.git +cd storage-testbench +git checkout pre-launch-acv2 +git checkout -b chore-merge-from-public-circa-$(date +%Y-%m-%d) +git cherry-pick ${A}..${B} +``` + +Send a PR and squash commit as usual. + + +## Updating Proto Files + +From time to time you may need to update the files generated by protobuf and +gRPC. To do so, clone the [protos](https://github.com/googleapis/googleapis) and +run the grpc_tools generator: + +```shell +cd $HOME/storage-testbench +pip install --no-deps grpcio-tools +./update-protos.sh $PWD/.googleapis +``` + +Then commit the files generated in `google/**`: + +```shell +git commit -m"chore: update protos" google +``` + ## Releasing the testbench The repository currently uses [Github Tags](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) From 9247a57bf9e6bfcd97ff97fee45f120c4811e919 Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 22 Nov 2024 15:16:21 -0800 Subject: [PATCH 31/39] feat: Support error code for single shot upload (#699) (#39) * support error for single shot upload * remove .idea files * lint fix * review comments * review comments * review comments * lint fix * lint fix * lint fix Co-authored-by: Tulsi Shah <46474643+Tulsishah@users.noreply.github.com> --- testbench/rest_server.py | 41 +++++++++---- tests/test_testbench_retry.py | 106 ++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 11 deletions(-) diff --git a/testbench/rest_server.py b/testbench/rest_server.py index 72a0ae88..5e58296f 100644 --- a/testbench/rest_server.py +++ b/testbench/rest_server.py @@ -979,17 +979,36 @@ def object_insert(bucket_name): blob, projection = gcs_type.object.Object.init_media(flask.request, bucket) elif upload_type == "multipart": blob, projection = gcs_type.object.Object.init_multipart(flask.request, bucket) - # Handle stall for full uploads. - testbench.common.extract_instruction(request, context=None) - ( - stall_time, - after_bytes, - test_id, - ) = testbench.common.get_stall_uploads_after_bytes(db, request) - if stall_time and len(blob.media) >= after_bytes: - if test_id: - db.dequeue_next_instruction(test_id, "storage.objects.insert") - time.sleep(stall_time) + + # Handle errors for single-shot uploads. + testbench.common.extract_instruction(request, context=None) + ( + error_code, + after_bytes, + test_id, + ) = testbench.common.get_retry_uploads_error_after_bytes(db, request) + + if error_code and len(blob.media) >= after_bytes: + if test_id: + db.dequeue_next_instruction(test_id, "storage.objects.insert") + testbench.error.generic( + "Fault injected during a single-shot upload", + rest_code=error_code, + grpc_code=None, + context=None, + ) + + # Handle stall for single-shot uploads. + testbench.common.extract_instruction(request, context=None) + ( + stall_time, + after_bytes, + test_id, + ) = testbench.common.get_stall_uploads_after_bytes(db, request) + if stall_time and len(blob.media) >= after_bytes: + if test_id: + db.dequeue_next_instruction(test_id, "storage.objects.insert") + time.sleep(stall_time) db.insert_object( bucket_name, diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index b629cb49..7c4f847b 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -883,6 +883,112 @@ def test_write_retry_test_stall_single_shot_while_upload_size_less_than_stall_si self.assertEqual(response.status_code, 200) self.assertLess(elapsed_time, 1) + def test_retry_test_return_error_after_bytes_for_single_shot_upload(self): + # Create a new bucket + response = self.client.post( + "/storage/v1/b", data=json.dumps({"name": "bucket-name"}) + ) + self.assertEqual(response.status_code, 200) + + # Setup a stall for reading back the object. + response = self.client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "return-503-after-250K", + ] + } + } + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + self.assertTrue( + response.headers.get("content-type").startswith("application/json") + ) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + test_id = create_rest.get("id") + + # Upload the 256KiB of data and trigger the stall. + data = self._create_block(UPLOAD_QUANTUM) + self.assertEqual(len(data), UPLOAD_QUANTUM) + + boundary, payload = format_multipart_upload({}, data) + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "stall"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + self.assertEqual(response.status_code, 503) + + # Upload the data again and check that stall not happen. + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "stall"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + self.assertEqual(response.status_code, 200) + + def test_write_retry_error_single_shot_while_upload_size_less_than_size( + self, + ): + # Create a new bucket + response = self.client.post( + "/storage/v1/b", data=json.dumps({"name": "bucket-name"}) + ) + self.assertEqual(response.status_code, 200) + + # Setup a error for reading back the object. + response = self.client.post( + "/retry_test", + data=json.dumps( + { + "instructions": { + "storage.objects.insert": [ + "return-503-after-250K", + ] + } + } + ), + content_type="application/json", + ) + self.assertEqual(response.status_code, 200) + self.assertTrue( + response.headers.get("content-type").startswith("application/json") + ) + + create_rest = json.loads(response.data) + self.assertIn("id", create_rest) + test_id = create_rest.get("id") + + # Upload the 200KiB of data and check error not happen. + data = self._create_block(200 * 1024) + self.assertEqual(len(data), 200 * 1024) + + boundary, payload = format_multipart_upload({}, data) + response = self.client.post( + "/upload/storage/v1/b/bucket-name/o", + query_string={"uploadType": "multipart", "name": "error"}, + content_type="multipart/related; boundary=" + boundary, + headers={ + "x-retry-test-id": test_id, + }, + data=payload, + ) + self.assertEqual(response.status_code, 200) + class TestTestbenchRetryGrpc(unittest.TestCase): def setUp(self): From 76cf6ec8319d7e04515f305acd4e93448feaee59 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 25 Nov 2024 22:35:29 -0500 Subject: [PATCH 32/39] chore: Timeout with cancellation in BidiReadObject (#42) We want to limit the total amount of time any one request can monopolize a thread on the gRPC server, so we have a 10 second timer to terminate the request. However, the existing code ends the stream with OK, which is misleading to clients. By switching to cancellation, we no longer need to set a timeout on the gather thread join (since it observes an error from next(request_iterator)) and we return a CANCELLED error which correctly indicates to client code that they probably wrote a bug. Now, tests with bugs that keep the stream open for more than 10 seconds look like: ``` === RUN TestRetryConformance/grpc-1-[return-reset-connection_return-reset-connection]-storage.objects.get-1 retry_conformance_test.go:696: want success, got rpc error: code = Canceled desc = CANCELLED ``` Tests pass when code correctly cleans up channels/RPCs. N.B. if we ever need longer than 10 second RPCs and we _don't_ want them to end in a CANCELLED error, we will have to revisit this. --- testbench/grpc_server.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 32d43e70..94c3507a 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -609,9 +609,12 @@ def gather_requests(initial_ranges): target=gather_requests, args=(first_message.read_ranges,) ) + # We force all BidiReadObject streams to cancel on the server side after + # 10 seconds. This is to bound the effect of thread exhaustion on the + # gRPC server, which can happen when clients don't clean up their + # streams. Such clients will instead see CANCELLED errors. def terminate_w_timer(): - nonlocal responses - responses.put(("terminate", None)) + context.cancel() timer_thread = Timer(10, terminate_w_timer) @@ -680,7 +683,7 @@ def terminate_w_timer(): action, _ = responses.get() if action == "terminate": poll_queue = False - gather_thread.join(timeout=10) + gather_thread.join() def _to_read_range_error_proto(self, range, status_code): return storage_pb2.ReadRangeError( From 3c77efe9d0339fe33b24ec17a1675e8b406990e6 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Wed, 27 Nov 2024 10:40:17 -0500 Subject: [PATCH 33/39] fix: Disable pipelining in BidiReadObject. (#43) The real implementation of BidiReadObject may pipeline requests, concurrently serving reads issued in separate messages. Unfortunately, as best we can tell, gRPC in synchronous Python makes it hard to abort the next(request_iterator) call when there's an error with a concurrent read. So we go back to a previous iteration of this code, which handled messages in batches. We no longer need a response queue or a thread pool. --- testbench/grpc_server.py | 132 ++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 78 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 94c3507a..3e810ecd 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -15,6 +15,7 @@ import base64 import datetime import functools +import itertools import json import re import sys @@ -22,8 +23,7 @@ import uuid from collections.abc import Iterable from concurrent import futures -from queue import Queue -from threading import Thread, Timer +from threading import Timer import crc32c import google.protobuf.any_pb2 as any_pb2 @@ -553,13 +553,9 @@ def response(resp): # always emit a response to the first request. yield response(storage_pb2.BidiReadObjectResponse()) - # Start handling async requests. maxsize=1 means that concurrent - # requests have a chance of blocking and therefore interleaving with one - # another. - responses = Queue(maxsize=1) - + # In real life requests may be async. For convenience of implementation, + # we handle each request synchronously before reading the next request. def process_read_range(range): - nonlocal responses size = storage_pb2.ServiceConstants.Values.MAX_READ_CHUNK_BYTES # A read range corresponds to a unique read_id. # For the same read_id, it is guaranteed that responses are delivered in increasing offset order. @@ -572,7 +568,7 @@ def process_read_range(range): range, grpc.StatusCode.OUT_OF_RANGE ) grpc_status = rpc_status.to_status(status_msg) - responses.put(("abort_with_status", grpc_status)) + context.abort_with_status(grpc_status) return if range.read_limit > 0: @@ -589,26 +585,9 @@ def process_read_range(range): "read_limit": range.read_limit, "read_id": read_id, } - responses.put(("respond", (chunk, range_end, read_range))) + yield (chunk, range_end, read_range) start = end - def gather_requests(initial_ranges): - nonlocal responses - with futures.ThreadPoolExecutor() as readers: - try: - for range in initial_ranges: - readers.submit(process_read_range, range) - for request in request_iterator: - for range in request.read_ranges: - readers.submit(process_read_range, range) - except Exception as e: - responses.put(("raise", e)) - responses.put(("terminate", None)) - - gather_thread = Thread( - target=gather_requests, args=(first_message.read_ranges,) - ) - # We force all BidiReadObject streams to cancel on the server side after # 10 seconds. This is to bound the effect of thread exhaustion on the # gRPC server, which can happen when clients don't clean up their @@ -617,8 +596,7 @@ def terminate_w_timer(): context.cancel() timer_thread = Timer(10, terminate_w_timer) - - poll_queue = True + timer_thread.start() # Check retry test broken-stream instructions. test_id = testbench.common.get_retry_test_id_from_context(context) @@ -635,55 +613,53 @@ def terminate_w_timer(): returnable = ( broken_stream_after_bytes if broken_stream_after_bytes else sys.maxsize ) - try: - gather_thread.start() - timer_thread.start() - - while poll_queue: - action, arg = responses.get() - if action == "terminate": - poll_queue = False - elif action == "respond": - chunk, range_end, read_range = arg - count = len(chunk) - excess = count - returnable - if excess > 0: - chunk = chunk[:returnable] - range_end = False - read_range["read_limit"] -= excess - returnable -= count - yield response( - storage_pb2.BidiReadObjectResponse( - object_data_ranges=[ - storage_pb2.ObjectRangeData( - checksummed_data=storage_pb2.ChecksummedData( - content=chunk, - crc32c=crc32c.crc32c(chunk), - ), - read_range=read_range, - range_end=range_end, - ), - ], - ) - ) - if returnable <= 0: - self.db.dequeue_next_instruction(test_id, method) - context.abort( - grpc.StatusCode.UNAVAILABLE, - "Injected 'broken stream' fault", - ) - elif action == "abort_with_status": - context.abort_with_status(arg) - elif action == "raise": - raise arg - else: - raise RuntimeError(f"Unexpected action {action}") - finally: - while poll_queue: - action, _ = responses.get() - if action == "terminate": - poll_queue = False - gather_thread.join() + + # We don't want to have a thread blocking on request_iterator, so we + # have to handle results in batches rather than concurrently. This + # generator yields the read results. + # + # We force clients to handle out-of-order responses by selecting one + # response from each range at a time. + def responses_for_range_batch(range_batch): + iters = map(process_read_range, range_batch) + for responses in itertools.zip_longest(*iters): + for response in responses: + if response is not None: + yield response + + def read_results(): + yield from responses_for_range_batch(first_message.read_ranges) + for request in request_iterator: + yield from responses_for_range_batch(request.read_ranges) + + for chunk, range_end, read_range in read_results(): + count = len(chunk) + excess = count - returnable + if excess > 0: + chunk = chunk[:returnable] + range_end = False + read_range["read_limit"] -= excess + returnable -= count + yield response( + storage_pb2.BidiReadObjectResponse( + object_data_ranges=[ + storage_pb2.ObjectRangeData( + checksummed_data=storage_pb2.ChecksummedData( + content=chunk, + crc32c=crc32c.crc32c(chunk), + ), + read_range=read_range, + range_end=range_end, + ), + ], + ) + ) + if returnable <= 0: + self.db.dequeue_next_instruction(test_id, method) + context.abort( + grpc.StatusCode.UNAVAILABLE, + "Injected 'broken stream' fault", + ) def _to_read_range_error_proto(self, range, status_code): return storage_pb2.ReadRangeError( From 1dec604f9b7b0943f90c48f65eb7890cb97459a7 Mon Sep 17 00:00:00 2001 From: Chris Carlon Date: Mon, 6 Jan 2025 13:54:16 -0500 Subject: [PATCH 34/39] chore: Update bidi proto patch. (#44) Deprecated fields have been removed from the proto we will upstream, and I renamed read_limit in ReadRange to read_length (since it's a length!). Verified with testbench unit tests and Go prelaunch SDK emulator tests. --- bidi-api-updates.patch | 293 +++++++++++++++++++------- google/storage/v2/storage_pb2.py | 276 ++++++++++++------------ google/storage/v2/storage_pb2_grpc.py | 142 +++++++++++-- testbench/grpc_server.py | 11 +- tests/test_grpc_server.py | 36 ++-- tests/test_testbench_retry.py | 8 +- 6 files changed, 503 insertions(+), 263 deletions(-) diff --git a/bidi-api-updates.patch b/bidi-api-updates.patch index a2972569..3fed10cb 100644 --- a/bidi-api-updates.patch +++ b/bidi-api-updates.patch @@ -19,7 +19,7 @@ index 8fa25cc09..c17d0fe82 100644 ], ) diff --git a/google/storage/v2/storage.proto b/google/storage/v2/storage.proto -index c7229d4e9..c56e7375e 100644 +index 2671acbc4..420130f15 100644 --- a/google/storage/v2/storage.proto +++ b/google/storage/v2/storage.proto @@ -26,6 +26,7 @@ import "google/protobuf/duration.proto"; @@ -30,7 +30,70 @@ index c7229d4e9..c56e7375e 100644 import "google/type/date.proto"; option go_package = "cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb"; -@@ -235,6 +236,16 @@ service Storage { +@@ -176,12 +177,26 @@ service Storage { + }; + } + +- // Deletes an object and its metadata. ++ // Deletes an object and its metadata. Deletions are permanent if versioning ++ // is not enabled for the bucket, or if the generation parameter is used, or ++ // if [soft delete](https://cloud.google.com/storage/docs/soft-delete) is not ++ // enabled for the bucket. ++ // When this API is used to delete an object from a bucket that has soft ++ // delete policy enabled, the object becomes soft deleted, and the ++ // `softDeleteTime` and `hardDeleteTime` properties are set on the object. ++ // This API cannot be used to permanently delete soft-deleted objects. ++ // Soft-deleted objects are permanently deleted according to their ++ // `hardDeleteTime`. + // +- // Deletions are normally permanent when versioning is disabled or whenever +- // the generation parameter is used. However, if soft delete is enabled for +- // the bucket, deleted objects can be restored using RestoreObject until the +- // soft delete retention period has passed. ++ // You can use the [`RestoreObject`][google.storage.v2.Storage.RestoreObject] ++ // API to restore soft-deleted objects until the soft delete retention period ++ // has passed. ++ // ++ // **IAM Permissions**: ++ // ++ // Requires `storage.objects.delete` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on ++ // the bucket. + rpc DeleteObject(DeleteObjectRequest) returns (google.protobuf.Empty) { + option (google.api.routing) = { + routing_parameters { field: "bucket" path_template: "{bucket=**}" } +@@ -217,7 +232,14 @@ service Storage { + option (google.api.method_signature) = "upload_id"; + } + +- // Retrieves an object's metadata. ++ // Retrieves object metadata. ++ // ++ // **IAM Permissions**: ++ // ++ // Requires `storage.objects.get` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on ++ // the bucket. To return object ACLs, the authenticated user must also have ++ // the `storage.objects.getIamPolicy` permission. + rpc GetObject(GetObjectRequest) returns (Object) { + option (google.api.routing) = { + routing_parameters { field: "bucket" path_template: "{bucket=**}" } +@@ -226,7 +248,13 @@ service Storage { + option (google.api.method_signature) = "bucket,object,generation"; + } + +- // Reads an object's data. ++ // Retrieves object data. ++ // ++ // **IAM Permissions**: ++ // ++ // Requires `storage.objects.get` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on ++ // the bucket. + rpc ReadObject(ReadObjectRequest) returns (stream ReadObjectResponse) { + option (google.api.routing) = { + routing_parameters { field: "bucket" path_template: "{bucket=**}" } +@@ -235,6 +263,16 @@ service Storage { option (google.api.method_signature) = "bucket,object,generation"; } @@ -47,7 +110,96 @@ index c7229d4e9..c56e7375e 100644 // Updates an object's metadata. // Equivalent to JSON API's storage.objects.patch. rpc UpdateObject(UpdateObjectRequest) returns (Object) { -@@ -847,6 +858,253 @@ message ReadObjectResponse { +@@ -297,12 +335,18 @@ service Storage { + // whether the service views the object as complete. + // + // Attempting to resume an already finalized object will result in an OK +- // status, with a WriteObjectResponse containing the finalized object's ++ // status, with a `WriteObjectResponse` containing the finalized object's + // metadata. + // + // Alternatively, the BidiWriteObject operation may be used to write an + // object with controls over flushing and the ability to fetch the ability to + // determine the current persisted size. ++ // ++ // **IAM Permissions**: ++ // ++ // Requires `storage.objects.create` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on ++ // the bucket. + rpc WriteObject(stream WriteObjectRequest) returns (WriteObjectResponse) {} + + // Stores a new object and metadata. +@@ -324,6 +368,13 @@ service Storage { + returns (stream BidiWriteObjectResponse) {} + + // Retrieves a list of objects matching the criteria. ++ // ++ // **IAM Permissions**: ++ // ++ // The authenticated user requires `storage.objects.list` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) ++ // to use this method. To return object ACLs, the authenticated user must also ++ // have the `storage.objects.getIamPolicy` permission. + rpc ListObjects(ListObjectsRequest) returns (ListObjectsResponse) { + option (google.api.routing) = { + routing_parameters { field: "parent" path_template: "{bucket=**}" } +@@ -343,9 +394,19 @@ service Storage { + }; + } + +- // Starts a resumable write. How long the write operation remains valid, and +- // what happens when the write operation becomes invalid, are +- // service-dependent. ++ // Starts a resumable write operation. This ++ // method is part of the [Resumable ++ // upload](https://cloud.google.com/storage/docs/resumable-uploads) feature. ++ // This allows you to upload large objects in multiple chunks, which is more ++ // resilient to network interruptions than a single upload. The validity ++ // duration of the write operation, and the consequences of it becoming ++ // invalid, are service-dependent. ++ // ++ // **IAM Permissions**: ++ // ++ // Requires `storage.objects.create` ++ // [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on ++ // the bucket. + rpc StartResumableWrite(StartResumableWriteRequest) + returns (StartResumableWriteResponse) { + option (google.api.routing) = { +@@ -356,18 +417,22 @@ service Storage { + }; + } + +- // Determines the `persisted_size` for an object that is being written, which +- // can then be used as the `write_offset` for the next `Write()` call. ++ // Determines the `persisted_size` of an object that is being written. This ++ // method is part of the [resumable ++ // upload](https://cloud.google.com/storage/docs/resumable-uploads) feature. ++ // The returned value is the size of the object that has been persisted so ++ // far. The value can be used as the `write_offset` for the next `Write()` ++ // call. + // +- // If the object does not exist (i.e., the object has been deleted, or the +- // first `Write()` has not yet reached the service), this method returns the ++ // If the object does not exist, meaning if it was deleted, or the ++ // first `Write()` has not yet reached the service, this method returns the + // error `NOT_FOUND`. + // +- // The client **may** call `QueryWriteStatus()` at any time to determine how +- // much data has been processed for this object. This is useful if the +- // client is buffering data and needs to know which data can be safely +- // evicted. For any sequence of `QueryWriteStatus()` calls for a given +- // object name, the sequence of returned `persisted_size` values will be ++ // This method is useful for clients that buffer data and need to know which ++ // data can be safely evicted. The client can call `QueryWriteStatus()` at any ++ // time to determine how much data has been logged for this object. ++ // For any sequence of `QueryWriteStatus()` calls for a given ++ // object name, the sequence of returned `persisted_size` values are + // non-decreasing. + rpc QueryWriteStatus(QueryWriteStatusRequest) + returns (QueryWriteStatusResponse) { +@@ -856,6 +921,205 @@ message ReadObjectResponse { Object metadata = 4; } @@ -110,14 +262,6 @@ index c7229d4e9..c56e7375e 100644 + +// Request message for BidiReadObject. +message BidiReadObjectRequest { -+ // The first message of each stream must set this field. The stream returns an -+ // error if any subsequent message sets this field, or if the first message -+ // does not set the field. -+ oneof first_message { -+ // Describes the object to read -+ BidiReadObjectSpec read_spec = 6 [deprecated = true]; -+ } -+ + // The first message of each stream should set this field. If this is not + // the first message, an error will be returned. Describes the object to read. + BidiReadObjectSpec read_object_spec = 1; @@ -129,47 +273,10 @@ index c7229d4e9..c56e7375e 100644 + // include ObjectRangeData. For full object downloads, the offset and size can + // be set to 0. + repeated ReadRange read_ranges = 8; -+ -+ // The offset for the first byte to return in the read, relative to the start -+ // of the object. -+ // -+ // A negative `read_offset` value will be interpreted as the number of bytes -+ // back from the end of the object to be returned. For example, if an object's -+ // length is 15 bytes, a ReadObjectRequest with `read_offset` = -5 and -+ // `read_limit` = 3 would return bytes 10 through 12 of the object. Requesting -+ // a negative offset with magnitude larger than the size of the object will -+ // return the entire object. -+ int64 read_offset = 4 [deprecated = true]; -+ -+ // The maximum number of `data` bytes the server is allowed to return in the -+ // sum of all `Object` messages. A `read_limit` of zero indicates that there -+ // is no limit, and a negative `read_limit` will cause an error. -+ // -+ // If the stream returns fewer bytes than allowed by the `read_limit` and no -+ // error occurred, the stream includes all data from the `read_offset` to the -+ // end of the resource. -+ int64 read_limit = 5 [deprecated = true]; +} + +// Response message for BidiReadObject. +message BidiReadObjectResponse { -+ // A portion of the data for the object. The service **may** leave `data` -+ // empty for any given `ReadResponse`. This enables the service to inform the -+ // client that the request is still live while it is running an operation to -+ // generate more data. -+ ChecksummedData checksummed_data = 1 [deprecated = true]; -+ -+ // The checksums of the complete object regardless of data range. If the -+ // object is downloaded in full, the client should compute one of these -+ // checksums over the downloaded object and compare it against the value -+ // provided here. -+ ObjectChecksums object_checksums = 2 [deprecated = true]; -+ -+ // If read_offset and or read_limit was specified on the -+ // ReadObjectRequest, ContentRange will be populated on the first -+ // ReadObjectResponse message following the request. -+ ContentRange content_range = 3 [deprecated = true]; -+ + // A portion of the object's data. The service **may** leave data + // empty for any given ReadResponse. This enables the service to inform the + // client that the request is still live while it is running an operation to @@ -188,9 +295,6 @@ index c7229d4e9..c56e7375e 100644 + // every response. It allows the client to more efficiently open subsequent + // bidirectional streams to the same object. + BidiReadHandle read_handle = 7; -+ -+ // If set, indicates there are no more bytes to read for the given range. -+ bool end_of_range = 5 [deprecated = true]; +} + +// Error proto containing details for a redirected read. This error is only @@ -244,19 +348,19 @@ index c7229d4e9..c56e7375e 100644 + // A negative read_offset value will be interpreted as the number of bytes + // back from the end of the object to be returned. For example, if an object's + // length is 15 bytes, a ReadObjectRequest with read_offset = -5 and -+ // read_limit = 3 would return bytes 10 through 12 of the object. Requesting ++ // read_length = 3 would return bytes 10 through 12 of the object. Requesting + // a negative offset with magnitude larger than the size of the object will + // return the entire object. A read_offset larger than the size of the object + // will result in an OutOfRange error. + int64 read_offset = 1 [(google.api.field_behavior) = REQUIRED]; + + // Optional. The maximum number of data bytes the server is allowed to return -+ // across all response messages with the same read_id. A read_limit of zero -+ // indicates that there is no limit, and a negative read_limit will cause an -+ // error. If the stream returns fewer bytes than allowed by the read_limit -+ // and no error occurred, the stream includes all data from the read_offset -+ // to the resource end. -+ int64 read_limit = 2 [(google.api.field_behavior) = OPTIONAL]; ++ // across all response messages with the same read_id. A read_length of zero ++ // indicates to read until the resource end, and a negative read_length will ++ // cause an error. If the stream returns fewer bytes than allowed by the ++ // read_length and no error occurred, the stream includes all data from the ++ // read_offset to the resource end. ++ int64 read_length = 2 [(google.api.field_behavior) = OPTIONAL]; + + // Required. Read identifier provided by the client. When the client issues + // more than one outstanding ReadRange on the same stream, responses can be @@ -301,7 +405,7 @@ index c7229d4e9..c56e7375e 100644 // Describes an attempt to insert an object, possibly over multiple requests. message WriteObjectSpec { // Required. Destination object, including its name and its metadata. -@@ -884,6 +1142,10 @@ message WriteObjectSpec { +@@ -893,6 +1157,10 @@ message WriteObjectSpec { // you must start the upload over from scratch, this time sending the correct // number of bytes. optional int64 object_size = 8; @@ -312,7 +416,7 @@ index c7229d4e9..c56e7375e 100644 } // Request message for WriteObject. -@@ -953,6 +1215,37 @@ message WriteObjectResponse { +@@ -962,6 +1230,37 @@ message WriteObjectResponse { } } @@ -350,7 +454,7 @@ index c7229d4e9..c56e7375e 100644 // Request message for BidiWriteObject. message BidiWriteObjectRequest { // The first message of each stream should set one of the following. -@@ -964,6 +1257,9 @@ message BidiWriteObjectRequest { +@@ -973,6 +1272,9 @@ message BidiWriteObjectRequest { // For non-resumable uploads. Describes the overall upload, including the // destination bucket and object name, preconditions, etc. WriteObjectSpec write_object_spec = 2; @@ -360,17 +464,7 @@ index c7229d4e9..c56e7375e 100644 } // Required. The offset from the beginning of the object at which the data -@@ -990,7 +1286,8 @@ message BidiWriteObjectRequest { - - // Checksums for the complete object. If the checksums computed by the service - // don't match the specified checksums the call will fail. May only be -- // provided in last request (with finish_write set). -+ // provided in the first request or the -+ // last request (with finish_write set). - ObjectChecksums object_checksums = 6; - - // For each BidiWriteObjectRequest where state_lookup is `true` or the client -@@ -1035,6 +1332,11 @@ message BidiWriteObjectResponse { +@@ -1045,6 +1347,11 @@ message BidiWriteObjectResponse { // the upload has finalized. Object resource = 2; } @@ -382,14 +476,51 @@ index c7229d4e9..c56e7375e 100644 } // Request message for ListObjects. -@@ -2055,6 +2357,10 @@ message Object { - google.protobuf.Timestamp delete_time = 12 - [(google.api.field_behavior) = OUTPUT_ONLY]; +@@ -1390,25 +1697,28 @@ message MoveObjectRequest { + + // Request message StartResumableWrite. + message StartResumableWriteRequest { +- // Required. The destination bucket, object, and metadata, as well as any +- // preconditions. ++ // Required. Contains the information necessary to start a resumable write. + WriteObjectSpec write_object_spec = 1 + [(google.api.field_behavior) = REQUIRED]; + +- // A set of parameters common to Storage API requests concerning an object. ++ // A set of parameters common to Storage API requests related to an object. + CommonObjectRequestParams common_object_request_params = 3; + +- // The checksums of the complete object. This will be used to validate the +- // uploaded object. For each upload, object_checksums can be provided with +- // either StartResumableWriteRequest or the WriteObjectRequest with +- // finish_write set to `true`. ++ // The checksums of the complete object. This is used to validate the ++ // uploaded object. For each upload, `object_checksums` can be provided when ++ // initiating a resumable upload with`StartResumableWriteRequest` or when ++ // completing a write with `WriteObjectRequest` with ++ // `finish_write` set to `true`. + ObjectChecksums object_checksums = 5; + } + + // Response object for `StartResumableWrite`. + message StartResumableWriteResponse { +- // The upload_id of the newly started resumable write operation. This +- // value should be copied into the `WriteObjectRequest.upload_id` field. ++ // A unique identifier for the initiated resumable write operation. ++ // As the ID grants write access, you should keep it confidential during ++ // the upload to prevent unauthorized access and data tampering during your ++ // upload. This ID should be included in subsequent `WriteObject` requests to ++ // upload the object data. + string upload_id = 1; + } -+ // Output only. The time when the object was finalized. -+ google.protobuf.Timestamp finalize_time = 36 -+ [(google.api.field_behavior) = OUTPUT_ONLY]; +@@ -1555,6 +1865,9 @@ message ServiceConstants { + // The maximum number of days for which a token returned by the + // GetListObjectsSplitPoints RPC is valid. + SPLIT_TOKEN_MAX_VALID_DAYS = 14; + - // Content-Type of the object data, matching - // [https://tools.ietf.org/html/rfc7231#section-3.1.1.5][RFC 7231 §3.1.1.5]. - // If an object is stored without a Content-Type, it is served as ++ // The maximum number of read ranges that can be in flight. ++ MAX_READ_RANGES_IN_FLIGHT = 100; + } + } + diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index 1039d29a..d2513770 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -50,7 +50,7 @@ from google.type import date_pb2 as google_dot_type_dot_date__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x91\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x36\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x02\x18\x01H\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8d\x02\n\x15\x42idiReadObjectRequest\x12>\n\tread_spec\x18\x06 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpecB\x02\x18\x01H\x00\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x17\n\x0bread_offset\x18\x04 \x01(\x03\x42\x02\x18\x01\x12\x16\n\nread_limit\x18\x05 \x01(\x03\x42\x02\x18\x01\x42\x0f\n\rfirst_message\"\x97\x03\n\x16\x42idiReadObjectResponse\x12@\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataB\x02\x18\x01\x12@\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x02\x18\x01\x12:\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRangeB\x02\x18\x01\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x18\n\x0c\x65nd_of_range\x18\x05 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"T\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x17\n\nread_limit\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xb5\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendable\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\x81\x03\n\x10\x41ppendObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xca\x05\n\x10ServiceConstants\"\xb5\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\x97\x0b\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x36\n\rfinalize_time\x18$ \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xa8\x1d\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fgoogle/storage/v2/storage.proto\x12\x11google.storage.v2\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x18google/api/routing.proto\x1a\x1egoogle/iam/v1/iam_policy.proto\x1a\x1agoogle/iam/v1/policy.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto\x1a\x16google/type/date.proto\"\xd6\x01\n\x13\x44\x65leteBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x95\x02\n\x10GetBucketRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x02\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xce\x01\n\x13\x43reateBucketRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12)\n\x06\x62ucket\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.Bucket\x12\x16\n\tbucket_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x06 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\x07 \x01(\t\"\xc4\x01\n\x12ListBucketsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x0e\n\x06prefix\x18\x04 \x01(\t\x12\x32\n\tread_mask\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x42\x0c\n\n_read_mask\"Z\n\x13ListBucketsResponse\x12*\n\x07\x62uckets\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Bucket\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x7f\n LockBucketRetentionPolicyRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x02\"\xc6\x02\n\x13UpdateBucketRequest\x12.\n\x06\x62ucket\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.BucketB\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\x08 \x01(\t\x12%\n\x1dpredefined_default_object_acl\x18\t \x01(\t\x12\x34\n\x0bupdate_mask\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf5\x05\n\x14\x43omposeObjectRequest\x12\x33\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12L\n\x0esource_objects\x18\x02 \x03(\x0b\x32\x34.google.storage.v2.ComposeObjectRequest.SourceObject\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\t \x01(\t\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x37\n\x07kms_key\x18\x06 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12R\n\x1c\x63ommon_object_request_params\x18\x07 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\n \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x1a\xee\x01\n\x0cSourceObject\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x02 \x01(\x03\x12\x66\n\x14object_preconditions\x18\x03 \x01(\x0b\x32H.google.storage.v2.ComposeObjectRequest.SourceObject.ObjectPreconditions\x1aO\n\x13ObjectPreconditions\x12 \n\x13if_generation_match\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_metageneration_match\"\xd1\x03\n\x13\x44\x65leteObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x04 \x01(\x03\x12 \n\x13if_generation_match\x18\x05 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x06 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x07 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x08 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xa5\x04\n\x14RestoreObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12\x1a\n\rrestore_token\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12\x1c\n\x0f\x63opy_source_acl\x18\t \x01(\x08H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x12\n\x10_copy_source_acl\"5\n\x1b\x43\x61ncelResumableWriteRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\"\x1e\n\x1c\x43\x61ncelResumableWriteResponse\"\xba\x04\n\x11ReadObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x13\n\x0bread_offset\x18\x04 \x01(\x03\x12\x12\n\nread_limit\x18\x05 \x01(\x03\x12 \n\x13if_generation_match\x18\x06 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x07 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x08 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\t \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x04\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xd8\x04\n\x10GetObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12\x19\n\x0csoft_deleted\x18\x0b \x01(\x08H\x00\x88\x01\x01\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x04\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x32\n\tread_mask\x18\n \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x05\x88\x01\x01\x12\x1a\n\rrestore_token\x18\x0c \x01(\tB\x03\xe0\x41\x01\x42\x0f\n\r_soft_deletedB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_mask\"\xf5\x01\n\x12ReadObjectResponse\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12<\n\x10object_checksums\x18\x02 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x36\n\rcontent_range\x18\x03 \x01(\x0b\x32\x1f.google.storage.v2.ContentRange\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\"\x91\x05\n\x12\x42idiReadObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x12\n\ngeneration\x18\x03 \x01(\x03\x12 \n\x13if_generation_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x06 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x07 \x01(\x03H\x03\x88\x01\x01\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12\x36\n\tread_mask\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x02\x18\x01H\x04\x88\x01\x01\x12;\n\x0bread_handle\x18\r \x01(\x0b\x32!.google.storage.v2.BidiReadHandleH\x05\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x0e \x01(\tH\x06\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0c\n\n_read_maskB\x0e\n\x0c_read_handleB\x10\n\x0e_routing_token\"\x8b\x01\n\x15\x42idiReadObjectRequest\x12?\n\x10read_object_spec\x18\x01 \x01(\x0b\x32%.google.storage.v2.BidiReadObjectSpec\x12\x31\n\x0bread_ranges\x18\x08 \x03(\x0b\x32\x1c.google.storage.v2.ReadRange\"\xbd\x01\n\x16\x42idiReadObjectResponse\x12>\n\x12object_data_ranges\x18\x06 \x03(\x0b\x32\".google.storage.v2.ObjectRangeData\x12+\n\x08metadata\x18\x04 \x01(\x0b\x32\x19.google.storage.v2.Object\x12\x36\n\x0bread_handle\x18\x07 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\"\x85\x01\n\x1d\x42idiReadObjectRedirectedError\x12\x36\n\x0bread_handle\x18\x01 \x01(\x0b\x32!.google.storage.v2.BidiReadHandle\x12\x1a\n\rrouting_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_routing_token\"\xc6\x01\n\x1e\x42idiWriteObjectRedirectedError\x12\x1a\n\rrouting_token\x18\x01 \x01(\tH\x00\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x02 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x12\x17\n\ngeneration\x18\x03 \x01(\x03H\x02\x88\x01\x01\x42\x10\n\x0e_routing_tokenB\x0f\n\r_write_handleB\r\n\x0b_generation\"S\n\x13\x42idiReadObjectError\x12<\n\x11read_range_errors\x18\x01 \x03(\x0b\x32!.google.storage.v2.ReadRangeError\"E\n\x0eReadRangeError\x12\x0f\n\x07read_id\x18\x01 \x01(\x03\x12\"\n\x06status\x18\x02 \x01(\x0b\x32\x12.google.rpc.Status\"U\n\tReadRange\x12\x18\n\x0bread_offset\x18\x01 \x01(\x03\x42\x03\xe0\x41\x02\x12\x18\n\x0bread_length\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01\x12\x14\n\x07read_id\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\"\x94\x01\n\x0fObjectRangeData\x12<\n\x10\x63hecksummed_data\x18\x01 \x01(\x0b\x32\".google.storage.v2.ChecksummedData\x12\x30\n\nread_range\x18\x02 \x01(\x0b\x32\x1c.google.storage.v2.ReadRange\x12\x11\n\trange_end\x18\x03 \x01(\x08\"%\n\x0e\x42idiReadHandle\x12\x13\n\x06handle\x18\x01 \x01(\x0c\x42\x03\xe0\x41\x02\"!\n\x0f\x42idiWriteHandle\x12\x0e\n\x06handle\x18\x01 \x01(\x0c\"\xb5\x03\n\x0fWriteObjectSpec\x12\x30\n\x08resource\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12\x16\n\x0epredefined_acl\x18\x07 \x01(\t\x12 \n\x13if_generation_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x06 \x01(\x03H\x03\x88\x01\x01\x12\x18\n\x0bobject_size\x18\x08 \x01(\x03H\x04\x88\x01\x01\x12\x17\n\nappendable\x18\t \x01(\x08H\x05\x88\x01\x01\x42\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x0e\n\x0c_object_sizeB\r\n\x0b_appendable\"\x86\x03\n\x12WriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0c\x66inish_write\x18\x07 \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"n\n\x13WriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\x81\x03\n\x10\x41ppendObjectSpec\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x13\n\x06object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rrouting_token\x18\x06 \x01(\tH\x02\x88\x01\x01\x12=\n\x0cwrite_handle\x18\x07 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x03\x88\x01\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x10\n\x0e_routing_tokenB\x0f\n\r_write_handle\"\xf2\x03\n\x16\x42idiWriteObjectRequest\x12\x13\n\tupload_id\x18\x01 \x01(\tH\x00\x12?\n\x11write_object_spec\x18\x02 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecH\x00\x12\x41\n\x12\x61ppend_object_spec\x18\x0b \x01(\x0b\x32#.google.storage.v2.AppendObjectSpecH\x00\x12\x19\n\x0cwrite_offset\x18\x03 \x01(\x03\x42\x03\xe0\x41\x02\x12>\n\x10\x63hecksummed_data\x18\x04 \x01(\x0b\x32\".google.storage.v2.ChecksummedDataH\x01\x12<\n\x10object_checksums\x18\x06 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\x12\x14\n\x0cstate_lookup\x18\x07 \x01(\x08\x12\r\n\x05\x66lush\x18\x08 \x01(\x08\x12\x14\n\x0c\x66inish_write\x18\t \x01(\x08\x12R\n\x1c\x63ommon_object_request_params\x18\n \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x0f\n\rfirst_messageB\x06\n\x04\x64\x61ta\"\xc2\x01\n\x17\x42idiWriteObjectResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x12=\n\x0cwrite_handle\x18\x03 \x01(\x0b\x32\".google.storage.v2.BidiWriteHandleH\x01\x88\x01\x01\x42\x0e\n\x0cwrite_statusB\x0f\n\r_write_handle\"\xad\x03\n\x12ListObjectsRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x11\n\tdelimiter\x18\x04 \x01(\t\x12\"\n\x1ainclude_trailing_delimiter\x18\x05 \x01(\x08\x12\x0e\n\x06prefix\x18\x06 \x01(\t\x12\x10\n\x08versions\x18\x07 \x01(\x08\x12\x32\n\tread_mask\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskH\x00\x88\x01\x01\x12 \n\x13lexicographic_start\x18\n \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x0b \x01(\tB\x03\xe0\x41\x01\x12\x19\n\x0csoft_deleted\x18\x0c \x01(\x08\x42\x03\xe0\x41\x01\x12(\n\x1binclude_folders_as_prefixes\x18\r \x01(\x08\x42\x03\xe0\x41\x01\x12\x17\n\nmatch_glob\x18\x0e \x01(\tB\x03\xe0\x41\x01\x42\x0c\n\n_read_mask\"\x85\x01\n\x17QueryWriteStatusRequest\x12\x16\n\tupload_id\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x02 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\"s\n\x18QueryWriteStatusResponse\x12\x18\n\x0epersisted_size\x18\x01 \x01(\x03H\x00\x12-\n\x08resource\x18\x02 \x01(\x0b\x32\x19.google.storage.v2.ObjectH\x00\x42\x0e\n\x0cwrite_status\"\xa8\n\n\x14RewriteObjectRequest\x12 \n\x10\x64\x65stination_name\x18\x18 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05\x12\x44\n\x12\x64\x65stination_bucket\x18\x19 \x01(\tB(\xe0\x41\x02\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x43\n\x13\x64\x65stination_kms_key\x18\x1b \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12.\n\x0b\x64\x65stination\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.Object\x12<\n\rsource_bucket\x18\x02 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x19\n\x11source_generation\x18\x04 \x01(\x03\x12\x15\n\rrewrite_token\x18\x05 \x01(\t\x12\"\n\x1a\x64\x65stination_predefined_acl\x18\x1c \x01(\t\x12 \n\x13if_generation_match\x18\x07 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x08 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\t \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\n \x01(\x03H\x03\x88\x01\x01\x12\'\n\x1aif_source_generation_match\x18\x0b \x01(\x03H\x04\x88\x01\x01\x12+\n\x1eif_source_generation_not_match\x18\x0c \x01(\x03H\x05\x88\x01\x01\x12+\n\x1eif_source_metageneration_match\x18\r \x01(\x03H\x06\x88\x01\x01\x12/\n\"if_source_metageneration_not_match\x18\x0e \x01(\x03H\x07\x88\x01\x01\x12$\n\x1cmax_bytes_rewritten_per_call\x18\x0f \x01(\x03\x12(\n copy_source_encryption_algorithm\x18\x10 \x01(\t\x12(\n copy_source_encryption_key_bytes\x18\x15 \x01(\x0c\x12/\n\'copy_source_encryption_key_sha256_bytes\x18\x16 \x01(\x0c\x12R\n\x1c\x63ommon_object_request_params\x18\x13 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x1d \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_matchB\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_match\"\x97\x01\n\x0fRewriteResponse\x12\x1d\n\x15total_bytes_rewritten\x18\x01 \x01(\x03\x12\x13\n\x0bobject_size\x18\x02 \x01(\x03\x12\x0c\n\x04\x64one\x18\x03 \x01(\x08\x12\x15\n\rrewrite_token\x18\x04 \x01(\t\x12+\n\x08resource\x18\x05 \x01(\x0b\x32\x19.google.storage.v2.Object\"\xf7\x05\n\x11MoveObjectRequest\x12\x35\n\x06\x62ucket\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x1a\n\rsource_object\x18\x02 \x01(\tB\x03\xe0\x41\x02\x12\x1f\n\x12\x64\x65stination_object\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12,\n\x1aif_source_generation_match\x18\x04 \x01(\x03\x42\x03\xe0\x41\x01H\x00\x88\x01\x01\x12\x30\n\x1eif_source_generation_not_match\x18\x05 \x01(\x03\x42\x03\xe0\x41\x01H\x01\x88\x01\x01\x12\x30\n\x1eif_source_metageneration_match\x18\x06 \x01(\x03\x42\x03\xe0\x41\x01H\x02\x88\x01\x01\x12\x34\n\"if_source_metageneration_not_match\x18\x07 \x01(\x03\x42\x03\xe0\x41\x01H\x03\x88\x01\x01\x12%\n\x13if_generation_match\x18\x08 \x01(\x03\x42\x03\xe0\x41\x01H\x04\x88\x01\x01\x12)\n\x17if_generation_not_match\x18\t \x01(\x03\x42\x03\xe0\x41\x01H\x05\x88\x01\x01\x12)\n\x17if_metageneration_match\x18\n \x01(\x03\x42\x03\xe0\x41\x01H\x06\x88\x01\x01\x12-\n\x1bif_metageneration_not_match\x18\x0b \x01(\x03\x42\x03\xe0\x41\x01H\x07\x88\x01\x01\x42\x1d\n\x1b_if_source_generation_matchB!\n\x1f_if_source_generation_not_matchB!\n\x1f_if_source_metageneration_matchB%\n#_if_source_metageneration_not_matchB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xf2\x01\n\x1aStartResumableWriteRequest\x12\x42\n\x11write_object_spec\x18\x01 \x01(\x0b\x32\".google.storage.v2.WriteObjectSpecB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x03 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParams\x12<\n\x10object_checksums\x18\x05 \x01(\x0b\x32\".google.storage.v2.ObjectChecksums\"0\n\x1bStartResumableWriteResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\"\xef\x03\n\x13UpdateObjectRequest\x12.\n\x06object\x18\x01 \x01(\x0b\x32\x19.google.storage.v2.ObjectB\x03\xe0\x41\x02\x12 \n\x13if_generation_match\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17if_generation_not_match\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12$\n\x17if_metageneration_match\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x16\n\x0epredefined_acl\x18\n \x01(\t\x12\x34\n\x0bupdate_mask\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12R\n\x1c\x63ommon_object_request_params\x18\x08 \x01(\x0b\x32,.google.storage.v2.CommonObjectRequestParamsB\x16\n\x14_if_generation_matchB\x1a\n\x18_if_generation_not_matchB\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"|\n\x19\x43ommonObjectRequestParams\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x1c\n\x14\x65ncryption_key_bytes\x18\x04 \x01(\x0c\x12#\n\x1b\x65ncryption_key_sha256_bytes\x18\x05 \x01(\x0c\"\xe9\x05\n\x10ServiceConstants\"\xd4\x05\n\x06Values\x12\x16\n\x12VALUES_UNSPECIFIED\x10\x00\x12\x1b\n\x14MAX_READ_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x1c\n\x15MAX_WRITE_CHUNK_BYTES\x10\x80\x80\x80\x01\x12\x19\n\x12MAX_OBJECT_SIZE_MB\x10\x80\x80\xc0\x02\x12)\n$MAX_CUSTOM_METADATA_FIELD_NAME_BYTES\x10\x80\x08\x12*\n%MAX_CUSTOM_METADATA_FIELD_VALUE_BYTES\x10\x80 \x12)\n$MAX_CUSTOM_METADATA_TOTAL_SIZE_BYTES\x10\x80@\x12*\n$MAX_BUCKET_METADATA_TOTAL_SIZE_BYTES\x10\x80\xa0\x01\x12\'\n#MAX_NOTIFICATION_CONFIGS_PER_BUCKET\x10\x64\x12\"\n\x1eMAX_LIFECYCLE_RULES_PER_BUCKET\x10\x64\x12&\n\"MAX_NOTIFICATION_CUSTOM_ATTRIBUTES\x10\x05\x12\x31\n,MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\x10\x80\x02\x12\x33\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_VALUE_LENGTH\x10\x80\x08\x12\x1c\n\x18MAX_LABELS_ENTRIES_COUNT\x10@\x12\x1f\n\x1bMAX_LABELS_KEY_VALUE_LENGTH\x10?\x12\x1f\n\x1aMAX_LABELS_KEY_VALUE_BYTES\x10\x80\x01\x12.\n)MAX_OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\x10\xe8\x07\x12\x1e\n\x1aSPLIT_TOKEN_MAX_VALID_DAYS\x10\x0e\x12\x1d\n\x19MAX_READ_RANGES_IN_FLIGHT\x10\x64\x1a\x02\x10\x01\"\xa3\x1c\n\x06\x42ucket\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x16\n\tbucket_id\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x0c\n\x04\x65tag\x18\x1d \x01(\t\x12\x44\n\x07project\x18\x03 \x01(\tB3\xe0\x41\x05\xfa\x41-\n+cloudresourcemanager.googleapis.com/Project\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x05 \x01(\tB\x03\xe0\x41\x05\x12\x1a\n\rlocation_type\x18\x06 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x07 \x01(\t\x12\x0b\n\x03rpo\x18\x1b \x01(\t\x12\x33\n\x03\x61\x63l\x18\x08 \x03(\x0b\x32&.google.storage.v2.BucketAccessControl\x12\x42\n\x12\x64\x65\x66\x61ult_object_acl\x18\t \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x36\n\tlifecycle\x18\n \x01(\x0b\x32#.google.storage.v2.Bucket.Lifecycle\x12\x34\n\x0b\x63reate_time\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12,\n\x04\x63ors\x18\x0c \x03(\x0b\x32\x1e.google.storage.v2.Bucket.Cors\x12\x34\n\x0bupdate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12 \n\x18\x64\x65\x66\x61ult_event_based_hold\x18\x0e \x01(\x08\x12\x35\n\x06labels\x18\x0f \x03(\x0b\x32%.google.storage.v2.Bucket.LabelsEntry\x12\x32\n\x07website\x18\x10 \x01(\x0b\x32!.google.storage.v2.Bucket.Website\x12\x38\n\nversioning\x18\x11 \x01(\x0b\x32$.google.storage.v2.Bucket.Versioning\x12\x32\n\x07logging\x18\x12 \x01(\x0b\x32!.google.storage.v2.Bucket.Logging\x12,\n\x05owner\x18\x13 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x38\n\nencryption\x18\x14 \x01(\x0b\x32$.google.storage.v2.Bucket.Encryption\x12\x32\n\x07\x62illing\x18\x15 \x01(\x0b\x32!.google.storage.v2.Bucket.Billing\x12\x43\n\x10retention_policy\x18\x16 \x01(\x0b\x32).google.storage.v2.Bucket.RetentionPolicy\x12\x37\n\niam_config\x18\x17 \x01(\x0b\x32#.google.storage.v2.Bucket.IamConfig\x12\x15\n\rsatisfies_pzs\x18\x19 \x01(\x08\x12P\n\x17\x63ustom_placement_config\x18\x1a \x01(\x0b\x32/.google.storage.v2.Bucket.CustomPlacementConfig\x12\x36\n\tautoclass\x18\x1c \x01(\x0b\x32#.google.storage.v2.Bucket.Autoclass\x12T\n\x16hierarchical_namespace\x18 \x01(\x0b\x32/.google.storage.v2.Bucket.HierarchicalNamespaceB\x03\xe0\x41\x01\x12K\n\x12soft_delete_policy\x18\x1f \x01(\x0b\x32*.google.storage.v2.Bucket.SoftDeletePolicyB\x03\xe0\x41\x01\x1a!\n\x07\x42illing\x12\x16\n\x0erequester_pays\x18\x01 \x01(\x08\x1aX\n\x04\x43ors\x12\x0e\n\x06origin\x18\x01 \x03(\t\x12\x0e\n\x06method\x18\x02 \x03(\t\x12\x17\n\x0fresponse_header\x18\x03 \x03(\t\x12\x17\n\x0fmax_age_seconds\x18\x04 \x01(\x05\x1aM\n\nEncryption\x12?\n\x0f\x64\x65\x66\x61ult_kms_key\x18\x01 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x1a\xec\x01\n\tIamConfig\x12\x61\n\x1buniform_bucket_level_access\x18\x01 \x01(\x0b\x32<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccess\x12 \n\x18public_access_prevention\x18\x03 \x01(\t\x1aZ\n\x18UniformBucketLevelAccess\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12-\n\tlock_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x1a\xf3\x05\n\tLifecycle\x12\x36\n\x04rule\x18\x01 \x03(\x0b\x32(.google.storage.v2.Bucket.Lifecycle.Rule\x1a\xad\x05\n\x04Rule\x12?\n\x06\x61\x63tion\x18\x01 \x01(\x0b\x32/.google.storage.v2.Bucket.Lifecycle.Rule.Action\x12\x45\n\tcondition\x18\x02 \x01(\x0b\x32\x32.google.storage.v2.Bucket.Lifecycle.Rule.Condition\x1a-\n\x06\x41\x63tion\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x15\n\rstorage_class\x18\x02 \x01(\t\x1a\xed\x03\n\tCondition\x12\x15\n\x08\x61ge_days\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x0e\x63reated_before\x18\x02 \x01(\x0b\x32\x11.google.type.Date\x12\x14\n\x07is_live\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12num_newer_versions\x18\x04 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x15matches_storage_class\x18\x05 \x03(\t\x12#\n\x16\x64\x61ys_since_custom_time\x18\x07 \x01(\x05H\x03\x88\x01\x01\x12-\n\x12\x63ustom_time_before\x18\x08 \x01(\x0b\x32\x11.google.type.Date\x12\'\n\x1a\x64\x61ys_since_noncurrent_time\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x31\n\x16noncurrent_time_before\x18\n \x01(\x0b\x32\x11.google.type.Date\x12\x16\n\x0ematches_prefix\x18\x0b \x03(\t\x12\x16\n\x0ematches_suffix\x18\x0c \x03(\tB\x0b\n\t_age_daysB\n\n\x08_is_liveB\x15\n\x13_num_newer_versionsB\x19\n\x17_days_since_custom_timeB\x1d\n\x1b_days_since_noncurrent_time\x1a\x38\n\x07Logging\x12\x12\n\nlog_bucket\x18\x01 \x01(\t\x12\x19\n\x11log_object_prefix\x18\x02 \x01(\t\x1a\x8f\x01\n\x0fRetentionPolicy\x12\x32\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x11\n\tis_locked\x18\x02 \x01(\x08\x12\x35\n\x12retention_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\xb1\x01\n\x10SoftDeletePolicy\x12:\n\x12retention_duration\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00\x88\x01\x01\x12\x37\n\x0e\x65\x66\x66\x65\x63tive_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x15\n\x13_retention_durationB\x11\n\x0f_effective_time\x1a\x1d\n\nVersioning\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x1a;\n\x07Website\x12\x18\n\x10main_page_suffix\x18\x01 \x01(\t\x12\x16\n\x0enot_found_page\x18\x02 \x01(\t\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a\x8b\x02\n\tAutoclass\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x34\n\x0btoggle_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12#\n\x16terminal_storage_class\x18\x03 \x01(\tH\x00\x88\x01\x01\x12P\n\"terminal_storage_class_update_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x01\x88\x01\x01\x42\x19\n\x17_terminal_storage_classB%\n#_terminal_storage_class_update_time\x1a-\n\x15HierarchicalNamespace\x12\x14\n\x07\x65nabled\x18\x01 \x01(\x08\x42\x03\xe0\x41\x01\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01:X\xea\x41U\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}*\x07\x62uckets2\x06\x62ucket\"\xce\x01\n\x13\x42ucketAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"I\n\x0f\x43hecksummedData\x12\x16\n\x07\x63ontent\x18\x01 \x01(\x0c\x42\x05\x08\x01\xe0\x41\x01\x12\x13\n\x06\x63rc32c\x18\x02 \x01(\x07H\x00\x88\x01\x01\x42\t\n\x07_crc32c\"C\n\x0fObjectChecksums\x12\x13\n\x06\x63rc32c\x18\x01 \x01(\x07H\x00\x88\x01\x01\x12\x10\n\x08md5_hash\x18\x02 \x01(\x0c\x42\t\n\x07_crc32c\"L\n\x12\x43ustomerEncryption\x12\x1c\n\x14\x65ncryption_algorithm\x18\x01 \x01(\t\x12\x18\n\x10key_sha256_bytes\x18\x03 \x01(\x0c\"\x97\x0b\n\x06Object\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x35\n\x06\x62ucket\x18\x02 \x01(\tB%\xe0\x41\x05\xfa\x41\x1f\n\x1dstorage.googleapis.com/Bucket\x12\x0c\n\x04\x65tag\x18\x1b \x01(\t\x12\x17\n\ngeneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x05\x12\x1f\n\rrestore_token\x18# \x01(\tB\x03\xe0\x41\x03H\x00\x88\x01\x01\x12\x1b\n\x0emetageneration\x18\x04 \x01(\x03\x42\x03\xe0\x41\x03\x12\x15\n\rstorage_class\x18\x05 \x01(\t\x12\x11\n\x04size\x18\x06 \x01(\x03\x42\x03\xe0\x41\x03\x12\x18\n\x10\x63ontent_encoding\x18\x07 \x01(\t\x12\x1b\n\x13\x63ontent_disposition\x18\x08 \x01(\t\x12\x15\n\rcache_control\x18\t \x01(\t\x12\x33\n\x03\x61\x63l\x18\n \x03(\x0b\x32&.google.storage.v2.ObjectAccessControl\x12\x18\n\x10\x63ontent_language\x18\x0b \x01(\t\x12\x34\n\x0b\x64\x65lete_time\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x36\n\rfinalize_time\x18$ \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x14\n\x0c\x63ontent_type\x18\r \x01(\t\x12\x34\n\x0b\x63reate_time\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x1c\n\x0f\x63omponent_count\x18\x0f \x01(\x05\x42\x03\xe0\x41\x03\x12:\n\tchecksums\x18\x10 \x01(\x0b\x32\".google.storage.v2.ObjectChecksumsB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x37\n\x07kms_key\x18\x12 \x01(\tB&\xfa\x41#\n!cloudkms.googleapis.com/CryptoKey\x12\x42\n\x19update_storage_class_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x16\n\x0etemporary_hold\x18\x14 \x01(\x08\x12\x39\n\x15retention_expire_time\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x39\n\x08metadata\x18\x16 \x03(\x0b\x32\'.google.storage.v2.Object.MetadataEntry\x12\x1d\n\x10\x65vent_based_hold\x18\x17 \x01(\x08H\x01\x88\x01\x01\x12,\n\x05owner\x18\x18 \x01(\x0b\x32\x18.google.storage.v2.OwnerB\x03\xe0\x41\x03\x12\x42\n\x13\x63ustomer_encryption\x18\x19 \x01(\x0b\x32%.google.storage.v2.CustomerEncryption\x12/\n\x0b\x63ustom_time\x18\x1a \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12>\n\x10soft_delete_time\x18\x1c \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02\x88\x01\x01\x12>\n\x10hard_delete_time\x18\x1d \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x03\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x10\n\x0e_restore_tokenB\x13\n\x11_event_based_holdB\x13\n\x11_soft_delete_timeB\x13\n\x11_hard_delete_time\"\xce\x01\n\x13ObjectAccessControl\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65ntity\x18\x03 \x01(\t\x12\x17\n\nentity_alt\x18\t \x01(\tB\x03\xe0\x41\x03\x12\x11\n\tentity_id\x18\x04 \x01(\t\x12\x0c\n\x04\x65tag\x18\x08 \x01(\t\x12\r\n\x05\x65mail\x18\x05 \x01(\t\x12\x0e\n\x06\x64omain\x18\x06 \x01(\t\x12\x34\n\x0cproject_team\x18\x07 \x01(\x0b\x32\x1e.google.storage.v2.ProjectTeam\"l\n\x13ListObjectsResponse\x12*\n\x07objects\x18\x01 \x03(\x0b\x32\x19.google.storage.v2.Object\x12\x10\n\x08prefixes\x18\x02 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x03 \x01(\t\"3\n\x0bProjectTeam\x12\x16\n\x0eproject_number\x18\x01 \x01(\t\x12\x0c\n\x04team\x18\x02 \x01(\t\"*\n\x05Owner\x12\x0e\n\x06\x65ntity\x18\x01 \x01(\t\x12\x11\n\tentity_id\x18\x02 \x01(\t\"C\n\x0c\x43ontentRange\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x17\n\x0f\x63omplete_length\x18\x03 \x01(\x03\x32\xc1\x1e\n\x07Storage\x12r\n\x0c\x44\x65leteBucket\x12&.google.storage.v2.DeleteBucketRequest\x1a\x16.google.protobuf.Empty\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12o\n\tGetBucket\x12#.google.storage.v2.GetBucketRequest\x1a\x19.google.storage.v2.Bucket\"\"\xda\x41\x04name\x8a\xd3\xe4\x93\x02\x15\x12\x13\n\x04name\x12\x0b{bucket=**}\x12\xab\x01\n\x0c\x43reateBucket\x12&.google.storage.v2.CreateBucketRequest\x1a\x19.google.storage.v2.Bucket\"X\xda\x41\x17parent,bucket,bucket_id\x8a\xd3\xe4\x93\x02\x38\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x1e\n\x0e\x62ucket.project\x12\x0c{project=**}\x12\x85\x01\n\x0bListBuckets\x12%.google.storage.v2.ListBucketsRequest\x1a&.google.storage.v2.ListBucketsResponse\"\'\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x18\x12\x16\n\x06parent\x12\x0c{project=**}\x12\x93\x01\n\x19LockBucketRetentionPolicy\x12\x33.google.storage.v2.LockBucketRetentionPolicyRequest\x1a\x19.google.storage.v2.Bucket\"&\xda\x41\x06\x62ucket\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12u\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"*\xda\x41\x08resource\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12|\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"1\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02\x19\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x96\x02\n\x12TestIamPermissions\x12(.google.iam.v1.TestIamPermissionsRequest\x1a).google.iam.v1.TestIamPermissionsResponse\"\xaa\x01\xda\x41\x14resource,permissions\x8a\xd3\xe4\x93\x02\x8c\x01\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12\x34\n\x08resource\x12({bucket=projects/*/buckets/*}/objects/**\x12;\n\x08resource\x12/{bucket=projects/*/buckets/*}/managedFolders/**\x12\x8a\x01\n\x0cUpdateBucket\x12&.google.storage.v2.UpdateBucketRequest\x1a\x19.google.storage.v2.Bucket\"7\xda\x41\x12\x62ucket,update_mask\x8a\xd3\xe4\x93\x02\x1c\x12\x1a\n\x0b\x62ucket.name\x12\x0b{bucket=**}\x12~\n\rComposeObject\x12\'.google.storage.v2.ComposeObjectRequest\x1a\x19.google.storage.v2.Object\")\x8a\xd3\xe4\x93\x02#\x12!\n\x12\x64\x65stination.bucket\x12\x0b{bucket=**}\x12\x98\x01\n\x0c\x44\x65leteObject\x12&.google.storage.v2.DeleteObjectRequest\x1a\x16.google.protobuf.Empty\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\x8d\x01\n\rRestoreObject\x12\'.google.storage.v2.RestoreObjectRequest\x1a\x19.google.storage.v2.Object\"8\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xba\x01\n\x14\x43\x61ncelResumableWrite\x12..google.storage.v2.CancelResumableWriteRequest\x1a/.google.storage.v2.CancelResumableWriteResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x95\x01\n\tGetObject\x12#.google.storage.v2.GetObjectRequest\x1a\x19.google.storage.v2.Object\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x12\xa5\x01\n\nReadObject\x12$.google.storage.v2.ReadObjectRequest\x1a%.google.storage.v2.ReadObjectResponse\"H\xda\x41\rbucket,object\xda\x41\x18\x62ucket,object,generation\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}0\x01\x12\x99\x01\n\x0e\x42idiReadObject\x12(.google.storage.v2.BidiReadObjectRequest\x1a).google.storage.v2.BidiReadObjectResponse\".\x8a\xd3\xe4\x93\x02(\x12&\n\x17read_object_spec.bucket\x12\x0b{bucket=**}(\x01\x30\x01\x12\x8c\x01\n\x0cUpdateObject\x12&.google.storage.v2.UpdateObjectRequest\x1a\x19.google.storage.v2.Object\"9\xda\x41\x12object,update_mask\x8a\xd3\xe4\x93\x02\x1e\x12\x1c\n\robject.bucket\x12\x0b{bucket=**}\x12`\n\x0bWriteObject\x12%.google.storage.v2.WriteObjectRequest\x1a&.google.storage.v2.WriteObjectResponse\"\x00(\x01\x12n\n\x0f\x42idiWriteObject\x12).google.storage.v2.BidiWriteObjectRequest\x1a*.google.storage.v2.BidiWriteObjectResponse\"\x00(\x01\x30\x01\x12\x84\x01\n\x0bListObjects\x12%.google.storage.v2.ListObjectsRequest\x1a&.google.storage.v2.ListObjectsResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x98\x01\n\rRewriteObject\x12\'.google.storage.v2.RewriteObjectRequest\x1a\".google.storage.v2.RewriteResponse\":\x8a\xd3\xe4\x93\x02\x34\x12\x0f\n\rsource_bucket\x12!\n\x12\x64\x65stination_bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x13StartResumableWrite\x12-.google.storage.v2.StartResumableWriteRequest\x1a..google.storage.v2.StartResumableWriteResponse\"8\x8a\xd3\xe4\x93\x02\x32\x12\x30\n!write_object_spec.resource.bucket\x12\x0b{bucket=**}\x12\xae\x01\n\x10QueryWriteStatus\x12*.google.storage.v2.QueryWriteStatusRequest\x1a+.google.storage.v2.QueryWriteStatusResponse\"A\xda\x41\tupload_id\x8a\xd3\xe4\x93\x02/\x12-\n\tupload_id\x12 {bucket=projects/*/buckets/*}/**\x12\x96\x01\n\nMoveObject\x12$.google.storage.v2.MoveObjectRequest\x1a\x19.google.storage.v2.Object\"G\xda\x41\'bucket,source_object,destination_object\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06\x62ucket\x12\x0b{bucket=**}\x1a\xa7\x02\xca\x41\x16storage.googleapis.com\xd2\x41\x8a\x02https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\xe2\x01\n\x15\x63om.google.storage.v2B\x0cStorageProtoP\x01Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\xea\x41x\n!cloudkms.googleapis.com/CryptoKey\x12Sprojects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -112,24 +112,10 @@ _globals['_BIDIREADOBJECTSPEC'].fields_by_name['object']._serialized_options = b'\340A\002' _globals['_BIDIREADOBJECTSPEC'].fields_by_name['read_mask']._loaded_options = None _globals['_BIDIREADOBJECTSPEC'].fields_by_name['read_mask']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._loaded_options = None - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_spec']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._loaded_options = None - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_offset']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_limit']._loaded_options = None - _globals['_BIDIREADOBJECTREQUEST'].fields_by_name['read_limit']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['checksummed_data']._loaded_options = None - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['checksummed_data']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['object_checksums']._loaded_options = None - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['object_checksums']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['content_range']._loaded_options = None - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['content_range']._serialized_options = b'\030\001' - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['end_of_range']._loaded_options = None - _globals['_BIDIREADOBJECTRESPONSE'].fields_by_name['end_of_range']._serialized_options = b'\030\001' _globals['_READRANGE'].fields_by_name['read_offset']._loaded_options = None _globals['_READRANGE'].fields_by_name['read_offset']._serialized_options = b'\340A\002' - _globals['_READRANGE'].fields_by_name['read_limit']._loaded_options = None - _globals['_READRANGE'].fields_by_name['read_limit']._serialized_options = b'\340A\001' + _globals['_READRANGE'].fields_by_name['read_length']._loaded_options = None + _globals['_READRANGE'].fields_by_name['read_length']._serialized_options = b'\340A\001' _globals['_READRANGE'].fields_by_name['read_id']._loaded_options = None _globals['_READRANGE'].fields_by_name['read_id']._serialized_options = b'\340A\002' _globals['_BIDIREADHANDLE'].fields_by_name['handle']._loaded_options = None @@ -170,6 +156,28 @@ _globals['_REWRITEOBJECTREQUEST'].fields_by_name['source_bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' _globals['_REWRITEOBJECTREQUEST'].fields_by_name['source_object']._loaded_options = None _globals['_REWRITEOBJECTREQUEST'].fields_by_name['source_object']._serialized_options = b'\340A\002' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['bucket']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['bucket']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Bucket' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['source_object']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['source_object']._serialized_options = b'\340A\002' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['destination_object']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['destination_object']._serialized_options = b'\340A\002' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_generation_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_generation_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_generation_not_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_generation_not_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_metageneration_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_metageneration_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_metageneration_not_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_source_metageneration_not_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_generation_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_generation_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_generation_not_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_generation_not_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_metageneration_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_metageneration_match']._serialized_options = b'\340A\001' + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_metageneration_not_match']._loaded_options = None + _globals['_MOVEOBJECTREQUEST'].fields_by_name['if_metageneration_not_match']._serialized_options = b'\340A\001' _globals['_STARTRESUMABLEWRITEREQUEST'].fields_by_name['write_object_spec']._loaded_options = None _globals['_STARTRESUMABLEWRITEREQUEST'].fields_by_name['write_object_spec']._serialized_options = b'\340A\002' _globals['_UPDATEOBJECTREQUEST'].fields_by_name['object']._loaded_options = None @@ -298,6 +306,8 @@ _globals['_STORAGE'].methods_by_name['StartResumableWrite']._serialized_options = b'\212\323\344\223\0022\0220\n!write_object_spec.resource.bucket\022\013{bucket=**}' _globals['_STORAGE'].methods_by_name['QueryWriteStatus']._loaded_options = None _globals['_STORAGE'].methods_by_name['QueryWriteStatus']._serialized_options = b'\332A\tupload_id\212\323\344\223\002/\022-\n\tupload_id\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGE'].methods_by_name['MoveObject']._loaded_options = None + _globals['_STORAGE'].methods_by_name['MoveObject']._serialized_options = b'\332A\'bucket,source_object,destination_object\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}' _globals['_DELETEBUCKETREQUEST']._serialized_start=403 _globals['_DELETEBUCKETREQUEST']._serialized_end=617 _globals['_GETBUCKETREQUEST']._serialized_start=620 @@ -335,119 +345,121 @@ _globals['_BIDIREADOBJECTSPEC']._serialized_start=5149 _globals['_BIDIREADOBJECTSPEC']._serialized_end=5806 _globals['_BIDIREADOBJECTREQUEST']._serialized_start=5809 - _globals['_BIDIREADOBJECTREQUEST']._serialized_end=6078 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=6081 - _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=6488 - _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=6491 - _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=6624 - _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_start=6627 - _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_end=6825 - _globals['_BIDIREADOBJECTERROR']._serialized_start=6827 - _globals['_BIDIREADOBJECTERROR']._serialized_end=6910 - _globals['_READRANGEERROR']._serialized_start=6912 - _globals['_READRANGEERROR']._serialized_end=6981 - _globals['_READRANGE']._serialized_start=6983 - _globals['_READRANGE']._serialized_end=7067 - _globals['_OBJECTRANGEDATA']._serialized_start=7070 - _globals['_OBJECTRANGEDATA']._serialized_end=7218 - _globals['_BIDIREADHANDLE']._serialized_start=7220 - _globals['_BIDIREADHANDLE']._serialized_end=7257 - _globals['_BIDIWRITEHANDLE']._serialized_start=7259 - _globals['_BIDIWRITEHANDLE']._serialized_end=7292 - _globals['_WRITEOBJECTSPEC']._serialized_start=7295 - _globals['_WRITEOBJECTSPEC']._serialized_end=7732 - _globals['_WRITEOBJECTREQUEST']._serialized_start=7735 - _globals['_WRITEOBJECTREQUEST']._serialized_end=8125 - _globals['_WRITEOBJECTRESPONSE']._serialized_start=8127 - _globals['_WRITEOBJECTRESPONSE']._serialized_end=8237 - _globals['_APPENDOBJECTSPEC']._serialized_start=8240 - _globals['_APPENDOBJECTSPEC']._serialized_end=8625 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8628 - _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=9126 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=9129 - _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=9323 - _globals['_LISTOBJECTSREQUEST']._serialized_start=9326 - _globals['_LISTOBJECTSREQUEST']._serialized_end=9755 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9758 - _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9891 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9893 - _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=10008 - _globals['_REWRITEOBJECTREQUEST']._serialized_start=10011 - _globals['_REWRITEOBJECTREQUEST']._serialized_end=11331 - _globals['_REWRITERESPONSE']._serialized_start=11334 - _globals['_REWRITERESPONSE']._serialized_end=11485 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11488 - _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=11730 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=11732 - _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=11780 - _globals['_UPDATEOBJECTREQUEST']._serialized_start=11783 - _globals['_UPDATEOBJECTREQUEST']._serialized_end=12278 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12280 - _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12404 - _globals['_SERVICECONSTANTS']._serialized_start=12407 - _globals['_SERVICECONSTANTS']._serialized_end=13121 - _globals['_SERVICECONSTANTS_VALUES']._serialized_start=12428 - _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13121 - _globals['_BUCKET']._serialized_start=13124 - _globals['_BUCKET']._serialized_end=16743 - _globals['_BUCKET_BILLING']._serialized_start=14565 - _globals['_BUCKET_BILLING']._serialized_end=14598 - _globals['_BUCKET_CORS']._serialized_start=14600 - _globals['_BUCKET_CORS']._serialized_end=14688 - _globals['_BUCKET_ENCRYPTION']._serialized_start=14690 - _globals['_BUCKET_ENCRYPTION']._serialized_end=14767 - _globals['_BUCKET_IAMCONFIG']._serialized_start=14770 - _globals['_BUCKET_IAMCONFIG']._serialized_end=15006 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=14916 - _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15006 - _globals['_BUCKET_LIFECYCLE']._serialized_start=15009 - _globals['_BUCKET_LIFECYCLE']._serialized_end=15764 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15079 - _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=15764 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15223 - _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15268 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15271 - _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=15764 - _globals['_BUCKET_LOGGING']._serialized_start=15766 - _globals['_BUCKET_LOGGING']._serialized_end=15822 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=15825 - _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=15968 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=15971 - _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16148 - _globals['_BUCKET_VERSIONING']._serialized_start=16150 - _globals['_BUCKET_VERSIONING']._serialized_end=16179 - _globals['_BUCKET_WEBSITE']._serialized_start=16181 - _globals['_BUCKET_WEBSITE']._serialized_end=16240 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16242 - _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16289 - _globals['_BUCKET_AUTOCLASS']._serialized_start=16292 - _globals['_BUCKET_AUTOCLASS']._serialized_end=16559 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=16561 - _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=16606 - _globals['_BUCKET_LABELSENTRY']._serialized_start=16608 - _globals['_BUCKET_LABELSENTRY']._serialized_end=16653 - _globals['_BUCKETACCESSCONTROL']._serialized_start=16746 - _globals['_BUCKETACCESSCONTROL']._serialized_end=16952 - _globals['_CHECKSUMMEDDATA']._serialized_start=16954 - _globals['_CHECKSUMMEDDATA']._serialized_end=17027 - _globals['_OBJECTCHECKSUMS']._serialized_start=17029 - _globals['_OBJECTCHECKSUMS']._serialized_end=17096 - _globals['_CUSTOMERENCRYPTION']._serialized_start=17098 - _globals['_CUSTOMERENCRYPTION']._serialized_end=17174 - _globals['_OBJECT']._serialized_start=17177 - _globals['_OBJECT']._serialized_end=18608 - _globals['_OBJECT_METADATAENTRY']._serialized_start=18480 - _globals['_OBJECT_METADATAENTRY']._serialized_end=18527 - _globals['_OBJECTACCESSCONTROL']._serialized_start=18611 - _globals['_OBJECTACCESSCONTROL']._serialized_end=18817 - _globals['_LISTOBJECTSRESPONSE']._serialized_start=18819 - _globals['_LISTOBJECTSRESPONSE']._serialized_end=18927 - _globals['_PROJECTTEAM']._serialized_start=18929 - _globals['_PROJECTTEAM']._serialized_end=18980 - _globals['_OWNER']._serialized_start=18982 - _globals['_OWNER']._serialized_end=19024 - _globals['_CONTENTRANGE']._serialized_start=19026 - _globals['_CONTENTRANGE']._serialized_end=19093 - _globals['_STORAGE']._serialized_start=19096 - _globals['_STORAGE']._serialized_end=22848 + _globals['_BIDIREADOBJECTREQUEST']._serialized_end=5948 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_start=5951 + _globals['_BIDIREADOBJECTRESPONSE']._serialized_end=6140 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_start=6143 + _globals['_BIDIREADOBJECTREDIRECTEDERROR']._serialized_end=6276 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_start=6279 + _globals['_BIDIWRITEOBJECTREDIRECTEDERROR']._serialized_end=6477 + _globals['_BIDIREADOBJECTERROR']._serialized_start=6479 + _globals['_BIDIREADOBJECTERROR']._serialized_end=6562 + _globals['_READRANGEERROR']._serialized_start=6564 + _globals['_READRANGEERROR']._serialized_end=6633 + _globals['_READRANGE']._serialized_start=6635 + _globals['_READRANGE']._serialized_end=6720 + _globals['_OBJECTRANGEDATA']._serialized_start=6723 + _globals['_OBJECTRANGEDATA']._serialized_end=6871 + _globals['_BIDIREADHANDLE']._serialized_start=6873 + _globals['_BIDIREADHANDLE']._serialized_end=6910 + _globals['_BIDIWRITEHANDLE']._serialized_start=6912 + _globals['_BIDIWRITEHANDLE']._serialized_end=6945 + _globals['_WRITEOBJECTSPEC']._serialized_start=6948 + _globals['_WRITEOBJECTSPEC']._serialized_end=7385 + _globals['_WRITEOBJECTREQUEST']._serialized_start=7388 + _globals['_WRITEOBJECTREQUEST']._serialized_end=7778 + _globals['_WRITEOBJECTRESPONSE']._serialized_start=7780 + _globals['_WRITEOBJECTRESPONSE']._serialized_end=7890 + _globals['_APPENDOBJECTSPEC']._serialized_start=7893 + _globals['_APPENDOBJECTSPEC']._serialized_end=8278 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_start=8281 + _globals['_BIDIWRITEOBJECTREQUEST']._serialized_end=8779 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_start=8782 + _globals['_BIDIWRITEOBJECTRESPONSE']._serialized_end=8976 + _globals['_LISTOBJECTSREQUEST']._serialized_start=8979 + _globals['_LISTOBJECTSREQUEST']._serialized_end=9408 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_start=9411 + _globals['_QUERYWRITESTATUSREQUEST']._serialized_end=9544 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_start=9546 + _globals['_QUERYWRITESTATUSRESPONSE']._serialized_end=9661 + _globals['_REWRITEOBJECTREQUEST']._serialized_start=9664 + _globals['_REWRITEOBJECTREQUEST']._serialized_end=10984 + _globals['_REWRITERESPONSE']._serialized_start=10987 + _globals['_REWRITERESPONSE']._serialized_end=11138 + _globals['_MOVEOBJECTREQUEST']._serialized_start=11141 + _globals['_MOVEOBJECTREQUEST']._serialized_end=11900 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_start=11903 + _globals['_STARTRESUMABLEWRITEREQUEST']._serialized_end=12145 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_start=12147 + _globals['_STARTRESUMABLEWRITERESPONSE']._serialized_end=12195 + _globals['_UPDATEOBJECTREQUEST']._serialized_start=12198 + _globals['_UPDATEOBJECTREQUEST']._serialized_end=12693 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_start=12695 + _globals['_COMMONOBJECTREQUESTPARAMS']._serialized_end=12819 + _globals['_SERVICECONSTANTS']._serialized_start=12822 + _globals['_SERVICECONSTANTS']._serialized_end=13567 + _globals['_SERVICECONSTANTS_VALUES']._serialized_start=12843 + _globals['_SERVICECONSTANTS_VALUES']._serialized_end=13567 + _globals['_BUCKET']._serialized_start=13570 + _globals['_BUCKET']._serialized_end=17189 + _globals['_BUCKET_BILLING']._serialized_start=15011 + _globals['_BUCKET_BILLING']._serialized_end=15044 + _globals['_BUCKET_CORS']._serialized_start=15046 + _globals['_BUCKET_CORS']._serialized_end=15134 + _globals['_BUCKET_ENCRYPTION']._serialized_start=15136 + _globals['_BUCKET_ENCRYPTION']._serialized_end=15213 + _globals['_BUCKET_IAMCONFIG']._serialized_start=15216 + _globals['_BUCKET_IAMCONFIG']._serialized_end=15452 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_start=15362 + _globals['_BUCKET_IAMCONFIG_UNIFORMBUCKETLEVELACCESS']._serialized_end=15452 + _globals['_BUCKET_LIFECYCLE']._serialized_start=15455 + _globals['_BUCKET_LIFECYCLE']._serialized_end=16210 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_start=15525 + _globals['_BUCKET_LIFECYCLE_RULE']._serialized_end=16210 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_start=15669 + _globals['_BUCKET_LIFECYCLE_RULE_ACTION']._serialized_end=15714 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_start=15717 + _globals['_BUCKET_LIFECYCLE_RULE_CONDITION']._serialized_end=16210 + _globals['_BUCKET_LOGGING']._serialized_start=16212 + _globals['_BUCKET_LOGGING']._serialized_end=16268 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_start=16271 + _globals['_BUCKET_RETENTIONPOLICY']._serialized_end=16414 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_start=16417 + _globals['_BUCKET_SOFTDELETEPOLICY']._serialized_end=16594 + _globals['_BUCKET_VERSIONING']._serialized_start=16596 + _globals['_BUCKET_VERSIONING']._serialized_end=16625 + _globals['_BUCKET_WEBSITE']._serialized_start=16627 + _globals['_BUCKET_WEBSITE']._serialized_end=16686 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_start=16688 + _globals['_BUCKET_CUSTOMPLACEMENTCONFIG']._serialized_end=16735 + _globals['_BUCKET_AUTOCLASS']._serialized_start=16738 + _globals['_BUCKET_AUTOCLASS']._serialized_end=17005 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_start=17007 + _globals['_BUCKET_HIERARCHICALNAMESPACE']._serialized_end=17052 + _globals['_BUCKET_LABELSENTRY']._serialized_start=17054 + _globals['_BUCKET_LABELSENTRY']._serialized_end=17099 + _globals['_BUCKETACCESSCONTROL']._serialized_start=17192 + _globals['_BUCKETACCESSCONTROL']._serialized_end=17398 + _globals['_CHECKSUMMEDDATA']._serialized_start=17400 + _globals['_CHECKSUMMEDDATA']._serialized_end=17473 + _globals['_OBJECTCHECKSUMS']._serialized_start=17475 + _globals['_OBJECTCHECKSUMS']._serialized_end=17542 + _globals['_CUSTOMERENCRYPTION']._serialized_start=17544 + _globals['_CUSTOMERENCRYPTION']._serialized_end=17620 + _globals['_OBJECT']._serialized_start=17623 + _globals['_OBJECT']._serialized_end=19054 + _globals['_OBJECT_METADATAENTRY']._serialized_start=18926 + _globals['_OBJECT_METADATAENTRY']._serialized_end=18973 + _globals['_OBJECTACCESSCONTROL']._serialized_start=19057 + _globals['_OBJECTACCESSCONTROL']._serialized_end=19263 + _globals['_LISTOBJECTSRESPONSE']._serialized_start=19265 + _globals['_LISTOBJECTSRESPONSE']._serialized_end=19373 + _globals['_PROJECTTEAM']._serialized_start=19375 + _globals['_PROJECTTEAM']._serialized_end=19426 + _globals['_OWNER']._serialized_start=19428 + _globals['_OWNER']._serialized_end=19470 + _globals['_CONTENTRANGE']._serialized_start=19472 + _globals['_CONTENTRANGE']._serialized_end=19539 + _globals['_STORAGE']._serialized_start=19542 + _globals['_STORAGE']._serialized_end=23447 # @@protoc_insertion_point(module_scope) diff --git a/google/storage/v2/storage_pb2_grpc.py b/google/storage/v2/storage_pb2_grpc.py index a1c453b0..9ff5024c 100644 --- a/google/storage/v2/storage_pb2_grpc.py +++ b/google/storage/v2/storage_pb2_grpc.py @@ -187,6 +187,11 @@ def __init__(self, channel): request_serializer=google_dot_storage_dot_v2_dot_storage__pb2.QueryWriteStatusRequest.SerializeToString, response_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.QueryWriteStatusResponse.FromString, _registered_method=True) + self.MoveObject = channel.unary_unary( + '/google.storage.v2.Storage/MoveObject', + request_serializer=google_dot_storage_dot_v2_dot_storage__pb2.MoveObjectRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.Object.FromString, + _registered_method=True) class StorageServicer(object): @@ -295,12 +300,26 @@ def ComposeObject(self, request, context): raise NotImplementedError('Method not implemented!') def DeleteObject(self, request, context): - """Deletes an object and its metadata. - - Deletions are normally permanent when versioning is disabled or whenever - the generation parameter is used. However, if soft delete is enabled for - the bucket, deleted objects can be restored using RestoreObject until the - soft delete retention period has passed. + """Deletes an object and its metadata. Deletions are permanent if versioning + is not enabled for the bucket, or if the generation parameter is used, or + if [soft delete](https://cloud.google.com/storage/docs/soft-delete) is not + enabled for the bucket. + When this API is used to delete an object from a bucket that has soft + delete policy enabled, the object becomes soft deleted, and the + `softDeleteTime` and `hardDeleteTime` properties are set on the object. + This API cannot be used to permanently delete soft-deleted objects. + Soft-deleted objects are permanently deleted according to their + `hardDeleteTime`. + + You can use the [`RestoreObject`][google.storage.v2.Storage.RestoreObject] + API to restore soft-deleted objects until the soft delete retention period + has passed. + + **IAM Permissions**: + + Requires `storage.objects.delete` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on + the bucket. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -328,14 +347,27 @@ def CancelResumableWrite(self, request, context): raise NotImplementedError('Method not implemented!') def GetObject(self, request, context): - """Retrieves an object's metadata. + """Retrieves object metadata. + + **IAM Permissions**: + + Requires `storage.objects.get` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on + the bucket. To return object ACLs, the authenticated user must also have + the `storage.objects.getIamPolicy` permission. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ReadObject(self, request, context): - """Reads an object's data. + """Retrieves object data. + + **IAM Permissions**: + + Requires `storage.objects.get` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on + the bucket. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -409,12 +441,18 @@ def WriteObject(self, request_iterator, context): whether the service views the object as complete. Attempting to resume an already finalized object will result in an OK - status, with a WriteObjectResponse containing the finalized object's + status, with a `WriteObjectResponse` containing the finalized object's metadata. Alternatively, the BidiWriteObject operation may be used to write an object with controls over flushing and the ability to fetch the ability to determine the current persisted size. + + **IAM Permissions**: + + Requires `storage.objects.create` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on + the bucket. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -443,6 +481,13 @@ def BidiWriteObject(self, request_iterator, context): def ListObjects(self, request, context): """Retrieves a list of objects matching the criteria. + + **IAM Permissions**: + + The authenticated user requires `storage.objects.list` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) + to use this method. To return object ACLs, the authenticated user must also + have the `storage.objects.getIamPolicy` permission. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -457,33 +502,54 @@ def RewriteObject(self, request, context): raise NotImplementedError('Method not implemented!') def StartResumableWrite(self, request, context): - """Starts a resumable write. How long the write operation remains valid, and - what happens when the write operation becomes invalid, are - service-dependent. + """Starts a resumable write operation. This + method is part of the [Resumable + upload](https://cloud.google.com/storage/docs/resumable-uploads) feature. + This allows you to upload large objects in multiple chunks, which is more + resilient to network interruptions than a single upload. The validity + duration of the write operation, and the consequences of it becoming + invalid, are service-dependent. + + **IAM Permissions**: + + Requires `storage.objects.create` + [IAM permission](https://cloud.google.com/iam/docs/overview#permissions) on + the bucket. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def QueryWriteStatus(self, request, context): - """Determines the `persisted_size` for an object that is being written, which - can then be used as the `write_offset` for the next `Write()` call. - - If the object does not exist (i.e., the object has been deleted, or the - first `Write()` has not yet reached the service), this method returns the + """Determines the `persisted_size` of an object that is being written. This + method is part of the [resumable + upload](https://cloud.google.com/storage/docs/resumable-uploads) feature. + The returned value is the size of the object that has been persisted so + far. The value can be used as the `write_offset` for the next `Write()` + call. + + If the object does not exist, meaning if it was deleted, or the + first `Write()` has not yet reached the service, this method returns the error `NOT_FOUND`. - The client **may** call `QueryWriteStatus()` at any time to determine how - much data has been processed for this object. This is useful if the - client is buffering data and needs to know which data can be safely - evicted. For any sequence of `QueryWriteStatus()` calls for a given - object name, the sequence of returned `persisted_size` values will be + This method is useful for clients that buffer data and need to know which + data can be safely evicted. The client can call `QueryWriteStatus()` at any + time to determine how much data has been logged for this object. + For any sequence of `QueryWriteStatus()` calls for a given + object name, the sequence of returned `persisted_size` values are non-decreasing. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def MoveObject(self, request, context): + """Moves the source object to the destination object in the same bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_StorageServicer_to_server(servicer, server): rpc_method_handlers = { @@ -602,6 +668,11 @@ def add_StorageServicer_to_server(servicer, server): request_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.QueryWriteStatusRequest.FromString, response_serializer=google_dot_storage_dot_v2_dot_storage__pb2.QueryWriteStatusResponse.SerializeToString, ), + 'MoveObject': grpc.unary_unary_rpc_method_handler( + servicer.MoveObject, + request_deserializer=google_dot_storage_dot_v2_dot_storage__pb2.MoveObjectRequest.FromString, + response_serializer=google_dot_storage_dot_v2_dot_storage__pb2.Object.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( 'google.storage.v2.Storage', rpc_method_handlers) @@ -1254,3 +1325,30 @@ def QueryWriteStatus(request, timeout, metadata, _registered_method=True) + + @staticmethod + def MoveObject(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/google.storage.v2.Storage/MoveObject', + google_dot_storage_dot_v2_dot_storage__pb2.MoveObjectRequest.SerializeToString, + google_dot_storage_dot_v2_dot_storage__pb2.Object.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 3e810ecd..0e589d93 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -563,7 +563,7 @@ def process_read_range(range): read_end = len(blob.media) read_id = range.read_id - if start > read_end or range.read_limit < 0: + if start > read_end or range.read_length < 0: status_msg = self._pack_bidiread_error_details( range, grpc.StatusCode.OUT_OF_RANGE ) @@ -571,9 +571,8 @@ def process_read_range(range): context.abort_with_status(grpc_status) return - if range.read_limit > 0: - # read_limit is the maximum number of data bytes the server is allowed to return across all response messages with the same read_id. - read_end = min(read_end, start + range.read_limit) + if range.read_length > 0: + read_end = min(read_end, start + range.read_length) while start < read_end: end = min(start + size, read_end) @@ -582,7 +581,7 @@ def process_read_range(range): chunk = blob.media[start:end] read_range = { "read_offset": start, - "read_limit": range.read_limit, + "read_length": end - start, "read_id": read_id, } yield (chunk, range_end, read_range) @@ -638,7 +637,7 @@ def read_results(): if excess > 0: chunk = chunk[:returnable] range_end = False - read_range["read_limit"] -= excess + read_range["read_length"] -= excess returnable -= count yield response( storage_pb2.BidiReadObjectResponse( diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index 4fc052c3..abb1eb42 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -2134,10 +2134,10 @@ def test_bidi_read_object(self): # Test n ranges in 1 stream, where n=2. offset_1 = 0 - limit_1 = 2 * 1024 * 1024 + length_1 = 2 * 1024 * 1024 read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) offset_2 = 3 * 1024 * 1024 - limit_2 = 2 * 1024 * 1024 + length_2 = 2 * 1024 * 1024 read_id_2 = read_id_1 + 1 r1 = storage_pb2.BidiReadObjectRequest( @@ -2148,12 +2148,12 @@ def test_bidi_read_object(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_1, - read_limit=limit_1, + read_length=length_1, read_id=read_id_1, ), storage_pb2.ReadRange( read_offset=offset_2, - read_limit=limit_2, + read_length=length_2, read_id=read_id_2, ), ], @@ -2174,8 +2174,8 @@ def test_bidi_read_object(self): self.assertEqual(crc32c.crc32c(data.content), data.crc32c) returned_by_readid[read_id] += len(data.content) - self.assertEqual(returned_by_readid[read_id_1], offset_1 + limit_1) - self.assertEqual(returned_by_readid[read_id_2], offset_2 + limit_2) + self.assertEqual(returned_by_readid[read_id_1], offset_1 + length_1) + self.assertEqual(returned_by_readid[read_id_2], offset_2 + length_2) def test_bidi_read_object_not_found(self): # Test BidiReadObject with non-existent object. @@ -2239,7 +2239,7 @@ def test_bidi_read_object_generation_precondition_failed(self): # Test BidiReadObject with invalid object generation match precondition. invalid_generation_match = 0 offset_1 = 0 - limit_1 = 1024 + length_1 = 1024 read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) r1 = storage_pb2.BidiReadObjectRequest( read_object_spec=storage_pb2.BidiReadObjectSpec( @@ -2250,7 +2250,7 @@ def test_bidi_read_object_generation_precondition_failed(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_1, - read_limit=limit_1, + read_length=length_1, read_id=read_id_1, ), ], @@ -2285,7 +2285,7 @@ def test_bidi_read_object_interleaves_responses(self): def make_2_chunk_range(i): return storage_pb2.ReadRange( read_offset=2 * CHUNK * i, - read_limit=2 * CHUNK, + read_length=2 * CHUNK, read_id=i, ) @@ -2330,7 +2330,7 @@ def test_bidi_read_out_of_range_error(self): # Test out-of-range offset. offset_1 = 8 * 1024 * 1024 - limit_1 = 1024 + length_1 = 1024 read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) r1 = storage_pb2.BidiReadObjectRequest( read_object_spec=storage_pb2.BidiReadObjectSpec( @@ -2340,13 +2340,13 @@ def test_bidi_read_out_of_range_error(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_1, - read_limit=limit_1, + read_length=length_1, read_id=read_id_1, ), ], ) - # Test out-of-range with negative read limit. - limit_2 = -2048 + # Test out-of-range with negative read length. + length_2 = -2048 offset_2 = 10 read_id_2 = read_id_1 + 1 r2 = storage_pb2.BidiReadObjectRequest( @@ -2357,7 +2357,7 @@ def test_bidi_read_out_of_range_error(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_2, - read_limit=limit_2, + read_length=length_2, read_id=read_id_2, ), ], @@ -2389,7 +2389,7 @@ def test_bidi_read_one_out_of_range_one_in_range_error(self): # Test out-of-range offset. offset_1 = 8 * 1024 * 1024 - limit_1 = 1024 + length_1 = 1024 read_id_1 = int(datetime.datetime.now(datetime.timezone.utc).timestamp() * 1000) r1 = storage_pb2.BidiReadObjectRequest( read_object_spec=storage_pb2.BidiReadObjectSpec( @@ -2399,14 +2399,14 @@ def test_bidi_read_one_out_of_range_one_in_range_error(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_1, - read_limit=limit_1, + read_length=length_1, read_id=read_id_1, ), ], ) # Test in-range offset. offset_2 = 0 - limit_2 = 10 + length_2 = 10 read_id_2 = read_id_1 + 1 r2 = storage_pb2.BidiReadObjectRequest( read_object_spec=storage_pb2.BidiReadObjectSpec( @@ -2416,7 +2416,7 @@ def test_bidi_read_one_out_of_range_one_in_range_error(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_2, - read_limit=limit_2, + read_length=length_2, read_id=read_id_2, ), ], diff --git a/tests/test_testbench_retry.py b/tests/test_testbench_retry.py index 7c4f847b..77d854b7 100644 --- a/tests/test_testbench_retry.py +++ b/tests/test_testbench_retry.py @@ -1564,9 +1564,9 @@ def test_grpc_bidiread_retry_broken_stream(self): return_value=(("x-retry-test-id", create_rest.get("id")),) ) - # Test one range in stream with limit more than 256kb. + # Test one range in stream with length more than 256kb. offset_1 = 0 - limit_1 = 1 * 1024 * 1024 + length_1 = 1 * 1024 * 1024 read_id_1 = 1 r1 = storage_pb2.BidiReadObjectRequest( @@ -1577,7 +1577,7 @@ def test_grpc_bidiread_retry_broken_stream(self): read_ranges=[ storage_pb2.ReadRange( read_offset=offset_1, - read_limit=limit_1, + read_length=length_1, read_id=read_id_1, ), ], @@ -1628,7 +1628,7 @@ def test_grpc_bidiread_retry_broken_stream(self): self.assertEqual(len(odr.checksummed_data.content), EXPECTED_LEN) self.assertEqual(odr.read_range.read_id, read_id_1) self.assertEqual(odr.read_range.read_offset, offset_1) - self.assertEqual(odr.read_range.read_limit, offset_1 + EXPECTED_LEN) + self.assertEqual(odr.read_range.read_length, EXPECTED_LEN) # Because we requested 1 MiB, but only got back 256KiB self.assertFalse(odr.range_end) From 367b4f824b4ef799f5fae95627ab7d344d514b4e Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Mon, 6 Jan 2025 13:52:28 -0800 Subject: [PATCH 35/39] Revert "docs: how to merge from public upstream (#40)" This reverts commit e96974db6f64d2810d749deb0d8d8192ad544a93. --- README.md | 93 ++++++++++++------------------------------------------- 1 file changed, 19 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 5fe10070..ccfe5ca9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ is expected to be used by Storage library maintainers. - [Run the testbench](#run-the-testbench) - [Start the gRPC server](#start-the-gRPC-server) - [Check that the testbench is running](#check-that-the-testbench-is-running) + - [Updating Proto Files](#updating-proto-files) - [Force Failures](#force-failures) - [return-broken-stream](#return-broken-stream) - [return-corrupted-data](#return-corrupted-data) @@ -34,8 +35,6 @@ is expected to be used by Storage library maintainers. - [Delete a Retry Test resource](#delete-a-retry-test-resource) - [Causing a failure using x-retry-test-id header](#causing-a-failure-using-x-retry-test-id-header) - [Forced Failures Supported](#forced-failures-supported) - - [Merging from Upstream](#merging-from-upstream) - - [Updating Proto Files](#updating-proto-files) - [Releasing the testbench](#releasing-the-testbench) ## Issue Policy @@ -121,6 +120,24 @@ The response you get should be: `OK` Now you can use the testbench (while it's running) with the client libraries. +## Updating Proto Files + +From time to time you may need to update the files generated by protobuf and +gRPC. To do so, clone the [protos](https://github.com/googleapis/googleapis) and +run the grpc_tools generator: + +```shell +cd $HOME/storage-testbench +pip install --no-deps grpcio-tools +./update-protos.sh $PWD/.googleapis +``` + +Then commit the files generated in `google/**`: + +```shell +git commit -m"chore: update protos" google +``` + ## Force Failures You can force the following failures by using the `x-goog-emulator-instructions` header. @@ -259,78 +276,6 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 | redirect-send-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. | redirect-send-handle-and-token-T | [HTTP] Unsupported [GRPC] Testbench will fail the RPC with `ABORTED` and include appropriate redirection error details. -## How-to Guide: maintaining the pre-launch branch(es) - -### Merging from Upstream - -Clone a repository (you may already have one) that has both the public and -`*-prelaunch` repos as remotes. We choose a configuration that makes it really -hard to accidentally push prelaunch code to the public repo: - -```shell -git clone git@github.com:googleapis/storage-testbench.git -cd storage-testbench -git remote add prelaunch git@github.com:googleapis/storage-testbench-prelaunch.git -``` - -Update your clone to the latest versions: - -```shell -git fetch prelaunch -git fetch origin -``` - -Find out the latest commit from the public repo already present in the -`*-prelaunch` repo: - -```shell -A=$(git rev-parse prelaunch/upstream) -``` - -Find out the latest commit from the public repo main branch: - -```shell -B=$(git rev-parse origin/main) -``` - -Update the `upstream` branch on the `*-prelaunch` repository: - -```shell -git push prelaunch origin/main:upstream -``` - -You can use a separate workspace for the next steps: - -```shell -cd $HOME/ -git clone git@github.com:googleapis/storage-testbench-prelaunch.git -cd storage-testbench -git checkout pre-launch-acv2 -git checkout -b chore-merge-from-public-circa-$(date +%Y-%m-%d) -git cherry-pick ${A}..${B} -``` - -Send a PR and squash commit as usual. - - -## Updating Proto Files - -From time to time you may need to update the files generated by protobuf and -gRPC. To do so, clone the [protos](https://github.com/googleapis/googleapis) and -run the grpc_tools generator: - -```shell -cd $HOME/storage-testbench -pip install --no-deps grpcio-tools -./update-protos.sh $PWD/.googleapis -``` - -Then commit the files generated in `google/**`: - -```shell -git commit -m"chore: update protos" google -``` - ## Releasing the testbench The repository currently uses [Github Tags](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) From 2c0c2b712a8029f1c1f7d723be31952ef50986cc Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Mon, 6 Jan 2025 13:53:22 -0800 Subject: [PATCH 36/39] Revert "test: enable GCS bucket logs (#26)" This reverts commit cc704ab42cf5489703db9d77ecbbd4ac9e9a21b5. --- cloudbuild_prelaunch.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cloudbuild_prelaunch.yaml b/cloudbuild_prelaunch.yaml index 864fbd18..ed44005f 100644 --- a/cloudbuild_prelaunch.yaml +++ b/cloudbuild_prelaunch.yaml @@ -30,6 +30,5 @@ images: - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest -# If you do not set `logging` option, Cloud Build stores the -# logs in both Cloud Logging and Cloud Storage. -logsBucket: 'gs://gcs-sdk-cloud-builds-logs' +options: + logging: CLOUD_LOGGING_ONLY From 24f070d72770717bc96109d766c94ef093e68cb9 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Mon, 6 Jan 2025 13:58:47 -0800 Subject: [PATCH 37/39] Revert "build: update cloudbuild for private images (#23)" This reverts commit 86db6be456de03dbb55cf04d49febbf4939d454f. --- cloudbuild_prelaunch.yaml => cloudbuild.yaml | 26 +++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) rename cloudbuild_prelaunch.yaml => cloudbuild.yaml (51%) diff --git a/cloudbuild_prelaunch.yaml b/cloudbuild.yaml similarity index 51% rename from cloudbuild_prelaunch.yaml rename to cloudbuild.yaml index ed44005f..aa1018e7 100644 --- a/cloudbuild_prelaunch.yaml +++ b/cloudbuild.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,20 +15,16 @@ timeout: 7200s # 2 hours steps: - name: gcr.io/cloud-builders/docker - args: ["build", "-t", "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA", "."] + args: ["build", + "-t", "gcr.io/cloud-devrel-public-resources/storage-testbench:$TAG_NAME", + "-t", "gcr.io/cloud-devrel-public-resources/storage-testbench:latest", + "-t", "gcr.io/cloud-devrel-public-resources/storage-testbench:infrastructure-public-image-$SHORT_SHA", + "."] dir: . - id: storage-testbench-prelaunch-build - - name: gcr.io/cloud-builders/docker - args: - [ - "tag", - "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA", - "gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest", - ] + id: storage-testbench-build images: - - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:$SHORT_SHA - - gcr.io/gcs-sdk-cloud-builds/storage-testbench-prelaunch:latest - -options: - logging: CLOUD_LOGGING_ONLY + - gcr.io/cloud-devrel-public-resources/storage-testbench:$TAG_NAME + - gcr.io/cloud-devrel-public-resources/storage-testbench:latest + - gcr.io/cloud-devrel-public-resources/storage-testbench:infrastructure-public-image-$SHORT_SHA + \ No newline at end of file From 94028262be20f383597df228d0aabd5f5675a293 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Tue, 7 Jan 2025 10:35:36 -0800 Subject: [PATCH 38/39] Revert "feat: Only RAPID supports appendable objects. (#30)" This reverts commit 47c63fa7aeaccea2e66d86ca5fbf8f08a5cb75d9. --- gcs/upload.py | 5 ----- tests/test_grpc_server.py | 36 +++--------------------------------- 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/gcs/upload.py b/gcs/upload.py index 123cbe46..0239d884 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -358,11 +358,6 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): ).metadata upload = cls.__init_first_write_grpc(first_msg, bucket, context) if first_msg.write_object_spec.appendable: - if bucket.storage_class != "RAPID": - testbench.error.invalid( - f"Appendable object in {bucket.storage_class} storage class", - context, - ) is_appendable = True appendable_metadata_in_first_response = True blob = cls._insert_empty_appendable_object( diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index abb1eb42..c11c2025 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -1859,39 +1859,11 @@ def test_bidi_write_object_resumable(self): self.assertEqual(blob.name, "object-name") self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") - def test_bidi_write_object_appendable_unsupported(self): - # The code depends on `context.abort()` raising an exception. - context = self.mock_context() - context.abort.side_effect = grpc.RpcError() - req = storage_pb2.BidiWriteObjectRequest( - write_object_spec=storage_pb2.WriteObjectSpec( - resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/bucket-name" - ), - appendable=True, - ), - ) - with self.assertRaises(grpc.RpcError): - streamer = self.grpc.BidiWriteObject([req], context=context) - responses = list(streamer) - def test_bidi_write_object_appendable(self): # The code depends on `context.abort()` raising an exception. context = self.mock_context() context.abort.side_effect = grpc.RpcError() - # Only the RAPID storage class supports appendable objects at this time. - self.grpc.CreateBucket( - storage_pb2.CreateBucketRequest( - parent="projects/test-project", - bucket_id="rapid-bucket", - bucket=storage_pb2.Bucket( - storage_class="RAPID", - ), - ), - context, - ) - QUANTUM = 256 * 1024 media = TestGrpc._create_block(2 * QUANTUM + QUANTUM / 2).encode("utf-8") offset = 0 @@ -1899,7 +1871,7 @@ def test_bidi_write_object_appendable(self): r1 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/bucket-name" ), appendable=True, ), @@ -1927,9 +1899,7 @@ def test_bidi_write_object_appendable(self): # For appendable objects, we expect the object metadata in the first # response rather than the persisted_size. self.assertEqual(responses[0].resource.size, 2 * QUANTUM) - self.assertEqual( - responses[0].resource.bucket, "projects/_/buckets/rapid-bucket" - ) + self.assertEqual(responses[0].resource.bucket, "projects/_/buckets/bucket-name") self.assertEqual(responses[0].resource.name, "object-name") bucket = responses[0].resource.bucket @@ -1969,7 +1939,7 @@ def test_bidi_write_object_appendable(self): blob = responses[1].resource self.assertEqual(responses[1].resource.size, 2 * QUANTUM + QUANTUM / 2) self.assertEqual(blob.name, "object-name") - self.assertEqual(blob.bucket, "projects/_/buckets/rapid-bucket") + self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") def test_bidi_write_object_appendable_already_finalized(self): # The code depends on `context.abort()` raising an exception. From 8221b84be03f934458cdfb2b5225ffc17477c824 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Tue, 7 Jan 2025 10:48:59 -0800 Subject: [PATCH 39/39] update for public merge --- tests/test_grpc_server.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/tests/test_grpc_server.py b/tests/test_grpc_server.py index c11c2025..a084cf15 100755 --- a/tests/test_grpc_server.py +++ b/tests/test_grpc_server.py @@ -1946,21 +1946,18 @@ def test_bidi_write_object_appendable_already_finalized(self): context = self.mock_context() context.abort.side_effect = grpc.RpcError() - # Only the RAPID storage class supports appendable objects at this time. self.grpc.CreateBucket( storage_pb2.CreateBucketRequest( parent="projects/test-project", - bucket_id="rapid-bucket", - bucket=storage_pb2.Bucket( - storage_class="RAPID", - ), + bucket_id="test-bucket-name", + bucket=storage_pb2.Bucket(), ), context, ) r1 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/test-bucket-name" ), appendable=True, ), @@ -1974,7 +1971,7 @@ def test_bidi_write_object_appendable_already_finalized(self): r2 = storage_pb2.BidiWriteObjectRequest( append_object_spec=storage_pb2.AppendObjectSpec( - bucket="projects/_/buckets/rapid-bucket", + bucket="projects/_/buckets/test-bucket-name", object="object-name", generation=responses[0].resource.generation, write_handle=responses[0].write_handle, @@ -1993,21 +1990,18 @@ def test_bidi_write_object_appendable_live_generation_unfinalized(self): context = self.mock_context() context.abort.side_effect = grpc.RpcError() - # Only the RAPID storage class supports appendable objects at this time. self.grpc.CreateBucket( storage_pb2.CreateBucketRequest( parent="projects/test-project", - bucket_id="rapid-bucket", - bucket=storage_pb2.Bucket( - storage_class="RAPID", - ), + bucket_id="test-bucket-name", + bucket=storage_pb2.Bucket(), ), context, ) r1 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/test-bucket-name" ), appendable=True, ), @@ -2022,7 +2016,7 @@ def test_bidi_write_object_appendable_live_generation_unfinalized(self): r2 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/test-bucket-name" ), appendable=True, ), @@ -2042,21 +2036,18 @@ def test_bidi_write_object_appendable_live_generation_finalized(self): context = self.mock_context() context.abort.side_effect = grpc.RpcError() - # Only the RAPID storage class supports appendable objects at this time. self.grpc.CreateBucket( storage_pb2.CreateBucketRequest( parent="projects/test-project", - bucket_id="rapid-bucket", - bucket=storage_pb2.Bucket( - storage_class="RAPID", - ), + bucket_id="test-bucket-name", + bucket=storage_pb2.Bucket(), ), context, ) r1 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/test-bucket-name" ), appendable=True, ), @@ -2071,7 +2062,7 @@ def test_bidi_write_object_appendable_live_generation_finalized(self): r2 = storage_pb2.BidiWriteObjectRequest( write_object_spec=storage_pb2.WriteObjectSpec( resource=storage_pb2.Object( - name="object-name", bucket="projects/_/buckets/rapid-bucket" + name="object-name", bucket="projects/_/buckets/test-bucket-name" ), appendable=True, ),