From 6b5b90583c2421b605ef3a4c24d774a9b841b184 Mon Sep 17 00:00:00 2001 From: raj-prince Date: Tue, 17 Mar 2026 06:14:09 +0000 Subject: [PATCH 1/4] feat(control-client-stall): adding stall feature for control client --- STALL_VALIDATION.md | 156 ++ google/iam/v1/iam_policy_pb2.py | 14 - google/iam/v1/iam_policy_pb2_grpc.py | 14 - google/iam/v1/options_pb2.py | 14 - google/iam/v1/options_pb2_grpc.py | 14 - google/iam/v1/policy_pb2.py | 14 - google/iam/v1/policy_pb2_grpc.py | 14 - google/storage/control/__init__.py | 13 + google/storage/control/v2/__init__.py | 13 + .../storage/control/v2/storage_control_pb2.py | 418 ++++++ .../control/v2/storage_control_pb2_grpc.py | 1275 +++++++++++++++++ google/storage/v2/storage_pb2.py | 14 - google/storage/v2/storage_pb2_grpc.py | 14 - testbench/database.py | 63 +- testbench/grpc_server.py | 79 + tests/test_storage_control_stall.py | 195 +++ update-protos.sh | 1 + 17 files changed, 2212 insertions(+), 113 deletions(-) create mode 100644 STALL_VALIDATION.md create mode 100644 google/storage/control/__init__.py create mode 100644 google/storage/control/v2/__init__.py create mode 100644 google/storage/control/v2/storage_control_pb2.py create mode 100644 google/storage/control/v2/storage_control_pb2_grpc.py create mode 100644 tests/test_storage_control_stall.py diff --git a/STALL_VALIDATION.md b/STALL_VALIDATION.md new file mode 100644 index 00000000..c2727af6 --- /dev/null +++ b/STALL_VALIDATION.md @@ -0,0 +1,156 @@ +# Storage Control API Stall Implementation - Validation Guide + +## Overview + +This document describes how to validate the stall functionality for the Storage Control API that was implemented in this branch. + +## What Was Implemented + +1. **Protobuf Generation**: Added `google/storage/control/v2/storage_control.proto` to the proto generation pipeline +2. **Database Layer**: Added folder storage **capabilities** to `testbench/database.py` +3. **gRPC Service**: Implemented `StorageControlServicer` in `testbench/grpc_server.py` with stall support +4. **Stall Functionality**: Added `_apply_stall()` method that intercepts folder API calls and applies delays based on `x-goog-emulator-instructions` metadata + +## Stall Instructions Supported + +The implementation supports the following stall instructions via gRPC metadata header `x-goog-emulator-instructions`: + +- `stall-always`: Stalls for 10 seconds at the beginning of the request +- `stall-for-Ns`: Stalls for N seconds (e.g., `stall-for-3s` stalls for 3 seconds) + +## Supported Operations + +All Storage Control API folder operations support stall: +- `CreateFolder` +- `DeleteFolder` +- `GetFolder` +- `ListFolders` +- `RenameFolder` + +## Running the Tests + +### Prerequisites + +1. Ensure you're in a virtual environment: +```bash +source ../venv-storage-testbench/bin/activate +``` + +### Quick Validation (Non-Stall Test) + +Run this test to verify basic functionality (~1 second): +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_create_folder_no_stall -v +``` + +### Stall Functionality Tests + +Run these tests to verify stall functionality (each takes several seconds due to intentional delays): + +**Custom duration stall (3 seconds):** +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_create_folder_stall_custom_duration -v +``` + +**Delete with stall (2 seconds):** +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_delete_folder_stall -v +``` + +**Get with stall (5 seconds):** +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_get_folder_stall -v +``` + +**List with stall (4 seconds):** +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_list_folders_stall -v +``` + +**Rename with stall (6 seconds):** +```bash +python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_rename_folder_stall -v +``` + +### Full Test Suite + +Run all tests at once (takes ~30+ seconds): +```bash +python -m unittest tests.test_storage_control_stall -v +``` + +**Note:** The `test_create_folder_stall_always` test takes 10+ seconds as it uses the default stall duration. + +## Manual Testing with gRPC Client + +You can also test using a Python gRPC client: + +```python +import grpc +from google.storage.control.v2 import storage_control_pb2, storage_control_pb2_grpc +import time + +# Connect to testbench +channel = grpc.insecure_channel('localhost:9099') # Use actual gRPC port +stub = storage_control_pb2_grpc.StorageControlStub(channel) + +# Test with stall-for-5s instruction +metadata = [('x-goog-emulator-instructions', 'stall-for-5s')] +request = storage_control_pb2.CreateFolderRequest() +request.parent = "projects/_/buckets/test-bucket" +request.folder_id = "my-test-folder" + +start = time.time() +folder = stub.CreateFolder(request, metadata=metadata) +elapsed = time.time() - start + +print(f"Request took {elapsed:.2f} seconds") +print(f"Created folder: {folder.name}") +``` + +## Expected Test Results + +✅ **Success Criteria:** +- Non-stall tests complete in < 1 second +- `stall-always` tests take >= 10 seconds +- `stall-for-Ns` tests take >= N seconds (within 1-2 seconds tolerance) +- Folder operations (create, delete, get, list, rename) all work correctly +- Stall applies before the operation executes + +## Integration with Existing Tests + +The implementation doesn't affect existing Storage API tests. You can verify this by running: + +```bash +python -m unittest discover -s tests/ -p "test_grpc_server.py" -v +``` + +This should pass without any issues. + +## Files Modified + +- `update-protos.sh`: Added storage_control.proto to the generation list +- `testbench/database.py`: Added folder storage methods +- `testbench/grpc_server.py`: Added StorageControlServicer with stall support +- `tests/test_storage_control_stall.py`: Comprehensive test suite for stall functionality +- `google/storage/control/v2/`: Generated protobuf files (storage_control_pb2.py, storage_control_pb2_grpc.py) + +## Troubleshooting + +**Issue: ImportError for storage_control_pb2** +- Solution: Regenerate protobuf files: `source ../venv-storage-testbench/bin/activate && bash update-protos.sh` + +**Issue: Tests timing out** +- Solution: Increase timeout values in test runner, stall tests are intentionally slow + +**Issue: "Protocol message Folder has no field 'bucket'"** +- Solution: This was fixed - Folder only has fields: name, metageneration, create_time, update_time, pending_rename_info + +## Architecture Notes + +The stall implementation uses `time.sleep()` which blocks the current thread. This is appropriate for: +- Testing timeout handling +- Simulating slow backends +- Reproducing transient network conditions + +The implementation extracts stall instructions from gRPC metadata via `testbench.common.extract_instruction()`, which checks for the `x-goog-emulator-instructions` header in the invocation metadata. diff --git a/google/iam/v1/iam_policy_pb2.py b/google/iam/v1/iam_policy_pb2.py index 03eda47c..a294d174 100644 --- a/google/iam/v1/iam_policy_pb2.py +++ b/google/iam/v1/iam_policy_pb2.py @@ -1,18 +1,4 @@ # -*- coding: utf-8 -*- -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: google/iam/v1/iam_policy.proto diff --git a/google/iam/v1/iam_policy_pb2_grpc.py b/google/iam/v1/iam_policy_pb2_grpc.py index 28ed5951..0d2513db 100644 --- a/google/iam/v1/iam_policy_pb2_grpc.py +++ b/google/iam/v1/iam_policy_pb2_grpc.py @@ -1,18 +1,4 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Client and server classes corresponding to protobuf-defined services.""" import grpc import warnings diff --git a/google/iam/v1/options_pb2.py b/google/iam/v1/options_pb2.py index 75e2a2b3..65739b0d 100644 --- a/google/iam/v1/options_pb2.py +++ b/google/iam/v1/options_pb2.py @@ -1,18 +1,4 @@ # -*- coding: utf-8 -*- -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: google/iam/v1/options.proto diff --git a/google/iam/v1/options_pb2_grpc.py b/google/iam/v1/options_pb2_grpc.py index baae5aa9..8c96ff94 100644 --- a/google/iam/v1/options_pb2_grpc.py +++ b/google/iam/v1/options_pb2_grpc.py @@ -1,18 +1,4 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Client and server classes corresponding to protobuf-defined services.""" import grpc import warnings diff --git a/google/iam/v1/policy_pb2.py b/google/iam/v1/policy_pb2.py index 2c976271..83cee4c1 100644 --- a/google/iam/v1/policy_pb2.py +++ b/google/iam/v1/policy_pb2.py @@ -1,18 +1,4 @@ # -*- coding: utf-8 -*- -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: google/iam/v1/policy.proto diff --git a/google/iam/v1/policy_pb2_grpc.py b/google/iam/v1/policy_pb2_grpc.py index af0dbb7f..b9faf955 100644 --- a/google/iam/v1/policy_pb2_grpc.py +++ b/google/iam/v1/policy_pb2_grpc.py @@ -1,18 +1,4 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Client and server classes corresponding to protobuf-defined services.""" import grpc import warnings diff --git a/google/storage/control/__init__.py b/google/storage/control/__init__.py new file mode 100644 index 00000000..c6334245 --- /dev/null +++ b/google/storage/control/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/google/storage/control/v2/__init__.py b/google/storage/control/v2/__init__.py new file mode 100644 index 00000000..c6334245 --- /dev/null +++ b/google/storage/control/v2/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/google/storage/control/v2/storage_control_pb2.py b/google/storage/control/v2/storage_control_pb2.py new file mode 100644 index 00000000..5f9bc472 --- /dev/null +++ b/google/storage/control/v2/storage_control_pb2.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: google/storage/control/v2/storage_control.proto +# Protobuf Python Version: 5.29.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 29, + 0, + '', + 'google/storage/control/v2/storage_control.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from google.api import client_pb2 as google_dot_api_dot_client__pb2 +from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 +from google.api import field_info_pb2 as google_dot_api_dot_field__info__pb2 +from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 +from google.api import routing_pb2 as google_dot_api_dot_routing__pb2 +from google.iam.v1 import iam_policy_pb2 as google_dot_iam_dot_v1_dot_iam__policy__pb2 +from google.iam.v1 import policy_pb2 as google_dot_iam_dot_v1_dot_policy__pb2 +from google.longrunning import operations_pb2 as google_dot_longrunning_dot_operations__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +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 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n/google/storage/control/v2/storage_control.proto\x12\x19google.storage.control.v2\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/api/field_info.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#google/longrunning/operations.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"+\n\x11PendingRenameInfo\x12\x16\n\toperation\x18\x01 \x01(\tB\x03\xe0\x41\x03\"\xe2\x02\n\x06\x46older\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08\x12\x1b\n\x0emetageneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x03\x12\x34\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12N\n\x13pending_rename_info\x18\x07 \x01(\x0b\x32,.google.storage.control.v2.PendingRenameInfoB\x03\xe0\x41\x03:l\xea\x41i\n\x1dstorage.googleapis.com/Folder\x12\x37projects/{project}/buckets/{bucket}/folders/{folder=**}*\x07\x66olders2\x06\x66older\"\xf4\x01\n\x10GetFolderRequest\x12\x33\n\x04name\x18\x06 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Folder\x12$\n\x17if_metageneration_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\nrequest_id\x18\x05 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xd5\x01\n\x13\x43reateFolderRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Folder\x12\x36\n\x06\x66older\x18\x02 \x01(\x0b\x32!.google.storage.control.v2.FolderB\x03\xe0\x41\x02\x12\x16\n\tfolder_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x16\n\trecursive\x18\x04 \x01(\x08\x42\x03\xe0\x41\x01\x12\x1f\n\nrequest_id\x18\x05 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xf7\x01\n\x13\x44\x65leteFolderRequest\x12\x33\n\x04name\x18\x06 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Folder\x12$\n\x17if_metageneration_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\nrequest_id\x18\x05 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x8c\x02\n\x12ListFoldersRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\x12\x1dstorage.googleapis.com/Folder\x12\x16\n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01\x12\x17\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01\x12\x13\n\x06prefix\x18\x04 \x01(\tB\x03\xe0\x41\x01\x12\x16\n\tdelimiter\x18\x08 \x01(\tB\x03\xe0\x41\x01\x12 \n\x13lexicographic_start\x18\x06 \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11lexicographic_end\x18\x07 \x01(\tB\x03\xe0\x41\x01\x12\x1f\n\nrequest_id\x18\t \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"b\n\x13ListFoldersResponse\x12\x32\n\x07\x66olders\x18\x01 \x03(\x0b\x32!.google.storage.control.v2.Folder\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x9b\x02\n\x13RenameFolderRequest\x12\x33\n\x04name\x18\x07 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Folder\x12\"\n\x15\x64\x65stination_folder_id\x18\x08 \x01(\tB\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\x1f\n\nrequest_id\x18\x06 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x8a\x02\n\x1c\x44\x65leteFolderRecursiveRequest\x12\x33\n\x04name\x18\x01 \x01(\tB%\xe0\x41\x02\xfa\x41\x1f\n\x1dstorage.googleapis.com/Folder\x12)\n\x17if_metageneration_match\x18\x02 \x01(\x03\x42\x03\xe0\x41\x01H\x00\x88\x01\x01\x12-\n\x1bif_metageneration_not_match\x18\x03 \x01(\x03\x42\x03\xe0\x41\x01H\x01\x88\x01\x01\x12\x1f\n\nrequest_id\x18\x04 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\x9a\x02\n\"CommonLongRunningOperationMetadata\x12\x34\n\x0b\x63reate_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x31\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x11\n\x04type\x18\x04 \x01(\tB\x03\xe0\x41\x03\x12#\n\x16requested_cancellation\x18\x05 \x01(\x08\x42\x03\xe0\x41\x03\x12\x1d\n\x10progress_percent\x18\x06 \x01(\x05\x42\x03\xe0\x41\x03\"\xa7\x01\n\x14RenameFolderMetadata\x12V\n\x0f\x63ommon_metadata\x18\x01 \x01(\x0b\x32=.google.storage.control.v2.CommonLongRunningOperationMetadata\x12\x18\n\x10source_folder_id\x18\x02 \x01(\t\x12\x1d\n\x15\x64\x65stination_folder_id\x18\x03 \x01(\t\"\x8a\x01\n\x1d\x44\x65leteFolderRecursiveMetadata\x12V\n\x0f\x63ommon_metadata\x18\x01 \x01(\x0b\x32=.google.storage.control.v2.CommonLongRunningOperationMetadata\x12\x11\n\tfolder_id\x18\x02 \x01(\t\"\xf8\x03\n\rStorageLayout\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x03\x12\x15\n\x08location\x18\x02 \x01(\tB\x03\xe0\x41\x03\x12\x1a\n\rlocation_type\x18\x03 \x01(\tB\x03\xe0\x41\x03\x12\x64\n\x17\x63ustom_placement_config\x18\x04 \x01(\x0b\x32>.google.storage.control.v2.StorageLayout.CustomPlacementConfigB\x03\xe0\x41\x03\x12\x63\n\x16hierarchical_namespace\x18\x05 \x01(\x0b\x32>.google.storage.control.v2.StorageLayout.HierarchicalNamespaceB\x03\xe0\x41\x03\x1a/\n\x15\x43ustomPlacementConfig\x12\x16\n\x0e\x64\x61ta_locations\x18\x01 \x03(\t\x1a(\n\x15HierarchicalNamespace\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08:{\xea\x41x\n$storage.googleapis.com/StorageLayout\x12\x31projects/{project}/buckets/{bucket}/storageLayout*\x0estorageLayouts2\rstorageLayout\"\x86\x01\n\x17GetStorageLayoutRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/StorageLayout\x12\x0e\n\x06prefix\x18\x02 \x01(\t\x12\x1f\n\nrequest_id\x18\x03 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xbf\x02\n\rManagedFolder\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08\x12\x1b\n\x0emetageneration\x18\x03 \x01(\x03\x42\x03\xe0\x41\x03\x12\x34\n\x0b\x63reate_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x34\n\x0bupdate_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03:\x91\x01\xea\x41\x8d\x01\n$storage.googleapis.com/ManagedFolder\x12\x46projects/{project}/buckets/{bucket}/managedFolders/{managed_folder=**}*\x0emanagedFolders2\rmanagedFolder\"\x82\x02\n\x17GetManagedFolderRequest\x12:\n\x04name\x18\x06 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/ManagedFolder\x12$\n\x17if_metageneration_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x1f\n\nrequest_id\x18\x05 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xe2\x01\n\x1a\x43reateManagedFolderRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$storage.googleapis.com/ManagedFolder\x12\x45\n\x0emanaged_folder\x18\x02 \x01(\x0b\x32(.google.storage.control.v2.ManagedFolderB\x03\xe0\x41\x02\x12\x1e\n\x11managed_folder_id\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x04 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\x9e\x02\n\x1a\x44\x65leteManagedFolderRequest\x12:\n\x04name\x18\x07 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/ManagedFolder\x12$\n\x17if_metageneration_match\x18\x03 \x01(\x03H\x00\x88\x01\x01\x12(\n\x1bif_metageneration_not_match\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x17\n\x0f\x61llow_non_empty\x18\x05 \x01(\x08\x12\x1f\n\nrequest_id\x18\x06 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\x42\x1a\n\x18_if_metageneration_matchB\x1e\n\x1c_if_metageneration_not_match\"\xc0\x01\n\x19ListManagedFoldersRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$storage.googleapis.com/ManagedFolder\x12\x16\n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01\x12\x17\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01\x12\x13\n\x06prefix\x18\x04 \x01(\tB\x03\xe0\x41\x01\x12\x1f\n\nrequest_id\x18\x05 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"x\n\x1aListManagedFoldersResponse\x12\x41\n\x0fmanaged_folders\x18\x01 \x03(\x0b\x32(.google.storage.control.v2.ManagedFolder\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xb0\x02\n\x1b\x43reateAnywhereCacheMetadata\x12V\n\x0f\x63ommon_metadata\x18\x01 \x01(\x0b\x32=.google.storage.control.v2.CommonLongRunningOperationMetadata\x12\x1e\n\x11\x61nywhere_cache_id\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x11\n\x04zone\x18\x06 \x01(\tH\x01\x88\x01\x01\x12+\n\x03ttl\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationH\x02\x88\x01\x01\x12\x1d\n\x10\x61\x64mission_policy\x18\x05 \x01(\tH\x03\x88\x01\x01\x42\x14\n\x12_anywhere_cache_idB\x07\n\x05_zoneB\x06\n\x04_ttlB\x13\n\x11_admission_policy\"\xb0\x02\n\x1bUpdateAnywhereCacheMetadata\x12V\n\x0f\x63ommon_metadata\x18\x01 \x01(\x0b\x32=.google.storage.control.v2.CommonLongRunningOperationMetadata\x12\x1e\n\x11\x61nywhere_cache_id\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x11\n\x04zone\x18\x05 \x01(\tH\x01\x88\x01\x01\x12+\n\x03ttl\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationH\x02\x88\x01\x01\x12\x1d\n\x10\x61\x64mission_policy\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x14\n\x12_anywhere_cache_idB\x07\n\x05_zoneB\x06\n\x04_ttlB\x13\n\x11_admission_policy\"\xa5\x03\n\rAnywhereCache\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x05\x12\x11\n\x04zone\x18\n \x01(\tB\x03\xe0\x41\x05\x12&\n\x03ttl\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x18\n\x10\x61\x64mission_policy\x18\t \x01(\t\x12\x12\n\x05state\x18\x05 \x01(\tB\x03\xe0\x41\x03\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\x1b\n\x0epending_update\x18\x08 \x01(\x08\x42\x03\xe0\x41\x03:\x8e\x01\xea\x41\x8a\x01\n$storage.googleapis.com/AnywhereCache\x12\x43projects/{project}/buckets/{bucket}/anywhereCaches/{anywhere_cache}*\x0e\x61nywhereCaches2\ranywhereCache\"\xc2\x01\n\x1a\x43reateAnywhereCacheRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$storage.googleapis.com/AnywhereCache\x12\x45\n\x0e\x61nywhere_cache\x18\x03 \x01(\x0b\x32(.google.storage.control.v2.AnywhereCacheB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x04 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xba\x01\n\x1aUpdateAnywhereCacheRequest\x12\x45\n\x0e\x61nywhere_cache\x18\x01 \x01(\x0b\x32(.google.storage.control.v2.AnywhereCacheB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x03 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"z\n\x1b\x44isableAnywhereCacheRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/AnywhereCache\x12\x1f\n\nrequest_id\x18\x02 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"x\n\x19PauseAnywhereCacheRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/AnywhereCache\x12\x1f\n\nrequest_id\x18\x02 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"y\n\x1aResumeAnywhereCacheRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/AnywhereCache\x12\x1f\n\nrequest_id\x18\x02 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"v\n\x17GetAnywhereCacheRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$storage.googleapis.com/AnywhereCache\x12\x1f\n\nrequest_id\x18\x02 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xa1\x01\n\x19ListAnywhereCachesRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$storage.googleapis.com/AnywhereCache\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\x12\x1f\n\nrequest_id\x18\x04 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"x\n\x1aListAnywhereCachesResponse\x12\x41\n\x0f\x61nywhere_caches\x18\x01 \x03(\x0b\x32(.google.storage.control.v2.AnywhereCache\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\x8e\x0e\n\x12IntelligenceConfig\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08\x12X\n\x0e\x65\x64ition_config\x18\x02 \x01(\x0e\x32;.google.storage.control.v2.IntelligenceConfig.EditionConfigB\x03\xe0\x41\x01\x12\x34\n\x0bupdate_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12I\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x34.google.storage.control.v2.IntelligenceConfig.FilterB\x03\xe0\x41\x01\x12u\n\x1d\x65\x66\x66\x65\x63tive_intelligence_config\x18\x05 \x01(\x0b\x32I.google.storage.control.v2.IntelligenceConfig.EffectiveIntelligenceConfigB\x03\xe0\x41\x03\x12O\n\x0ctrial_config\x18\x07 \x01(\x0b\x32\x39.google.storage.control.v2.IntelligenceConfig.TrialConfig\x1a\xfc\x04\n\x06\x46ilter\x12v\n included_cloud_storage_locations\x18\x01 \x01(\x0b\x32J.google.storage.control.v2.IntelligenceConfig.Filter.CloudStorageLocationsH\x00\x12v\n excluded_cloud_storage_locations\x18\x02 \x01(\x0b\x32J.google.storage.control.v2.IntelligenceConfig.Filter.CloudStorageLocationsH\x00\x12r\n\x1eincluded_cloud_storage_buckets\x18\x03 \x01(\x0b\x32H.google.storage.control.v2.IntelligenceConfig.Filter.CloudStorageBucketsH\x01\x12r\n\x1e\x65xcluded_cloud_storage_buckets\x18\x04 \x01(\x0b\x32H.google.storage.control.v2.IntelligenceConfig.Filter.CloudStorageBucketsH\x01\x1a/\n\x15\x43loudStorageLocations\x12\x16\n\tlocations\x18\x01 \x03(\tB\x03\xe0\x41\x01\x1a\x35\n\x13\x43loudStorageBuckets\x12\x1e\n\x11\x62ucket_id_regexes\x18\x01 \x03(\tB\x03\xe0\x41\x01\x42\x19\n\x17\x63loud_storage_locationsB\x17\n\x15\x63loud_storage_buckets\x1a\x8a\x02\n\x1b\x45\x66\x66\x65\x63tiveIntelligenceConfig\x12z\n\x11\x65\x66\x66\x65\x63tive_edition\x18\x01 \x01(\x0e\x32Z.google.storage.control.v2.IntelligenceConfig.EffectiveIntelligenceConfig.EffectiveEditionB\x03\xe0\x41\x03\x12 \n\x13intelligence_config\x18\x02 \x01(\tB\x03\xe0\x41\x03\"M\n\x10\x45\x66\x66\x65\x63tiveEdition\x12!\n\x1d\x45\x46\x46\x45\x43TIVE_EDITION_UNSPECIFIED\x10\x00\x12\x08\n\x04NONE\x10\x01\x12\x0c\n\x08STANDARD\x10\x02\x1a\x43\n\x0bTrialConfig\x12\x34\n\x0b\x65xpire_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\"c\n\rEditionConfig\x12\x1e\n\x1a\x45\x44ITION_CONFIG_UNSPECIFIED\x10\x00\x12\x0b\n\x07INHERIT\x10\x01\x12\x0c\n\x08\x44ISABLED\x10\x02\x12\x0c\n\x08STANDARD\x10\x03\x12\t\n\x05TRIAL\x10\x05:\x8b\x02\xea\x41\x87\x02\n)storage.googleapis.com/IntelligenceConfig\x12\x38\x66olders/{folder}/locations/{location}/intelligenceConfig\x12;organizations/{org}/locations/{location}/intelligenceConfig\x12:projects/{project}/locations/{location}/intelligenceConfig*\x13intelligenceConfigs2\x12intelligenceConfig\"\xd5\x01\n+UpdateOrganizationIntelligenceConfigRequest\x12O\n\x13intelligence_config\x18\x01 \x01(\x0b\x32-.google.storage.control.v2.IntelligenceConfigB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x03 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xcf\x01\n%UpdateFolderIntelligenceConfigRequest\x12O\n\x13intelligence_config\x18\x01 \x01(\x0b\x32-.google.storage.control.v2.IntelligenceConfigB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x03 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"\xd0\x01\n&UpdateProjectIntelligenceConfigRequest\x12O\n\x13intelligence_config\x18\x01 \x01(\x0b\x32-.google.storage.control.v2.IntelligenceConfigB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x02\x12\x1f\n\nrequest_id\x18\x03 \x01(\tB\x0b\xe0\x41\x01\xe2\x8c\xcf\xd7\x08\x02\x08\x01\"k\n(GetOrganizationIntelligenceConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/IntelligenceConfig\"e\n\"GetFolderIntelligenceConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/IntelligenceConfig\"f\n#GetProjectIntelligenceConfigRequest\x12?\n\x04name\x18\x01 \x01(\tB1\xe0\x41\x02\xfa\x41+\n)storage.googleapis.com/IntelligenceConfig2\xd2,\n\x0eStorageControl\x12\x9a\x01\n\x0c\x43reateFolder\x12..google.storage.control.v2.CreateFolderRequest\x1a!.google.storage.control.v2.Folder\"7\xda\x41\x17parent,folder,folder_id\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x8f\x01\n\x0c\x44\x65leteFolder\x12..google.storage.control.v2.DeleteFolderRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\x94\x01\n\tGetFolder\x12+.google.storage.control.v2.GetFolderRequest\x1a!.google.storage.control.v2.Folder\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\x94\x01\n\x0bListFolders\x12-.google.storage.control.v2.ListFoldersRequest\x1a..google.storage.control.v2.ListFoldersResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xcd\x01\n\x0cRenameFolder\x12..google.storage.control.v2.RenameFolderRequest\x1a\x1d.google.longrunning.Operation\"n\xca\x41\x1e\n\x06\x46older\x12\x14RenameFolderMetadata\xda\x41\x1aname,destination_folder_id\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xe1\x01\n\x15\x44\x65leteFolderRecursive\x12\x37.google.storage.control.v2.DeleteFolderRecursiveRequest\x1a\x1d.google.longrunning.Operation\"p\xca\x41\x36\n\x15google.protobuf.Empty\x12\x1d\x44\x65leteFolderRecursiveMetadata\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa9\x01\n\x10GetStorageLayout\x12\x32.google.storage.control.v2.GetStorageLayoutRequest\x1a(.google.storage.control.v2.StorageLayout\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xbf\x01\n\x13\x43reateManagedFolder\x12\x35.google.storage.control.v2.CreateManagedFolderRequest\x1a(.google.storage.control.v2.ManagedFolder\"G\xda\x41\'parent,managed_folder,managed_folder_id\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\x9d\x01\n\x13\x44\x65leteManagedFolder\x12\x35.google.storage.control.v2.DeleteManagedFolderRequest\x1a\x16.google.protobuf.Empty\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa9\x01\n\x10GetManagedFolder\x12\x32.google.storage.control.v2.GetManagedFolderRequest\x1a(.google.storage.control.v2.ManagedFolder\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa9\x01\n\x12ListManagedFolders\x12\x34.google.storage.control.v2.ListManagedFoldersRequest\x1a\x35.google.storage.control.v2.ListManagedFoldersResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xd1\x01\n\x13\x43reateAnywhereCache\x12\x35.google.storage.control.v2.CreateAnywhereCacheRequest\x1a\x1d.google.longrunning.Operation\"d\xca\x41,\n\rAnywhereCache\x12\x1b\x43reateAnywhereCacheMetadata\xda\x41\x15parent,anywhere_cache\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xf9\x01\n\x13UpdateAnywhereCache\x12\x35.google.storage.control.v2.UpdateAnywhereCacheRequest\x1a\x1d.google.longrunning.Operation\"\x8b\x01\xca\x41,\n\rAnywhereCache\x12\x1bUpdateAnywhereCacheMetadata\xda\x41\x1a\x61nywhere_cache,update_mask\x8a\xd3\xe4\x93\x02\x39\x12\x37\n\x13\x61nywhere_cache.name\x12 {bucket=projects/*/buckets/*}/**\x12\xb1\x01\n\x14\x44isableAnywhereCache\x12\x36.google.storage.control.v2.DisableAnywhereCacheRequest\x1a(.google.storage.control.v2.AnywhereCache\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xad\x01\n\x12PauseAnywhereCache\x12\x34.google.storage.control.v2.PauseAnywhereCacheRequest\x1a(.google.storage.control.v2.AnywhereCache\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xaf\x01\n\x13ResumeAnywhereCache\x12\x35.google.storage.control.v2.ResumeAnywhereCacheRequest\x1a(.google.storage.control.v2.AnywhereCache\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa9\x01\n\x10GetAnywhereCache\x12\x32.google.storage.control.v2.GetAnywhereCacheRequest\x1a(.google.storage.control.v2.AnywhereCache\"7\xda\x41\x04name\x8a\xd3\xe4\x93\x02*\x12(\n\x04name\x12 {bucket=projects/*/buckets/*}/**\x12\xa9\x01\n\x12ListAnywhereCaches\x12\x34.google.storage.control.v2.ListAnywhereCachesRequest\x1a\x35.google.storage.control.v2.ListAnywhereCachesResponse\"&\xda\x41\x06parent\x8a\xd3\xe4\x93\x02\x17\x12\x15\n\x06parent\x12\x0b{bucket=**}\x12\xd2\x01\n\x1cGetProjectIntelligenceConfig\x12>.google.storage.control.v2.GetProjectIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"C\xda\x41\x04name\x82\xd3\xe4\x93\x02\x36\x12\x34/v2/{name=projects/*/locations/*/intelligenceConfig}\x12\x9d\x02\n\x1fUpdateProjectIntelligenceConfig\x12\x41.google.storage.control.v2.UpdateProjectIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"\x87\x01\xda\x41\x1fintelligence_config,update_mask\x82\xd3\xe4\x93\x02_2H/v2/{intelligence_config.name=projects/*/locations/*/intelligenceConfig}:\x13intelligence_config\x12\xcf\x01\n\x1bGetFolderIntelligenceConfig\x12=.google.storage.control.v2.GetFolderIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"B\xda\x41\x04name\x82\xd3\xe4\x93\x02\x35\x12\x33/v2/{name=folders/*/locations/*/intelligenceConfig}\x12\x9a\x02\n\x1eUpdateFolderIntelligenceConfig\x12@.google.storage.control.v2.UpdateFolderIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"\x86\x01\xda\x41\x1fintelligence_config,update_mask\x82\xd3\xe4\x93\x02^2G/v2/{intelligence_config.name=folders/*/locations/*/intelligenceConfig}:\x13intelligence_config\x12\xe1\x01\n!GetOrganizationIntelligenceConfig\x12\x43.google.storage.control.v2.GetOrganizationIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"H\xda\x41\x04name\x82\xd3\xe4\x93\x02;\x12\x39/v2/{name=organizations/*/locations/*/intelligenceConfig}\x12\xac\x02\n$UpdateOrganizationIntelligenceConfig\x12\x46.google.storage.control.v2.UpdateOrganizationIntelligenceConfigRequest\x1a-.google.storage.control.v2.IntelligenceConfig\"\x8c\x01\xda\x41\x1fintelligence_config,update_mask\x82\xd3\xe4\x93\x02\x64\x32M/v2/{intelligence_config.name=organizations/*/locations/*/intelligenceConfig}:\x13intelligence_config\x12\xa3\x01\n\x0cGetIamPolicy\x12\".google.iam.v1.GetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"X\xda\x41\x08resource\x8a\xd3\xe4\x93\x02G\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12,\n\x08resource\x12 {bucket=projects/*/buckets/*}/**\x12\xaa\x01\n\x0cSetIamPolicy\x12\".google.iam.v1.SetIamPolicyRequest\x1a\x15.google.iam.v1.Policy\"_\xda\x41\x0fresource,policy\x8a\xd3\xe4\x93\x02G\x12\x17\n\x08resource\x12\x0b{bucket=**}\x12,\n\x08resource\x12 {bucket=projects/*/buckets/*}/**\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/**\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\xa6\x02\n\x1d\x63om.google.storage.control.v2B\x13StorageControlProtoP\x01Z=cloud.google.com/go/storage/control/apiv2/controlpb;controlpb\xaa\x02\x1fGoogle.Cloud.Storage.Control.V2\xca\x02\x1fGoogle\\Cloud\\Storage\\Control\\V2\xea\x02#Google::Cloud::Storage::Control::V2\xea\x41\x44\n\x1dstorage.googleapis.com/Bucket\x12#projects/{project}/buckets/{bucket}b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'google.storage.control.v2.storage_control_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\035com.google.storage.control.v2B\023StorageControlProtoP\001Z=cloud.google.com/go/storage/control/apiv2/controlpb;controlpb\252\002\037Google.Cloud.Storage.Control.V2\312\002\037Google\\Cloud\\Storage\\Control\\V2\352\002#Google::Cloud::Storage::Control::V2\352AD\n\035storage.googleapis.com/Bucket\022#projects/{project}/buckets/{bucket}' + _globals['_PENDINGRENAMEINFO'].fields_by_name['operation']._loaded_options = None + _globals['_PENDINGRENAMEINFO'].fields_by_name['operation']._serialized_options = b'\340A\003' + _globals['_FOLDER'].fields_by_name['name']._loaded_options = None + _globals['_FOLDER'].fields_by_name['name']._serialized_options = b'\340A\010' + _globals['_FOLDER'].fields_by_name['metageneration']._loaded_options = None + _globals['_FOLDER'].fields_by_name['metageneration']._serialized_options = b'\340A\003' + _globals['_FOLDER'].fields_by_name['create_time']._loaded_options = None + _globals['_FOLDER'].fields_by_name['create_time']._serialized_options = b'\340A\003' + _globals['_FOLDER'].fields_by_name['update_time']._loaded_options = None + _globals['_FOLDER'].fields_by_name['update_time']._serialized_options = b'\340A\003' + _globals['_FOLDER'].fields_by_name['pending_rename_info']._loaded_options = None + _globals['_FOLDER'].fields_by_name['pending_rename_info']._serialized_options = b'\340A\003' + _globals['_FOLDER']._loaded_options = None + _globals['_FOLDER']._serialized_options = b'\352Ai\n\035storage.googleapis.com/Folder\0227projects/{project}/buckets/{bucket}/folders/{folder=**}*\007folders2\006folder' + _globals['_GETFOLDERREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETFOLDERREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Folder' + _globals['_GETFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_GETFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_CREATEFOLDERREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_CREATEFOLDERREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A\037\022\035storage.googleapis.com/Folder' + _globals['_CREATEFOLDERREQUEST'].fields_by_name['folder']._loaded_options = None + _globals['_CREATEFOLDERREQUEST'].fields_by_name['folder']._serialized_options = b'\340A\002' + _globals['_CREATEFOLDERREQUEST'].fields_by_name['folder_id']._loaded_options = None + _globals['_CREATEFOLDERREQUEST'].fields_by_name['folder_id']._serialized_options = b'\340A\002' + _globals['_CREATEFOLDERREQUEST'].fields_by_name['recursive']._loaded_options = None + _globals['_CREATEFOLDERREQUEST'].fields_by_name['recursive']._serialized_options = b'\340A\001' + _globals['_CREATEFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_CREATEFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_DELETEFOLDERREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_DELETEFOLDERREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Folder' + _globals['_DELETEFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_DELETEFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A\037\022\035storage.googleapis.com/Folder' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['page_size']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['page_size']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['page_token']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['page_token']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['prefix']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['prefix']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['delimiter']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['delimiter']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['lexicographic_start']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['lexicographic_start']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['lexicographic_end']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['lexicographic_end']._serialized_options = b'\340A\001' + _globals['_LISTFOLDERSREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_LISTFOLDERSREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Folder' + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['destination_folder_id']._loaded_options = None + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['destination_folder_id']._serialized_options = b'\340A\002' + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_RENAMEFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A\037\n\035storage.googleapis.com/Folder' + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['if_metageneration_match']._loaded_options = None + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['if_metageneration_match']._serialized_options = b'\340A\001' + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['if_metageneration_not_match']._loaded_options = None + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['if_metageneration_not_match']._serialized_options = b'\340A\001' + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_DELETEFOLDERRECURSIVEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['create_time']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['create_time']._serialized_options = b'\340A\003' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['end_time']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['end_time']._serialized_options = b'\340A\003' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['update_time']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['update_time']._serialized_options = b'\340A\003' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['type']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['type']._serialized_options = b'\340A\003' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['requested_cancellation']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['requested_cancellation']._serialized_options = b'\340A\003' + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['progress_percent']._loaded_options = None + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA'].fields_by_name['progress_percent']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT'].fields_by_name['name']._loaded_options = None + _globals['_STORAGELAYOUT'].fields_by_name['name']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT'].fields_by_name['location']._loaded_options = None + _globals['_STORAGELAYOUT'].fields_by_name['location']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT'].fields_by_name['location_type']._loaded_options = None + _globals['_STORAGELAYOUT'].fields_by_name['location_type']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT'].fields_by_name['custom_placement_config']._loaded_options = None + _globals['_STORAGELAYOUT'].fields_by_name['custom_placement_config']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT'].fields_by_name['hierarchical_namespace']._loaded_options = None + _globals['_STORAGELAYOUT'].fields_by_name['hierarchical_namespace']._serialized_options = b'\340A\003' + _globals['_STORAGELAYOUT']._loaded_options = None + _globals['_STORAGELAYOUT']._serialized_options = b'\352Ax\n$storage.googleapis.com/StorageLayout\0221projects/{project}/buckets/{bucket}/storageLayout*\016storageLayouts2\rstorageLayout' + _globals['_GETSTORAGELAYOUTREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETSTORAGELAYOUTREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/StorageLayout' + _globals['_GETSTORAGELAYOUTREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_GETSTORAGELAYOUTREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_MANAGEDFOLDER'].fields_by_name['name']._loaded_options = None + _globals['_MANAGEDFOLDER'].fields_by_name['name']._serialized_options = b'\340A\010' + _globals['_MANAGEDFOLDER'].fields_by_name['metageneration']._loaded_options = None + _globals['_MANAGEDFOLDER'].fields_by_name['metageneration']._serialized_options = b'\340A\003' + _globals['_MANAGEDFOLDER'].fields_by_name['create_time']._loaded_options = None + _globals['_MANAGEDFOLDER'].fields_by_name['create_time']._serialized_options = b'\340A\003' + _globals['_MANAGEDFOLDER'].fields_by_name['update_time']._loaded_options = None + _globals['_MANAGEDFOLDER'].fields_by_name['update_time']._serialized_options = b'\340A\003' + _globals['_MANAGEDFOLDER']._loaded_options = None + _globals['_MANAGEDFOLDER']._serialized_options = b'\352A\215\001\n$storage.googleapis.com/ManagedFolder\022Fprojects/{project}/buckets/{bucket}/managedFolders/{managed_folder=**}*\016managedFolders2\rmanagedFolder' + _globals['_GETMANAGEDFOLDERREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETMANAGEDFOLDERREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/ManagedFolder' + _globals['_GETMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_GETMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A&\022$storage.googleapis.com/ManagedFolder' + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['managed_folder']._loaded_options = None + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['managed_folder']._serialized_options = b'\340A\002' + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['managed_folder_id']._loaded_options = None + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['managed_folder_id']._serialized_options = b'\340A\002' + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_CREATEMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_DELETEMANAGEDFOLDERREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_DELETEMANAGEDFOLDERREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/ManagedFolder' + _globals['_DELETEMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_DELETEMANAGEDFOLDERREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A&\022$storage.googleapis.com/ManagedFolder' + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['page_size']._loaded_options = None + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['page_size']._serialized_options = b'\340A\001' + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['page_token']._loaded_options = None + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['page_token']._serialized_options = b'\340A\001' + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['prefix']._loaded_options = None + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['prefix']._serialized_options = b'\340A\001' + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_LISTMANAGEDFOLDERSREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_ANYWHERECACHE'].fields_by_name['name']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['name']._serialized_options = b'\340A\005' + _globals['_ANYWHERECACHE'].fields_by_name['zone']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['zone']._serialized_options = b'\340A\005' + _globals['_ANYWHERECACHE'].fields_by_name['state']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['state']._serialized_options = b'\340A\003' + _globals['_ANYWHERECACHE'].fields_by_name['create_time']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['create_time']._serialized_options = b'\340A\003' + _globals['_ANYWHERECACHE'].fields_by_name['update_time']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['update_time']._serialized_options = b'\340A\003' + _globals['_ANYWHERECACHE'].fields_by_name['pending_update']._loaded_options = None + _globals['_ANYWHERECACHE'].fields_by_name['pending_update']._serialized_options = b'\340A\003' + _globals['_ANYWHERECACHE']._loaded_options = None + _globals['_ANYWHERECACHE']._serialized_options = b'\352A\212\001\n$storage.googleapis.com/AnywhereCache\022Cprojects/{project}/buckets/{bucket}/anywhereCaches/{anywhere_cache}*\016anywhereCaches2\ranywhereCache' + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A&\022$storage.googleapis.com/AnywhereCache' + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['anywhere_cache']._loaded_options = None + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['anywhere_cache']._serialized_options = b'\340A\002' + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_CREATEANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['anywhere_cache']._loaded_options = None + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['anywhere_cache']._serialized_options = b'\340A\002' + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['update_mask']._loaded_options = None + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['update_mask']._serialized_options = b'\340A\002' + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_UPDATEANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_DISABLEANYWHERECACHEREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_DISABLEANYWHERECACHEREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/AnywhereCache' + _globals['_DISABLEANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_DISABLEANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_PAUSEANYWHERECACHEREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_PAUSEANYWHERECACHEREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/AnywhereCache' + _globals['_PAUSEANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_PAUSEANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_RESUMEANYWHERECACHEREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_RESUMEANYWHERECACHEREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/AnywhereCache' + _globals['_RESUMEANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_RESUMEANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_GETANYWHERECACHEREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETANYWHERECACHEREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A&\n$storage.googleapis.com/AnywhereCache' + _globals['_GETANYWHERECACHEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_GETANYWHERECACHEREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_LISTANYWHERECACHESREQUEST'].fields_by_name['parent']._loaded_options = None + _globals['_LISTANYWHERECACHESREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002\372A&\022$storage.googleapis.com/AnywhereCache' + _globals['_LISTANYWHERECACHESREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_LISTANYWHERECACHESREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGELOCATIONS'].fields_by_name['locations']._loaded_options = None + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGELOCATIONS'].fields_by_name['locations']._serialized_options = b'\340A\001' + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGEBUCKETS'].fields_by_name['bucket_id_regexes']._loaded_options = None + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGEBUCKETS'].fields_by_name['bucket_id_regexes']._serialized_options = b'\340A\001' + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG'].fields_by_name['effective_edition']._loaded_options = None + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG'].fields_by_name['effective_edition']._serialized_options = b'\340A\003' + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG'].fields_by_name['intelligence_config']._loaded_options = None + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG'].fields_by_name['intelligence_config']._serialized_options = b'\340A\003' + _globals['_INTELLIGENCECONFIG_TRIALCONFIG'].fields_by_name['expire_time']._loaded_options = None + _globals['_INTELLIGENCECONFIG_TRIALCONFIG'].fields_by_name['expire_time']._serialized_options = b'\340A\003' + _globals['_INTELLIGENCECONFIG'].fields_by_name['name']._loaded_options = None + _globals['_INTELLIGENCECONFIG'].fields_by_name['name']._serialized_options = b'\340A\010' + _globals['_INTELLIGENCECONFIG'].fields_by_name['edition_config']._loaded_options = None + _globals['_INTELLIGENCECONFIG'].fields_by_name['edition_config']._serialized_options = b'\340A\001' + _globals['_INTELLIGENCECONFIG'].fields_by_name['update_time']._loaded_options = None + _globals['_INTELLIGENCECONFIG'].fields_by_name['update_time']._serialized_options = b'\340A\003' + _globals['_INTELLIGENCECONFIG'].fields_by_name['filter']._loaded_options = None + _globals['_INTELLIGENCECONFIG'].fields_by_name['filter']._serialized_options = b'\340A\001' + _globals['_INTELLIGENCECONFIG'].fields_by_name['effective_intelligence_config']._loaded_options = None + _globals['_INTELLIGENCECONFIG'].fields_by_name['effective_intelligence_config']._serialized_options = b'\340A\003' + _globals['_INTELLIGENCECONFIG']._loaded_options = None + _globals['_INTELLIGENCECONFIG']._serialized_options = b'\352A\207\002\n)storage.googleapis.com/IntelligenceConfig\0228folders/{folder}/locations/{location}/intelligenceConfig\022;organizations/{org}/locations/{location}/intelligenceConfig\022:projects/{project}/locations/{location}/intelligenceConfig*\023intelligenceConfigs2\022intelligenceConfig' + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._loaded_options = None + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._serialized_options = b'\340A\002' + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._loaded_options = None + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._serialized_options = b'\340A\002' + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._loaded_options = None + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._serialized_options = b'\340A\002' + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._loaded_options = None + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._serialized_options = b'\340A\002' + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._loaded_options = None + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['intelligence_config']._serialized_options = b'\340A\002' + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._loaded_options = None + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['update_mask']._serialized_options = b'\340A\002' + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['request_id']._serialized_options = b'\340A\001\342\214\317\327\010\002\010\001' + _globals['_GETORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETORGANIZATIONINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A+\n)storage.googleapis.com/IntelligenceConfig' + _globals['_GETFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETFOLDERINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A+\n)storage.googleapis.com/IntelligenceConfig' + _globals['_GETPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._loaded_options = None + _globals['_GETPROJECTINTELLIGENCECONFIGREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002\372A+\n)storage.googleapis.com/IntelligenceConfig' + _globals['_STORAGECONTROL']._loaded_options = None + _globals['_STORAGECONTROL']._serialized_options = b'\312A\026storage.googleapis.com\322A\212\002https://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_write' + _globals['_STORAGECONTROL'].methods_by_name['CreateFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['CreateFolder']._serialized_options = b'\332A\027parent,folder,folder_id\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['DeleteFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['DeleteFolder']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['GetFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetFolder']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['ListFolders']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['ListFolders']._serialized_options = b'\332A\006parent\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['RenameFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['RenameFolder']._serialized_options = b'\312A\036\n\006Folder\022\024RenameFolderMetadata\332A\032name,destination_folder_id\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['DeleteFolderRecursive']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['DeleteFolderRecursive']._serialized_options = b'\312A6\n\025google.protobuf.Empty\022\035DeleteFolderRecursiveMetadata\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['GetStorageLayout']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetStorageLayout']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['CreateManagedFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['CreateManagedFolder']._serialized_options = b'\332A\'parent,managed_folder,managed_folder_id\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['DeleteManagedFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['DeleteManagedFolder']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['GetManagedFolder']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetManagedFolder']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['ListManagedFolders']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['ListManagedFolders']._serialized_options = b'\332A\006parent\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['CreateAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['CreateAnywhereCache']._serialized_options = b'\312A,\n\rAnywhereCache\022\033CreateAnywhereCacheMetadata\332A\025parent,anywhere_cache\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['UpdateAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['UpdateAnywhereCache']._serialized_options = b'\312A,\n\rAnywhereCache\022\033UpdateAnywhereCacheMetadata\332A\032anywhere_cache,update_mask\212\323\344\223\0029\0227\n\023anywhere_cache.name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['DisableAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['DisableAnywhereCache']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['PauseAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['PauseAnywhereCache']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['ResumeAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['ResumeAnywhereCache']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['GetAnywhereCache']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetAnywhereCache']._serialized_options = b'\332A\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['ListAnywhereCaches']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['ListAnywhereCaches']._serialized_options = b'\332A\006parent\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}' + _globals['_STORAGECONTROL'].methods_by_name['GetProjectIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetProjectIntelligenceConfig']._serialized_options = b'\332A\004name\202\323\344\223\0026\0224/v2/{name=projects/*/locations/*/intelligenceConfig}' + _globals['_STORAGECONTROL'].methods_by_name['UpdateProjectIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['UpdateProjectIntelligenceConfig']._serialized_options = b'\332A\037intelligence_config,update_mask\202\323\344\223\002_2H/v2/{intelligence_config.name=projects/*/locations/*/intelligenceConfig}:\023intelligence_config' + _globals['_STORAGECONTROL'].methods_by_name['GetFolderIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetFolderIntelligenceConfig']._serialized_options = b'\332A\004name\202\323\344\223\0025\0223/v2/{name=folders/*/locations/*/intelligenceConfig}' + _globals['_STORAGECONTROL'].methods_by_name['UpdateFolderIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['UpdateFolderIntelligenceConfig']._serialized_options = b'\332A\037intelligence_config,update_mask\202\323\344\223\002^2G/v2/{intelligence_config.name=folders/*/locations/*/intelligenceConfig}:\023intelligence_config' + _globals['_STORAGECONTROL'].methods_by_name['GetOrganizationIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetOrganizationIntelligenceConfig']._serialized_options = b'\332A\004name\202\323\344\223\002;\0229/v2/{name=organizations/*/locations/*/intelligenceConfig}' + _globals['_STORAGECONTROL'].methods_by_name['UpdateOrganizationIntelligenceConfig']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['UpdateOrganizationIntelligenceConfig']._serialized_options = b'\332A\037intelligence_config,update_mask\202\323\344\223\002d2M/v2/{intelligence_config.name=organizations/*/locations/*/intelligenceConfig}:\023intelligence_config' + _globals['_STORAGECONTROL'].methods_by_name['GetIamPolicy']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['GetIamPolicy']._serialized_options = b'\332A\010resource\212\323\344\223\002G\022\027\n\010resource\022\013{bucket=**}\022,\n\010resource\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['SetIamPolicy']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['SetIamPolicy']._serialized_options = b'\332A\017resource,policy\212\323\344\223\002G\022\027\n\010resource\022\013{bucket=**}\022,\n\010resource\022 {bucket=projects/*/buckets/*}/**' + _globals['_STORAGECONTROL'].methods_by_name['TestIamPermissions']._loaded_options = None + _globals['_STORAGECONTROL'].methods_by_name['TestIamPermissions']._serialized_options = b'\332A\024resource,permissions\212\323\344\223\002\214\001\022\027\n\010resource\022\013{bucket=**}\0224\n\010resource\022({bucket=projects/*/buckets/*}/objects/**\022;\n\010resource\022/{bucket=projects/*/buckets/*}/managedFolders/**' + _globals['_PENDINGRENAMEINFO']._serialized_start=473 + _globals['_PENDINGRENAMEINFO']._serialized_end=516 + _globals['_FOLDER']._serialized_start=519 + _globals['_FOLDER']._serialized_end=873 + _globals['_GETFOLDERREQUEST']._serialized_start=876 + _globals['_GETFOLDERREQUEST']._serialized_end=1120 + _globals['_CREATEFOLDERREQUEST']._serialized_start=1123 + _globals['_CREATEFOLDERREQUEST']._serialized_end=1336 + _globals['_DELETEFOLDERREQUEST']._serialized_start=1339 + _globals['_DELETEFOLDERREQUEST']._serialized_end=1586 + _globals['_LISTFOLDERSREQUEST']._serialized_start=1589 + _globals['_LISTFOLDERSREQUEST']._serialized_end=1857 + _globals['_LISTFOLDERSRESPONSE']._serialized_start=1859 + _globals['_LISTFOLDERSRESPONSE']._serialized_end=1957 + _globals['_RENAMEFOLDERREQUEST']._serialized_start=1960 + _globals['_RENAMEFOLDERREQUEST']._serialized_end=2243 + _globals['_DELETEFOLDERRECURSIVEREQUEST']._serialized_start=2246 + _globals['_DELETEFOLDERRECURSIVEREQUEST']._serialized_end=2512 + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA']._serialized_start=2515 + _globals['_COMMONLONGRUNNINGOPERATIONMETADATA']._serialized_end=2797 + _globals['_RENAMEFOLDERMETADATA']._serialized_start=2800 + _globals['_RENAMEFOLDERMETADATA']._serialized_end=2967 + _globals['_DELETEFOLDERRECURSIVEMETADATA']._serialized_start=2970 + _globals['_DELETEFOLDERRECURSIVEMETADATA']._serialized_end=3108 + _globals['_STORAGELAYOUT']._serialized_start=3111 + _globals['_STORAGELAYOUT']._serialized_end=3615 + _globals['_STORAGELAYOUT_CUSTOMPLACEMENTCONFIG']._serialized_start=3401 + _globals['_STORAGELAYOUT_CUSTOMPLACEMENTCONFIG']._serialized_end=3448 + _globals['_STORAGELAYOUT_HIERARCHICALNAMESPACE']._serialized_start=3450 + _globals['_STORAGELAYOUT_HIERARCHICALNAMESPACE']._serialized_end=3490 + _globals['_GETSTORAGELAYOUTREQUEST']._serialized_start=3618 + _globals['_GETSTORAGELAYOUTREQUEST']._serialized_end=3752 + _globals['_MANAGEDFOLDER']._serialized_start=3755 + _globals['_MANAGEDFOLDER']._serialized_end=4074 + _globals['_GETMANAGEDFOLDERREQUEST']._serialized_start=4077 + _globals['_GETMANAGEDFOLDERREQUEST']._serialized_end=4335 + _globals['_CREATEMANAGEDFOLDERREQUEST']._serialized_start=4338 + _globals['_CREATEMANAGEDFOLDERREQUEST']._serialized_end=4564 + _globals['_DELETEMANAGEDFOLDERREQUEST']._serialized_start=4567 + _globals['_DELETEMANAGEDFOLDERREQUEST']._serialized_end=4853 + _globals['_LISTMANAGEDFOLDERSREQUEST']._serialized_start=4856 + _globals['_LISTMANAGEDFOLDERSREQUEST']._serialized_end=5048 + _globals['_LISTMANAGEDFOLDERSRESPONSE']._serialized_start=5050 + _globals['_LISTMANAGEDFOLDERSRESPONSE']._serialized_end=5170 + _globals['_CREATEANYWHERECACHEMETADATA']._serialized_start=5173 + _globals['_CREATEANYWHERECACHEMETADATA']._serialized_end=5477 + _globals['_UPDATEANYWHERECACHEMETADATA']._serialized_start=5480 + _globals['_UPDATEANYWHERECACHEMETADATA']._serialized_end=5784 + _globals['_ANYWHERECACHE']._serialized_start=5787 + _globals['_ANYWHERECACHE']._serialized_end=6208 + _globals['_CREATEANYWHERECACHEREQUEST']._serialized_start=6211 + _globals['_CREATEANYWHERECACHEREQUEST']._serialized_end=6405 + _globals['_UPDATEANYWHERECACHEREQUEST']._serialized_start=6408 + _globals['_UPDATEANYWHERECACHEREQUEST']._serialized_end=6594 + _globals['_DISABLEANYWHERECACHEREQUEST']._serialized_start=6596 + _globals['_DISABLEANYWHERECACHEREQUEST']._serialized_end=6718 + _globals['_PAUSEANYWHERECACHEREQUEST']._serialized_start=6720 + _globals['_PAUSEANYWHERECACHEREQUEST']._serialized_end=6840 + _globals['_RESUMEANYWHERECACHEREQUEST']._serialized_start=6842 + _globals['_RESUMEANYWHERECACHEREQUEST']._serialized_end=6963 + _globals['_GETANYWHERECACHEREQUEST']._serialized_start=6965 + _globals['_GETANYWHERECACHEREQUEST']._serialized_end=7083 + _globals['_LISTANYWHERECACHESREQUEST']._serialized_start=7086 + _globals['_LISTANYWHERECACHESREQUEST']._serialized_end=7247 + _globals['_LISTANYWHERECACHESRESPONSE']._serialized_start=7249 + _globals['_LISTANYWHERECACHESRESPONSE']._serialized_end=7369 + _globals['_INTELLIGENCECONFIG']._serialized_start=7372 + _globals['_INTELLIGENCECONFIG']._serialized_end=9178 + _globals['_INTELLIGENCECONFIG_FILTER']._serialized_start=7833 + _globals['_INTELLIGENCECONFIG_FILTER']._serialized_end=8469 + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGELOCATIONS']._serialized_start=8315 + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGELOCATIONS']._serialized_end=8362 + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGEBUCKETS']._serialized_start=8364 + _globals['_INTELLIGENCECONFIG_FILTER_CLOUDSTORAGEBUCKETS']._serialized_end=8417 + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG']._serialized_start=8472 + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG']._serialized_end=8738 + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG_EFFECTIVEEDITION']._serialized_start=8661 + _globals['_INTELLIGENCECONFIG_EFFECTIVEINTELLIGENCECONFIG_EFFECTIVEEDITION']._serialized_end=8738 + _globals['_INTELLIGENCECONFIG_TRIALCONFIG']._serialized_start=8740 + _globals['_INTELLIGENCECONFIG_TRIALCONFIG']._serialized_end=8807 + _globals['_INTELLIGENCECONFIG_EDITIONCONFIG']._serialized_start=8809 + _globals['_INTELLIGENCECONFIG_EDITIONCONFIG']._serialized_end=8908 + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST']._serialized_start=9181 + _globals['_UPDATEORGANIZATIONINTELLIGENCECONFIGREQUEST']._serialized_end=9394 + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST']._serialized_start=9397 + _globals['_UPDATEFOLDERINTELLIGENCECONFIGREQUEST']._serialized_end=9604 + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST']._serialized_start=9607 + _globals['_UPDATEPROJECTINTELLIGENCECONFIGREQUEST']._serialized_end=9815 + _globals['_GETORGANIZATIONINTELLIGENCECONFIGREQUEST']._serialized_start=9817 + _globals['_GETORGANIZATIONINTELLIGENCECONFIGREQUEST']._serialized_end=9924 + _globals['_GETFOLDERINTELLIGENCECONFIGREQUEST']._serialized_start=9926 + _globals['_GETFOLDERINTELLIGENCECONFIGREQUEST']._serialized_end=10027 + _globals['_GETPROJECTINTELLIGENCECONFIGREQUEST']._serialized_start=10029 + _globals['_GETPROJECTINTELLIGENCECONFIGREQUEST']._serialized_end=10131 + _globals['_STORAGECONTROL']._serialized_start=10134 + _globals['_STORAGECONTROL']._serialized_end=15848 +# @@protoc_insertion_point(module_scope) diff --git a/google/storage/control/v2/storage_control_pb2_grpc.py b/google/storage/control/v2/storage_control_pb2_grpc.py new file mode 100644 index 00000000..cb1b186e --- /dev/null +++ b/google/storage/control/v2/storage_control_pb2_grpc.py @@ -0,0 +1,1275 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + +from google.iam.v1 import iam_policy_pb2 as google_dot_iam_dot_v1_dot_iam__policy__pb2 +from google.iam.v1 import policy_pb2 as google_dot_iam_dot_v1_dot_policy__pb2 +from google.longrunning import operations_pb2 as google_dot_longrunning_dot_operations__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 +from google.storage.control.v2 import storage_control_pb2 as google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2 + +GRPC_GENERATED_VERSION = '1.70.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + f' but the generated code in google/storage/control/v2/storage_control_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) + + +class StorageControlStub(object): + """StorageControl service includes selected control plane operations. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.CreateFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/CreateFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateFolderRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.FromString, + _registered_method=True) + self.DeleteFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/DeleteFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRequest.SerializeToString, + response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + _registered_method=True) + self.GetFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.FromString, + _registered_method=True) + self.ListFolders = channel.unary_unary( + '/google.storage.control.v2.StorageControl/ListFolders', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersResponse.FromString, + _registered_method=True) + self.RenameFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/RenameFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.RenameFolderRequest.SerializeToString, + response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, + _registered_method=True) + self.DeleteFolderRecursive = channel.unary_unary( + '/google.storage.control.v2.StorageControl/DeleteFolderRecursive', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRecursiveRequest.SerializeToString, + response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, + _registered_method=True) + self.GetStorageLayout = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetStorageLayout', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetStorageLayoutRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.StorageLayout.FromString, + _registered_method=True) + self.CreateManagedFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/CreateManagedFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateManagedFolderRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.FromString, + _registered_method=True) + self.DeleteManagedFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/DeleteManagedFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteManagedFolderRequest.SerializeToString, + response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + _registered_method=True) + self.GetManagedFolder = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetManagedFolder', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetManagedFolderRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.FromString, + _registered_method=True) + self.ListManagedFolders = channel.unary_unary( + '/google.storage.control.v2.StorageControl/ListManagedFolders', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersResponse.FromString, + _registered_method=True) + self.CreateAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/CreateAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, + _registered_method=True) + self.UpdateAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/UpdateAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, + _registered_method=True) + self.DisableAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/DisableAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DisableAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + _registered_method=True) + self.PauseAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/PauseAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.PauseAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + _registered_method=True) + self.ResumeAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/ResumeAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ResumeAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + _registered_method=True) + self.GetAnywhereCache = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetAnywhereCache', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetAnywhereCacheRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + _registered_method=True) + self.ListAnywhereCaches = channel.unary_unary( + '/google.storage.control.v2.StorageControl/ListAnywhereCaches', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesResponse.FromString, + _registered_method=True) + self.GetProjectIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetProjectIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetProjectIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.UpdateProjectIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/UpdateProjectIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateProjectIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.GetFolderIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetFolderIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.UpdateFolderIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/UpdateFolderIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateFolderIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.GetOrganizationIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetOrganizationIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetOrganizationIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.UpdateOrganizationIntelligenceConfig = channel.unary_unary( + '/google.storage.control.v2.StorageControl/UpdateOrganizationIntelligenceConfig', + request_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateOrganizationIntelligenceConfigRequest.SerializeToString, + response_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + _registered_method=True) + self.GetIamPolicy = channel.unary_unary( + '/google.storage.control.v2.StorageControl/GetIamPolicy', + request_serializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.GetIamPolicyRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_v1_dot_policy__pb2.Policy.FromString, + _registered_method=True) + self.SetIamPolicy = channel.unary_unary( + '/google.storage.control.v2.StorageControl/SetIamPolicy', + request_serializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.SetIamPolicyRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_v1_dot_policy__pb2.Policy.FromString, + _registered_method=True) + self.TestIamPermissions = channel.unary_unary( + '/google.storage.control.v2.StorageControl/TestIamPermissions', + request_serializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsRequest.SerializeToString, + response_deserializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsResponse.FromString, + _registered_method=True) + + +class StorageControlServicer(object): + """StorageControl service includes selected control plane operations. + """ + + def CreateFolder(self, request, context): + """Creates a new folder. This operation is only applicable to a hierarchical + namespace enabled bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteFolder(self, request, context): + """Permanently deletes an empty folder. This operation is only applicable to a + hierarchical namespace enabled bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetFolder(self, request, context): + """Returns metadata for the specified folder. This operation is only + applicable to a hierarchical namespace enabled bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListFolders(self, request, context): + """Retrieves a list of folders. This operation is only applicable to a + hierarchical namespace enabled bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def RenameFolder(self, request, context): + """Renames a source folder to a destination folder. This operation is only + applicable to a hierarchical namespace enabled bucket. During a rename, the + source and destination folders are locked until the long running operation + completes. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteFolderRecursive(self, request, context): + """Deletes a folder recursively. This operation is only applicable to a + hierarchical namespace enabled bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetStorageLayout(self, request, context): + """Returns the storage layout configuration for a given bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CreateManagedFolder(self, request, context): + """Creates a new managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteManagedFolder(self, request, context): + """Permanently deletes an empty managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetManagedFolder(self, request, context): + """Returns metadata for the specified managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListManagedFolders(self, request, context): + """Retrieves a list of managed folders for a given bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CreateAnywhereCache(self, request, context): + """Creates an Anywhere Cache instance. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateAnywhereCache(self, request, context): + """Updates an Anywhere Cache instance. Mutable fields include `ttl` and + `admission_policy`. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DisableAnywhereCache(self, request, context): + """Disables an Anywhere Cache instance. A disabled instance is read-only. The + disablement could be revoked by calling ResumeAnywhereCache. The cache + instance will be deleted automatically if it remains in the disabled state + for at least one hour. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def PauseAnywhereCache(self, request, context): + """Pauses an Anywhere Cache instance. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ResumeAnywhereCache(self, request, context): + """Resumes a disabled or paused Anywhere Cache instance. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetAnywhereCache(self, request, context): + """Gets an Anywhere Cache instance. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListAnywhereCaches(self, request, context): + """Lists Anywhere Cache instances for a given bucket. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetProjectIntelligenceConfig(self, request, context): + """Returns the Project scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateProjectIntelligenceConfig(self, request, context): + """Updates the Project scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetFolderIntelligenceConfig(self, request, context): + """Returns the Folder scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateFolderIntelligenceConfig(self, request, context): + """Updates the Folder scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetOrganizationIntelligenceConfig(self, request, context): + """Returns the Organization scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateOrganizationIntelligenceConfig(self, request, context): + """Updates the Organization scoped singleton IntelligenceConfig resource. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetIamPolicy(self, request, context): + """Gets the IAM policy for a specified bucket. + The `resource` field in the request should be + `projects/_/buckets/{bucket}` for a bucket, or + `projects/_/buckets/{bucket}/managedFolders/{managedFolder}` + for a managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SetIamPolicy(self, request, context): + """Updates an IAM policy for the specified bucket. + The `resource` field in the request should be + `projects/_/buckets/{bucket}` for a bucket, or + `projects/_/buckets/{bucket}/managedFolders/{managedFolder}` + for a managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def TestIamPermissions(self, request, context): + """Tests a set of permissions on the given bucket, object, or managed folder + to see which, if any, are held by the caller. + The `resource` field in the request should be + `projects/_/buckets/{bucket}` for a bucket, + `projects/_/buckets/{bucket}/objects/{object}` for an object, or + `projects/_/buckets/{bucket}/managedFolders/{managedFolder}` + for a managed folder. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_StorageControlServicer_to_server(servicer, server): + rpc_method_handlers = { + 'CreateFolder': grpc.unary_unary_rpc_method_handler( + servicer.CreateFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateFolderRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.SerializeToString, + ), + 'DeleteFolder': grpc.unary_unary_rpc_method_handler( + servicer.DeleteFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRequest.FromString, + response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + ), + 'GetFolder': grpc.unary_unary_rpc_method_handler( + servicer.GetFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.SerializeToString, + ), + 'ListFolders': grpc.unary_unary_rpc_method_handler( + servicer.ListFolders, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersResponse.SerializeToString, + ), + 'RenameFolder': grpc.unary_unary_rpc_method_handler( + servicer.RenameFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.RenameFolderRequest.FromString, + response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, + ), + 'DeleteFolderRecursive': grpc.unary_unary_rpc_method_handler( + servicer.DeleteFolderRecursive, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRecursiveRequest.FromString, + response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, + ), + 'GetStorageLayout': grpc.unary_unary_rpc_method_handler( + servicer.GetStorageLayout, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetStorageLayoutRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.StorageLayout.SerializeToString, + ), + 'CreateManagedFolder': grpc.unary_unary_rpc_method_handler( + servicer.CreateManagedFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateManagedFolderRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.SerializeToString, + ), + 'DeleteManagedFolder': grpc.unary_unary_rpc_method_handler( + servicer.DeleteManagedFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteManagedFolderRequest.FromString, + response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + ), + 'GetManagedFolder': grpc.unary_unary_rpc_method_handler( + servicer.GetManagedFolder, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetManagedFolderRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.SerializeToString, + ), + 'ListManagedFolders': grpc.unary_unary_rpc_method_handler( + servicer.ListManagedFolders, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersResponse.SerializeToString, + ), + 'CreateAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.CreateAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateAnywhereCacheRequest.FromString, + response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, + ), + 'UpdateAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.UpdateAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateAnywhereCacheRequest.FromString, + response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, + ), + 'DisableAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.DisableAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DisableAnywhereCacheRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.SerializeToString, + ), + 'PauseAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.PauseAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.PauseAnywhereCacheRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.SerializeToString, + ), + 'ResumeAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.ResumeAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ResumeAnywhereCacheRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.SerializeToString, + ), + 'GetAnywhereCache': grpc.unary_unary_rpc_method_handler( + servicer.GetAnywhereCache, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetAnywhereCacheRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.SerializeToString, + ), + 'ListAnywhereCaches': grpc.unary_unary_rpc_method_handler( + servicer.ListAnywhereCaches, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesResponse.SerializeToString, + ), + 'GetProjectIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.GetProjectIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetProjectIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'UpdateProjectIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.UpdateProjectIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateProjectIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'GetFolderIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.GetFolderIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'UpdateFolderIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.UpdateFolderIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateFolderIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'GetOrganizationIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.GetOrganizationIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetOrganizationIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'UpdateOrganizationIntelligenceConfig': grpc.unary_unary_rpc_method_handler( + servicer.UpdateOrganizationIntelligenceConfig, + request_deserializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateOrganizationIntelligenceConfigRequest.FromString, + response_serializer=google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.SerializeToString, + ), + 'GetIamPolicy': grpc.unary_unary_rpc_method_handler( + servicer.GetIamPolicy, + request_deserializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.GetIamPolicyRequest.FromString, + response_serializer=google_dot_iam_dot_v1_dot_policy__pb2.Policy.SerializeToString, + ), + 'SetIamPolicy': grpc.unary_unary_rpc_method_handler( + servicer.SetIamPolicy, + request_deserializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.SetIamPolicyRequest.FromString, + response_serializer=google_dot_iam_dot_v1_dot_policy__pb2.Policy.SerializeToString, + ), + 'TestIamPermissions': grpc.unary_unary_rpc_method_handler( + servicer.TestIamPermissions, + request_deserializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsRequest.FromString, + response_serializer=google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'google.storage.control.v2.StorageControl', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('google.storage.control.v2.StorageControl', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class StorageControl(object): + """StorageControl service includes selected control plane operations. + """ + + @staticmethod + def CreateFolder(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.control.v2.StorageControl/CreateFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateFolderRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteFolder(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.control.v2.StorageControl/DeleteFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRequest.SerializeToString, + google_dot_protobuf_dot_empty__pb2.Empty.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetFolder(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.control.v2.StorageControl/GetFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.Folder.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListFolders(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.control.v2.StorageControl/ListFolders', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListFoldersResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def RenameFolder(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.control.v2.StorageControl/RenameFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.RenameFolderRequest.SerializeToString, + google_dot_longrunning_dot_operations__pb2.Operation.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteFolderRecursive(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.control.v2.StorageControl/DeleteFolderRecursive', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteFolderRecursiveRequest.SerializeToString, + google_dot_longrunning_dot_operations__pb2.Operation.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetStorageLayout(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.control.v2.StorageControl/GetStorageLayout', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetStorageLayoutRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.StorageLayout.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CreateManagedFolder(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.control.v2.StorageControl/CreateManagedFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateManagedFolderRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteManagedFolder(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.control.v2.StorageControl/DeleteManagedFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DeleteManagedFolderRequest.SerializeToString, + google_dot_protobuf_dot_empty__pb2.Empty.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetManagedFolder(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.control.v2.StorageControl/GetManagedFolder', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetManagedFolderRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ManagedFolder.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListManagedFolders(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.control.v2.StorageControl/ListManagedFolders', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListManagedFoldersResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CreateAnywhereCache(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.control.v2.StorageControl/CreateAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.CreateAnywhereCacheRequest.SerializeToString, + google_dot_longrunning_dot_operations__pb2.Operation.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateAnywhereCache(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.control.v2.StorageControl/UpdateAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateAnywhereCacheRequest.SerializeToString, + google_dot_longrunning_dot_operations__pb2.Operation.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DisableAnywhereCache(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.control.v2.StorageControl/DisableAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.DisableAnywhereCacheRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def PauseAnywhereCache(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.control.v2.StorageControl/PauseAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.PauseAnywhereCacheRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ResumeAnywhereCache(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.control.v2.StorageControl/ResumeAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ResumeAnywhereCacheRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetAnywhereCache(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.control.v2.StorageControl/GetAnywhereCache', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetAnywhereCacheRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.AnywhereCache.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListAnywhereCaches(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.control.v2.StorageControl/ListAnywhereCaches', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.ListAnywhereCachesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetProjectIntelligenceConfig(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.control.v2.StorageControl/GetProjectIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetProjectIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateProjectIntelligenceConfig(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.control.v2.StorageControl/UpdateProjectIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateProjectIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetFolderIntelligenceConfig(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.control.v2.StorageControl/GetFolderIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetFolderIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateFolderIntelligenceConfig(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.control.v2.StorageControl/UpdateFolderIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateFolderIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetOrganizationIntelligenceConfig(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.control.v2.StorageControl/GetOrganizationIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.GetOrganizationIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateOrganizationIntelligenceConfig(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.control.v2.StorageControl/UpdateOrganizationIntelligenceConfig', + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.UpdateOrganizationIntelligenceConfigRequest.SerializeToString, + google_dot_storage_dot_control_dot_v2_dot_storage__control__pb2.IntelligenceConfig.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetIamPolicy(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.control.v2.StorageControl/GetIamPolicy', + google_dot_iam_dot_v1_dot_iam__policy__pb2.GetIamPolicyRequest.SerializeToString, + google_dot_iam_dot_v1_dot_policy__pb2.Policy.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def SetIamPolicy(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.control.v2.StorageControl/SetIamPolicy', + google_dot_iam_dot_v1_dot_iam__policy__pb2.SetIamPolicyRequest.SerializeToString, + google_dot_iam_dot_v1_dot_policy__pb2.Policy.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def TestIamPermissions(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.control.v2.StorageControl/TestIamPermissions', + google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsRequest.SerializeToString, + google_dot_iam_dot_v1_dot_iam__policy__pb2.TestIamPermissionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/google/storage/v2/storage_pb2.py b/google/storage/v2/storage_pb2.py index f26e3b24..392dd83a 100644 --- a/google/storage/v2/storage_pb2.py +++ b/google/storage/v2/storage_pb2.py @@ -1,18 +1,4 @@ # -*- coding: utf-8 -*- -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: google/storage/v2/storage.proto diff --git a/google/storage/v2/storage_pb2_grpc.py b/google/storage/v2/storage_pb2_grpc.py index 1ed487bf..fa6feef8 100644 --- a/google/storage/v2/storage_pb2_grpc.py +++ b/google/storage/v2/storage_pb2_grpc.py @@ -1,18 +1,4 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -# 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. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Client and server classes corresponding to protobuf-defined services.""" import grpc import warnings diff --git a/testbench/database.py b/testbench/database.py index 675166f7..bd640c1e 100644 --- a/testbench/database.py +++ b/testbench/database.py @@ -39,6 +39,7 @@ def __init__( retry_tests, supported_methods, soft_deleted_objects, + folders=None, ): self._resources_lock = threading.RLock() self._buckets = buckets @@ -59,9 +60,12 @@ def __init__( self._projects_lock = threading.RLock() self._projects = {} + self._folders_lock = threading.RLock() + self._folders = folders if folders is not None else {} + @classmethod def init(cls): - return cls({}, {}, {}, {}, {}, {}, [], {}) + return cls({}, {}, {}, {}, {}, {}, [], {}, {}) def clear(self): """Clear all data except for the supported method list.""" @@ -76,6 +80,8 @@ def clear(self): self._rewrites = {} with self._retry_tests_lock: self._retry_tests = {} + with self._folders_lock: + self._folders = {} # The list of supported methods for `retry_test` is defined via flask # decorators, it should remain unchanged after the test or application # is initialized. Arguably this means it should be in a global variable. @@ -790,3 +796,58 @@ def delete_retry_test(self, retry_test_id): with self._retry_tests_lock: self.get_retry_test(retry_test_id) del self._retry_tests[retry_test_id] + + # === FOLDER OPERATIONS === # + + def insert_folder(self, folder_name, folder, context): + """Insert a folder into the database.""" + with self._folders_lock: + if folder_name in self._folders: + testbench.error.already_exists( + "Folder %s already exists" % folder_name, context + ) + self._folders[folder_name] = folder + return folder + + def get_folder(self, folder_name, context): + """Get a folder from the database.""" + with self._folders_lock: + folder = self._folders.get(folder_name) + if folder is None: + testbench.error.notfound("Folder %s" % folder_name, context) + return folder + + def delete_folder(self, folder_name, context): + """Delete a folder from the database.""" + with self._folders_lock: + if folder_name not in self._folders: + testbench.error.notfound("Folder %s" % folder_name, context) + del self._folders[folder_name] + + def list_folders(self, bucket_name, prefix, context): + """List folders in a bucket with optional prefix filter.""" + with self._folders_lock: + folders = [] + for folder_name, folder in self._folders.items(): + # Filter by bucket + if not folder_name.startswith(bucket_name): + continue + # Filter by prefix if provided + if prefix and not folder_name.startswith(f"{bucket_name}/{prefix}"): + continue + folders.append(folder) + return folders + + def rename_folder(self, src_folder_name, dst_folder_name, context): + """Rename a folder.""" + with self._folders_lock: + if src_folder_name not in self._folders: + testbench.error.notfound("Source folder %s" % src_folder_name, context) + if dst_folder_name in self._folders: + testbench.error.already_exists( + "Destination folder %s already exists" % dst_folder_name, context + ) + folder = self._folders[src_folder_name] + del self._folders[src_folder_name] + self._folders[dst_folder_name] = folder + return folder diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 66782273..c59bfc10 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -40,6 +40,7 @@ import testbench from google.iam.v1 import iam_policy_pb2 from google.storage.v2 import storage_pb2, storage_pb2_grpc +from google.storage.control.v2 import storage_control_pb2, storage_control_pb2_grpc _GRPC_SERVER_THREAD_COUNT = 2 @@ -1163,6 +1164,81 @@ def QueryWriteStatus(self, request, context): return storage_pb2.QueryWriteStatusResponse(persisted_size=len(upload.media)) +# === STORAGE CONTROL SERVICER === # + + +@decorate_all_rpc_methods +class StorageControlServicer(storage_control_pb2_grpc.StorageControlServicer): + """Implements the google.storage.control.v2.StorageControl gRPC service.""" + + def __init__(self, db, echo_metadata=False): + self.db = db + self.db.insert_test_bucket() + self.echo_metadata = echo_metadata + + def _apply_stall(self, context): + """Check for stall instructions and apply delay if needed.""" + import time + + instruction = testbench.common.extract_instruction(None, context) + if instruction and "stall" in instruction: + # Parse stall instruction (e.g., "stall-always", "stall-for-10s") + if instruction.startswith("stall-always"): + time.sleep(10) + elif instruction.startswith("stall-for-"): + # Parse "stall-for-10s" format + match = re.match(r'stall-for-(\d+)s', instruction) + if match: + time.sleep(int(match.group(1))) + + @retry_test(method="storage.folders.create") + def CreateFolder(self, request, context): + self._apply_stall(context) + # Create a simple folder metadata + folder = storage_control_pb2.Folder() + # The name should include the full path + folder.name = f"{request.parent}/folders/{request.folder_id}" + folder.metageneration = 1 + folder.create_time.FromDatetime(datetime.datetime.now(datetime.timezone.utc)) + folder.update_time.CopyFrom(folder.create_time) + + # Store in database using full name as key + self.db.insert_folder(folder.name, folder, context) + return folder + + @retry_test(method="storage.folders.delete") + def DeleteFolder(self, request, context): + self._apply_stall(context) + folder_key = request.name + self.db.delete_folder(folder_key, context) + return empty_pb2.Empty() + + @retry_test(method="storage.folders.get") + def GetFolder(self, request, context): + self._apply_stall(context) + folder_key = request.name + return self.db.get_folder(folder_key, context) + + @retry_test(method="storage.folders.list") + def ListFolders(self, request, context): + self._apply_stall(context) + # Extract bucket from parent (format: "projects/_/buckets/{bucket}") + bucket_name = request.parent + prefix = request.prefix if hasattr(request, 'prefix') else "" + + folders = self.db.list_folders(bucket_name, prefix, context) + return storage_control_pb2.ListFoldersResponse(folders=folders) + + @retry_test(method="storage.folders.rename") + def RenameFolder(self, request, context): + self._apply_stall(context) + src_folder = request.name + dst_folder = request.destination_folder_id + + folder = self.db.rename_folder(src_folder, dst_folder, context) + return folder + + def run(port, database, echo_metadata=False): server = grpc.server( futures.ThreadPoolExecutor(max_workers=_GRPC_SERVER_THREAD_COUNT) @@ -1170,6 +1246,9 @@ def run(port, database, echo_metadata=False): storage_pb2_grpc.add_StorageServicer_to_server( StorageServicer(database, echo_metadata), server ) + storage_control_pb2_grpc.add_StorageControlServicer_to_server( + StorageControlServicer(database, echo_metadata), server + ) port = server.add_insecure_port("0.0.0.0:%d" % port) server.start() return port, server diff --git a/tests/test_storage_control_stall.py b/tests/test_storage_control_stall.py new file mode 100644 index 00000000..7b9994a0 --- /dev/null +++ b/tests/test_storage_control_stall.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Test stall functionality for Storage Control API.""" + +import time +import unittest +import unittest.mock + +import grpc + +import testbench +from google.protobuf import empty_pb2 +from google.storage.control.v2 import storage_control_pb2 + + +class TestStorageControlStall(unittest.TestCase): + """Test cases for Storage Control API stall functionality.""" + + def mock_context(self, metadata=None): + """Create a mock context with optional metadata.""" + context = unittest.mock.Mock() + if metadata is None: + metadata = [] + context.invocation_metadata = unittest.mock.Mock(return_value=metadata) + return context + + def setUp(self): + self.db = testbench.database.Database.init() + self.servicer = testbench.grpc_server.StorageControlServicer( + self.db, echo_metadata=False + ) + + def test_create_folder_no_stall(self): + """Test folder creation without stall instruction.""" + request = storage_control_pb2.CreateFolderRequest() + request.parent = "projects/_/buckets/test-bucket" + request.folder_id = "test-folder" + + context = self.mock_context() + + start_time = time.time() + folder = self.servicer.CreateFolder(request, context) + elapsed = time.time() - start_time + + self.assertIsNotNone(folder) + self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder") + self.assertLess(elapsed, 1.0, "Should complete quickly without stall") + + def test_create_folder_stall_always(self): + """Test folder creation with stall-always instruction.""" + request = storage_control_pb2.CreateFolderRequest() + request.parent = "projects/_/buckets/test-bucket" + request.folder_id = "test-folder-stall" + + metadata = [("x-goog-emulator-instructions", "stall-always")] + context = self.mock_context(metadata) + + start_time = time.time() + folder = self.servicer.CreateFolder(request, context) + elapsed = time.time() - start_time + + self.assertIsNotNone(folder) + self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-stall") + self.assertGreaterEqual(elapsed, 10.0, "Should stall for at least 10 seconds") + + def test_create_folder_stall_custom_duration(self): + """Test folder creation with custom stall duration.""" + request = storage_control_pb2.CreateFolderRequest() + request.parent = "projects/_/buckets/test-bucket" + request.folder_id = "test-folder-custom-stall" + + metadata = [("x-goog-emulator-instructions", "stall-for-3s")] + context = self.mock_context(metadata) + + start_time = time.time() + folder = self.servicer.CreateFolder(request, context) + elapsed = time.time() - start_time + + self.assertIsNotNone(folder) + self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-custom-stall") + self.assertGreaterEqual(elapsed, 3.0, "Should stall for at least 3 seconds") + self.assertLess(elapsed, 5.0, "Should not stall longer than 5 seconds") + + def test_delete_folder_stall(self): + """Test folder deletion with stall instruction.""" + # First create a folder + create_request = storage_control_pb2.CreateFolderRequest() + create_request.parent = "projects/_/buckets/test-bucket" + create_request.folder_id = "test-folder-delete" + context = self.mock_context() + self.servicer.CreateFolder(create_request, context) + + # Now delete it with stall + delete_request = storage_control_pb2.DeleteFolderRequest() + delete_request.name = "projects/_/buckets/test-bucket/test-folder-delete" + + metadata = [("x-goog-emulator-instructions", "stall-for-2s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + result = self.servicer.DeleteFolder(delete_request, context_stall) + elapsed = time.time() - start_time + + self.assertIsInstance(result, empty_pb2.Empty) + self.assertGreaterEqual(elapsed, 2.0, "Should stall for at least 2 seconds") + + def test_get_folder_stall(self): + """Test get folder with stall instruction.""" + # First create a folder + create_request = storage_control_pb2.CreateFolderRequest() + create_request.parent = "projects/_/buckets/test-bucket" + create_request.folder_id = "test-folder-get" + context = self.mock_context() + created_folder = self.servicer.CreateFolder(create_request, context) + + # Now get it with stall + get_request = storage_control_pb2.GetFolderRequest() + get_request.name = "projects/_/buckets/test-bucket/folders/test-folder-get" + + metadata = [("x-goog-emulator-instructions", "stall-for-5s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + folder = self.servicer.GetFolder(get_request, context_stall) + elapsed = time.time() - start_time + + self.assertIsNotNone(folder) + self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-get") + self.assertGreaterEqual(elapsed, 5.0, "Should stall for at least 5 seconds") + + def test_list_folders_stall(self): + """Test list folders with stall instruction.""" + # Create some folders + for i in range(3): + create_request = storage_control_pb2.CreateFolderRequest() + create_request.parent = "projects/_/buckets/test-bucket" + create_request.folder_id = f"test-folder-list-{i}" + context = self.mock_context() + self.servicer.CreateFolder(create_request, context) + + # List with stall + list_request = storage_control_pb2.ListFoldersRequest() + list_request.parent = "projects/_/buckets/test-bucket" + + metadata = [("x-goog-emulator-instructions", "stall-for-4s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + response = self.servicer.ListFolders(list_request, context_stall) + elapsed = time.time() - start_time + + self.assertIsNotNone(response) + self.assertGreaterEqual(len(response.folders), 3) + self.assertGreaterEqual(elapsed, 4.0, "Should stall for at least 4 seconds") + + def test_rename_folder_stall(self): + """Test rename folder with stall instruction.""" + # Create a folder + create_request = storage_control_pb2.CreateFolderRequest() + create_request.parent = "projects/_/buckets/test-bucket" + create_request.folder_id = "test-folder-rename-src" + context = self.mock_context() + self.servicer.CreateFolder(create_request, context) + + # Rename with stall + rename_request = storage_control_pb2.RenameFolderRequest() + rename_request.name = "projects/_/buckets/test-bucket/test-folder-rename-src" + rename_request.destination_folder_id = "projects/_/buckets/test-bucket/test-folder-rename-dst" + + metadata = [("x-goog-emulator-instructions", "stall-for-6s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + folder = self.servicer.RenameFolder(rename_request, context_stall) + elapsed = time.time() - start_time + + self.assertIsNotNone(folder) + self.assertGreaterEqual(elapsed, 6.0, "Should stall for at least 6 seconds") + + +if __name__ == "__main__": + unittest.main() diff --git a/update-protos.sh b/update-protos.sh index 4e09fcf2..073767e5 100755 --- a/update-protos.sh +++ b/update-protos.sh @@ -31,6 +31,7 @@ readonly INPUTS=( google/iam/v1/options.proto google/iam/v1/policy.proto google/storage/v2/storage.proto + google/storage/control/v2/storage_control.proto ) readonly INPUTS From e2409e434f02c9dcb3557c8bc375b5eb96853b83 Mon Sep 17 00:00:00 2001 From: raj-prince Date: Tue, 17 Mar 2026 06:49:41 +0000 Subject: [PATCH 2/4] adding more test and removing redundant content --- README.md | 31 ++++- STALL_VALIDATION.md | 156 -------------------------- google/storage/control/__init__.py | 2 +- google/storage/control/v2/__init__.py | 13 --- testbench/grpc_server.py | 8 +- tests/test_storage_control_stall.py | 81 ++++++++++--- 6 files changed, 96 insertions(+), 195 deletions(-) delete mode 100644 STALL_VALIDATION.md delete mode 100644 google/storage/control/v2/__init__.py diff --git a/README.md b/README.md index 70042961..108f8cd7 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,7 @@ is expected to be used by Storage library maintainers. - [When to use this testbench](#when-to-use-this-testbench) - [How to use this testbench](#how-to-use-this-testbench) - [Initial set up](#initial-set-up) - - [Run the testbench](#run-the-testbench) - - [Start the gRPC server](#start-the-gRPC-server) + - [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) @@ -35,6 +34,7 @@ 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) + - [Storage Control API Stall Support](#storage-control-api-stall-support) - [Developing for the testbench](#developing-for-the-testbench) - [Writing and running tests](#writing-and-running-tests) - [Releasing the testbench](#releasing-the-testbench) @@ -277,6 +277,33 @@ 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. +## Storage Control API Stall Support + +The testbench supports stall functionality for the Storage Control API (gRPC only) to test client retry behavior. All folder operations (`CreateFolder`, `DeleteFolder`, `GetFolder`, `ListFolders`, `RenameFolder`) can be delayed using the `x-goog-emulator-instructions` metadata header. + +> **Note:** The Storage Control API uses the **same gRPC server** as the Storage API. Both services are available on the same port (e.g., port 8888 if started with `curl "http://localhost:9000/start_grpc?port=8888"`). + +**Supported stall instruction:** +- `stall-for-Ns`: Stalls for N seconds (e.g., `stall-for-3s` stalls for 3 seconds) + +**Example usage in Python:** +```python +import grpc +from google.storage.control.v2 import storage_control_pb2, storage_control_pb2_grpc + +# Connect to the same gRPC server port (8888) started earlier +channel = grpc.insecure_channel('localhost:8888') +stub = storage_control_pb2_grpc.StorageControlStub(channel) + +# Create folder with 2-second stall +metadata = [('x-goog-emulator-instructions', 'stall-for-2s')] +request = storage_control_pb2.CreateFolderRequest( + parent="projects/_/buckets/test-bucket", + folder_id="test-folder" +) +response = stub.CreateFolder(request, metadata=metadata) +``` + ## Developing for the testbench ### Writing and running tests diff --git a/STALL_VALIDATION.md b/STALL_VALIDATION.md deleted file mode 100644 index c2727af6..00000000 --- a/STALL_VALIDATION.md +++ /dev/null @@ -1,156 +0,0 @@ -# Storage Control API Stall Implementation - Validation Guide - -## Overview - -This document describes how to validate the stall functionality for the Storage Control API that was implemented in this branch. - -## What Was Implemented - -1. **Protobuf Generation**: Added `google/storage/control/v2/storage_control.proto` to the proto generation pipeline -2. **Database Layer**: Added folder storage **capabilities** to `testbench/database.py` -3. **gRPC Service**: Implemented `StorageControlServicer` in `testbench/grpc_server.py` with stall support -4. **Stall Functionality**: Added `_apply_stall()` method that intercepts folder API calls and applies delays based on `x-goog-emulator-instructions` metadata - -## Stall Instructions Supported - -The implementation supports the following stall instructions via gRPC metadata header `x-goog-emulator-instructions`: - -- `stall-always`: Stalls for 10 seconds at the beginning of the request -- `stall-for-Ns`: Stalls for N seconds (e.g., `stall-for-3s` stalls for 3 seconds) - -## Supported Operations - -All Storage Control API folder operations support stall: -- `CreateFolder` -- `DeleteFolder` -- `GetFolder` -- `ListFolders` -- `RenameFolder` - -## Running the Tests - -### Prerequisites - -1. Ensure you're in a virtual environment: -```bash -source ../venv-storage-testbench/bin/activate -``` - -### Quick Validation (Non-Stall Test) - -Run this test to verify basic functionality (~1 second): -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_create_folder_no_stall -v -``` - -### Stall Functionality Tests - -Run these tests to verify stall functionality (each takes several seconds due to intentional delays): - -**Custom duration stall (3 seconds):** -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_create_folder_stall_custom_duration -v -``` - -**Delete with stall (2 seconds):** -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_delete_folder_stall -v -``` - -**Get with stall (5 seconds):** -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_get_folder_stall -v -``` - -**List with stall (4 seconds):** -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_list_folders_stall -v -``` - -**Rename with stall (6 seconds):** -```bash -python -m unittest tests.test_storage_control_stall.TestStorageControlStall.test_rename_folder_stall -v -``` - -### Full Test Suite - -Run all tests at once (takes ~30+ seconds): -```bash -python -m unittest tests.test_storage_control_stall -v -``` - -**Note:** The `test_create_folder_stall_always` test takes 10+ seconds as it uses the default stall duration. - -## Manual Testing with gRPC Client - -You can also test using a Python gRPC client: - -```python -import grpc -from google.storage.control.v2 import storage_control_pb2, storage_control_pb2_grpc -import time - -# Connect to testbench -channel = grpc.insecure_channel('localhost:9099') # Use actual gRPC port -stub = storage_control_pb2_grpc.StorageControlStub(channel) - -# Test with stall-for-5s instruction -metadata = [('x-goog-emulator-instructions', 'stall-for-5s')] -request = storage_control_pb2.CreateFolderRequest() -request.parent = "projects/_/buckets/test-bucket" -request.folder_id = "my-test-folder" - -start = time.time() -folder = stub.CreateFolder(request, metadata=metadata) -elapsed = time.time() - start - -print(f"Request took {elapsed:.2f} seconds") -print(f"Created folder: {folder.name}") -``` - -## Expected Test Results - -✅ **Success Criteria:** -- Non-stall tests complete in < 1 second -- `stall-always` tests take >= 10 seconds -- `stall-for-Ns` tests take >= N seconds (within 1-2 seconds tolerance) -- Folder operations (create, delete, get, list, rename) all work correctly -- Stall applies before the operation executes - -## Integration with Existing Tests - -The implementation doesn't affect existing Storage API tests. You can verify this by running: - -```bash -python -m unittest discover -s tests/ -p "test_grpc_server.py" -v -``` - -This should pass without any issues. - -## Files Modified - -- `update-protos.sh`: Added storage_control.proto to the generation list -- `testbench/database.py`: Added folder storage methods -- `testbench/grpc_server.py`: Added StorageControlServicer with stall support -- `tests/test_storage_control_stall.py`: Comprehensive test suite for stall functionality -- `google/storage/control/v2/`: Generated protobuf files (storage_control_pb2.py, storage_control_pb2_grpc.py) - -## Troubleshooting - -**Issue: ImportError for storage_control_pb2** -- Solution: Regenerate protobuf files: `source ../venv-storage-testbench/bin/activate && bash update-protos.sh` - -**Issue: Tests timing out** -- Solution: Increase timeout values in test runner, stall tests are intentionally slow - -**Issue: "Protocol message Folder has no field 'bucket'"** -- Solution: This was fixed - Folder only has fields: name, metageneration, create_time, update_time, pending_rename_info - -## Architecture Notes - -The stall implementation uses `time.sleep()` which blocks the current thread. This is appropriate for: -- Testing timeout handling -- Simulating slow backends -- Reproducing transient network conditions - -The implementation extracts stall instructions from gRPC metadata via `testbench.common.extract_instruction()`, which checks for the `x-goog-emulator-instructions` header in the invocation metadata. diff --git a/google/storage/control/__init__.py b/google/storage/control/__init__.py index c6334245..58d482ea 100644 --- a/google/storage/control/__init__.py +++ b/google/storage/control/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/google/storage/control/v2/__init__.py b/google/storage/control/v2/__init__.py deleted file mode 100644 index c6334245..00000000 --- a/google/storage/control/v2/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index c59bfc10..9853e065 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -1182,11 +1182,9 @@ def _apply_stall(self, context): instruction = testbench.common.extract_instruction(None, context) if instruction and "stall" in instruction: - # Parse stall instruction (e.g., "stall-always", "stall-for-10s") - if instruction.startswith("stall-always"): - time.sleep(10) - elif instruction.startswith("stall-for-"): - # Parse "stall-for-10s" format + # Parse stall instruction (e.g., "stall-for-1s") + if instruction.startswith("stall-for-"): + # Parse "stall-for-1s" format match = re.match(r'stall-for-(\d+)s', instruction) if match: time.sleep(int(match.group(1))) diff --git a/tests/test_storage_control_stall.py b/tests/test_storage_control_stall.py index 7b9994a0..54c3eb29 100644 --- a/tests/test_storage_control_stall.py +++ b/tests/test_storage_control_stall.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright 2020 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -59,13 +59,13 @@ def test_create_folder_no_stall(self): self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder") self.assertLess(elapsed, 1.0, "Should complete quickly without stall") - def test_create_folder_stall_always(self): - """Test folder creation with stall-always instruction.""" + def test_create_folder_stall_1s(self): + """Test folder creation with 1s stall instruction.""" request = storage_control_pb2.CreateFolderRequest() request.parent = "projects/_/buckets/test-bucket" request.folder_id = "test-folder-stall" - metadata = [("x-goog-emulator-instructions", "stall-always")] + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context = self.mock_context(metadata) start_time = time.time() @@ -74,7 +74,7 @@ def test_create_folder_stall_always(self): self.assertIsNotNone(folder) self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-stall") - self.assertGreaterEqual(elapsed, 10.0, "Should stall for at least 10 seconds") + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_create_folder_stall_custom_duration(self): """Test folder creation with custom stall duration.""" @@ -82,7 +82,7 @@ def test_create_folder_stall_custom_duration(self): request.parent = "projects/_/buckets/test-bucket" request.folder_id = "test-folder-custom-stall" - metadata = [("x-goog-emulator-instructions", "stall-for-3s")] + metadata = [("x-goog-emulator-instructions", "stall-for-2s")] context = self.mock_context(metadata) start_time = time.time() @@ -91,8 +91,8 @@ def test_create_folder_stall_custom_duration(self): self.assertIsNotNone(folder) self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-custom-stall") - self.assertGreaterEqual(elapsed, 3.0, "Should stall for at least 3 seconds") - self.assertLess(elapsed, 5.0, "Should not stall longer than 5 seconds") + self.assertGreaterEqual(elapsed, 2.0, "Should stall for at least 2 seconds") + self.assertLess(elapsed, 3.0, "Should not stall longer than 3 seconds") def test_delete_folder_stall(self): """Test folder deletion with stall instruction.""" @@ -105,9 +105,9 @@ def test_delete_folder_stall(self): # Now delete it with stall delete_request = storage_control_pb2.DeleteFolderRequest() - delete_request.name = "projects/_/buckets/test-bucket/test-folder-delete" + delete_request.name = "projects/_/buckets/test-bucket/folders/test-folder-delete" - metadata = [("x-goog-emulator-instructions", "stall-for-2s")] + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) start_time = time.time() @@ -115,7 +115,7 @@ def test_delete_folder_stall(self): elapsed = time.time() - start_time self.assertIsInstance(result, empty_pb2.Empty) - self.assertGreaterEqual(elapsed, 2.0, "Should stall for at least 2 seconds") + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_get_folder_stall(self): """Test get folder with stall instruction.""" @@ -130,7 +130,7 @@ def test_get_folder_stall(self): get_request = storage_control_pb2.GetFolderRequest() get_request.name = "projects/_/buckets/test-bucket/folders/test-folder-get" - metadata = [("x-goog-emulator-instructions", "stall-for-5s")] + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) start_time = time.time() @@ -139,7 +139,7 @@ def test_get_folder_stall(self): self.assertIsNotNone(folder) self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-get") - self.assertGreaterEqual(elapsed, 5.0, "Should stall for at least 5 seconds") + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_list_folders_stall(self): """Test list folders with stall instruction.""" @@ -155,7 +155,7 @@ def test_list_folders_stall(self): list_request = storage_control_pb2.ListFoldersRequest() list_request.parent = "projects/_/buckets/test-bucket" - metadata = [("x-goog-emulator-instructions", "stall-for-4s")] + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) start_time = time.time() @@ -164,7 +164,7 @@ def test_list_folders_stall(self): self.assertIsNotNone(response) self.assertGreaterEqual(len(response.folders), 3) - self.assertGreaterEqual(elapsed, 4.0, "Should stall for at least 4 seconds") + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_rename_folder_stall(self): """Test rename folder with stall instruction.""" @@ -177,10 +177,10 @@ def test_rename_folder_stall(self): # Rename with stall rename_request = storage_control_pb2.RenameFolderRequest() - rename_request.name = "projects/_/buckets/test-bucket/test-folder-rename-src" + rename_request.name = "projects/_/buckets/test-bucket/folders/test-folder-rename-src" rename_request.destination_folder_id = "projects/_/buckets/test-bucket/test-folder-rename-dst" - metadata = [("x-goog-emulator-instructions", "stall-for-6s")] + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) start_time = time.time() @@ -188,7 +188,52 @@ def test_rename_folder_stall(self): elapsed = time.time() - start_time self.assertIsNotNone(folder) - self.assertGreaterEqual(elapsed, 6.0, "Should stall for at least 6 seconds") + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") + + def test_multiple_stalls_and_no_stall(self): + """Test that stall happens twice with metadata and not without.""" + # First call with stall metadata + request1 = storage_control_pb2.CreateFolderRequest() + request1.parent = "projects/_/buckets/test-bucket" + request1.folder_id = "test-folder-multi-1" + + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + folder1 = self.servicer.CreateFolder(request1, context_stall) + elapsed1 = time.time() - start_time + + self.assertIsNotNone(folder1) + self.assertGreaterEqual(elapsed1, 1.0, "First call should stall for at least 1 second") + + # Second call with stall metadata + request2 = storage_control_pb2.CreateFolderRequest() + request2.parent = "projects/_/buckets/test-bucket" + request2.folder_id = "test-folder-multi-2" + + context_stall2 = self.mock_context(metadata) + + start_time = time.time() + folder2 = self.servicer.CreateFolder(request2, context_stall2) + elapsed2 = time.time() - start_time + + self.assertIsNotNone(folder2) + self.assertGreaterEqual(elapsed2, 1.0, "Second call should stall for at least 1 second") + + # Third call without stall metadata + request3 = storage_control_pb2.CreateFolderRequest() + request3.parent = "projects/_/buckets/test-bucket" + request3.folder_id = "test-folder-multi-3" + + context_no_stall = self.mock_context() + + start_time = time.time() + folder3 = self.servicer.CreateFolder(request3, context_no_stall) + elapsed3 = time.time() - start_time + + self.assertIsNotNone(folder3) + self.assertLess(elapsed3, 1.0, "Third call should complete quickly without stall") if __name__ == "__main__": From 61fb8f3117cb137ab121701745cc066eeecc858d Mon Sep 17 00:00:00 2001 From: raj-prince Date: Tue, 17 Mar 2026 07:01:39 +0000 Subject: [PATCH 3/4] adding GetStorageLayout API support --- README.md | 6 ++++- testbench/grpc_server.py | 13 +++++++++++ tests/test_storage_control_stall.py | 34 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 108f8cd7..7b77857f 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,11 @@ curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:91 ## Storage Control API Stall Support -The testbench supports stall functionality for the Storage Control API (gRPC only) to test client retry behavior. All folder operations (`CreateFolder`, `DeleteFolder`, `GetFolder`, `ListFolders`, `RenameFolder`) can be delayed using the `x-goog-emulator-instructions` metadata header. +The testbench supports stall functionality for the Storage Control API (gRPC only) to test client retry behavior. All folder operations and storage layout operations can be delayed using the `x-goog-emulator-instructions` metadata header. + +**Supported operations:** +- **Folder operations:** `CreateFolder`, `DeleteFolder`, `GetFolder`, `ListFolders`, `RenameFolder` +- **Storage layout operations:** `GetStorageLayout` > **Note:** The Storage Control API uses the **same gRPC server** as the Storage API. Both services are available on the same port (e.g., port 8888 if started with `curl "http://localhost:9000/start_grpc?port=8888"`). diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 9853e065..0a76f862 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -1236,6 +1236,19 @@ def RenameFolder(self, request, context): folder = self.db.rename_folder(src_folder, dst_folder, context) return folder + @retry_test(method="storage.storageLayout.get") + def GetStorageLayout(self, request, context): + self._apply_stall(context) + # Create a simple storage layout response + layout = storage_control_pb2.StorageLayout() + layout.name = request.name + # Set default location and location_type + layout.location = "US" + layout.location_type = "multi-region" + # Optionally set hierarchical namespace enabled flag + layout.hierarchical_namespace.enabled = False + return layout + def run(port, database, echo_metadata=False): server = grpc.server( diff --git a/tests/test_storage_control_stall.py b/tests/test_storage_control_stall.py index 54c3eb29..1fad3472 100644 --- a/tests/test_storage_control_stall.py +++ b/tests/test_storage_control_stall.py @@ -235,6 +235,40 @@ def test_multiple_stalls_and_no_stall(self): self.assertIsNotNone(folder3) self.assertLess(elapsed3, 1.0, "Third call should complete quickly without stall") + def test_get_storage_layout_no_stall(self): + """Test get storage layout without stall instruction.""" + request = storage_control_pb2.GetStorageLayoutRequest() + request.name = "projects/_/buckets/test-bucket/storageLayout" + + context = self.mock_context() + + start_time = time.time() + layout = self.servicer.GetStorageLayout(request, context) + elapsed = time.time() - start_time + + self.assertIsNotNone(layout) + self.assertEqual(layout.name, "projects/_/buckets/test-bucket/storageLayout") + self.assertLess(elapsed, 1.0, "Should complete quickly without stall") + + def test_get_storage_layout_stall(self): + """Test get storage layout with stall instruction.""" + request = storage_control_pb2.GetStorageLayoutRequest() + request.name = "projects/_/buckets/test-bucket/storageLayout" + + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] + context_stall = self.mock_context(metadata) + + start_time = time.time() + layout = self.servicer.GetStorageLayout(request, context_stall) + elapsed = time.time() - start_time + + self.assertIsNotNone(layout) + self.assertEqual(layout.name, "projects/_/buckets/test-bucket/storageLayout") + self.assertEqual(layout.location, "US") + self.assertEqual(layout.location_type, "multi-region") + self.assertFalse(layout.hierarchical_namespace.enabled) + self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") + if __name__ == "__main__": unittest.main() From e64634c282399c3f21207de7080940e6727a0a00 Mon Sep 17 00:00:00 2001 From: raj-prince Date: Tue, 17 Mar 2026 07:04:54 +0000 Subject: [PATCH 4/4] fixing lint issue --- testbench/grpc_server.py | 17 ++-- tests/test_storage_control_stall.py | 125 ++++++++++++++++------------ 2 files changed, 83 insertions(+), 59 deletions(-) diff --git a/testbench/grpc_server.py b/testbench/grpc_server.py index 0a76f862..78c293e2 100644 --- a/testbench/grpc_server.py +++ b/testbench/grpc_server.py @@ -541,7 +541,10 @@ def precondition(_, live_version, ctx): bucket = self.db.get_bucket(request.destination.bucket, context).metadata metadata = storage_pb2.Object() metadata.MergeFrom(request.destination) - (blob, _,) = gcs.object.Object.init( + ( + blob, + _, + ) = gcs.object.Object.init( request, metadata, composed_media, bucket, True, context ) self.db.insert_object( @@ -1179,13 +1182,13 @@ def __init__(self, db, echo_metadata=False): def _apply_stall(self, context): """Check for stall instructions and apply delay if needed.""" import time - + instruction = testbench.common.extract_instruction(None, context) if instruction and "stall" in instruction: # Parse stall instruction (e.g., "stall-for-1s") if instruction.startswith("stall-for-"): # Parse "stall-for-1s" format - match = re.match(r'stall-for-(\d+)s', instruction) + match = re.match(r"stall-for-(\d+)s", instruction) if match: time.sleep(int(match.group(1))) @@ -1199,7 +1202,7 @@ def CreateFolder(self, request, context): folder.metageneration = 1 folder.create_time.FromDatetime(datetime.datetime.now(datetime.timezone.utc)) folder.update_time.CopyFrom(folder.create_time) - + # Store in database using full name as key self.db.insert_folder(folder.name, folder, context) return folder @@ -1222,8 +1225,8 @@ def ListFolders(self, request, context): self._apply_stall(context) # Extract bucket from parent (format: "projects/_/buckets/{bucket}") bucket_name = request.parent - prefix = request.prefix if hasattr(request, 'prefix') else "" - + prefix = request.prefix if hasattr(request, "prefix") else "" + folders = self.db.list_folders(bucket_name, prefix, context) return storage_control_pb2.ListFoldersResponse(folders=folders) @@ -1232,7 +1235,7 @@ def RenameFolder(self, request, context): self._apply_stall(context) src_folder = request.name dst_folder = request.destination_folder_id - + folder = self.db.rename_folder(src_folder, dst_folder, context) return folder diff --git a/tests/test_storage_control_stall.py b/tests/test_storage_control_stall.py index 1fad3472..507cd358 100644 --- a/tests/test_storage_control_stall.py +++ b/tests/test_storage_control_stall.py @@ -48,15 +48,17 @@ def test_create_folder_no_stall(self): request = storage_control_pb2.CreateFolderRequest() request.parent = "projects/_/buckets/test-bucket" request.folder_id = "test-folder" - + context = self.mock_context() - + start_time = time.time() folder = self.servicer.CreateFolder(request, context) elapsed = time.time() - start_time - + self.assertIsNotNone(folder) - self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder") + self.assertEqual( + folder.name, "projects/_/buckets/test-bucket/folders/test-folder" + ) self.assertLess(elapsed, 1.0, "Should complete quickly without stall") def test_create_folder_stall_1s(self): @@ -64,16 +66,18 @@ def test_create_folder_stall_1s(self): request = storage_control_pb2.CreateFolderRequest() request.parent = "projects/_/buckets/test-bucket" request.folder_id = "test-folder-stall" - + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context = self.mock_context(metadata) - + start_time = time.time() folder = self.servicer.CreateFolder(request, context) elapsed = time.time() - start_time - + self.assertIsNotNone(folder) - self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-stall") + self.assertEqual( + folder.name, "projects/_/buckets/test-bucket/folders/test-folder-stall" + ) self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_create_folder_stall_custom_duration(self): @@ -81,16 +85,19 @@ def test_create_folder_stall_custom_duration(self): request = storage_control_pb2.CreateFolderRequest() request.parent = "projects/_/buckets/test-bucket" request.folder_id = "test-folder-custom-stall" - + metadata = [("x-goog-emulator-instructions", "stall-for-2s")] context = self.mock_context(metadata) - + start_time = time.time() folder = self.servicer.CreateFolder(request, context) elapsed = time.time() - start_time - + self.assertIsNotNone(folder) - self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-custom-stall") + self.assertEqual( + folder.name, + "projects/_/buckets/test-bucket/folders/test-folder-custom-stall", + ) self.assertGreaterEqual(elapsed, 2.0, "Should stall for at least 2 seconds") self.assertLess(elapsed, 3.0, "Should not stall longer than 3 seconds") @@ -102,18 +109,20 @@ def test_delete_folder_stall(self): create_request.folder_id = "test-folder-delete" context = self.mock_context() self.servicer.CreateFolder(create_request, context) - + # Now delete it with stall delete_request = storage_control_pb2.DeleteFolderRequest() - delete_request.name = "projects/_/buckets/test-bucket/folders/test-folder-delete" - + delete_request.name = ( + "projects/_/buckets/test-bucket/folders/test-folder-delete" + ) + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() result = self.servicer.DeleteFolder(delete_request, context_stall) elapsed = time.time() - start_time - + self.assertIsInstance(result, empty_pb2.Empty) self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") @@ -125,20 +134,22 @@ def test_get_folder_stall(self): create_request.folder_id = "test-folder-get" context = self.mock_context() created_folder = self.servicer.CreateFolder(create_request, context) - + # Now get it with stall get_request = storage_control_pb2.GetFolderRequest() get_request.name = "projects/_/buckets/test-bucket/folders/test-folder-get" - + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() folder = self.servicer.GetFolder(get_request, context_stall) elapsed = time.time() - start_time - + self.assertIsNotNone(folder) - self.assertEqual(folder.name, "projects/_/buckets/test-bucket/folders/test-folder-get") + self.assertEqual( + folder.name, "projects/_/buckets/test-bucket/folders/test-folder-get" + ) self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") def test_list_folders_stall(self): @@ -150,18 +161,18 @@ def test_list_folders_stall(self): create_request.folder_id = f"test-folder-list-{i}" context = self.mock_context() self.servicer.CreateFolder(create_request, context) - + # List with stall list_request = storage_control_pb2.ListFoldersRequest() list_request.parent = "projects/_/buckets/test-bucket" - + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() response = self.servicer.ListFolders(list_request, context_stall) elapsed = time.time() - start_time - + self.assertIsNotNone(response) self.assertGreaterEqual(len(response.folders), 3) self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") @@ -174,19 +185,23 @@ def test_rename_folder_stall(self): create_request.folder_id = "test-folder-rename-src" context = self.mock_context() self.servicer.CreateFolder(create_request, context) - + # Rename with stall rename_request = storage_control_pb2.RenameFolderRequest() - rename_request.name = "projects/_/buckets/test-bucket/folders/test-folder-rename-src" - rename_request.destination_folder_id = "projects/_/buckets/test-bucket/test-folder-rename-dst" - + rename_request.name = ( + "projects/_/buckets/test-bucket/folders/test-folder-rename-src" + ) + rename_request.destination_folder_id = ( + "projects/_/buckets/test-bucket/test-folder-rename-dst" + ) + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() folder = self.servicer.RenameFolder(rename_request, context_stall) elapsed = time.time() - start_time - + self.assertIsNotNone(folder) self.assertGreaterEqual(elapsed, 1.0, "Should stall for at least 1 second") @@ -196,56 +211,62 @@ def test_multiple_stalls_and_no_stall(self): request1 = storage_control_pb2.CreateFolderRequest() request1.parent = "projects/_/buckets/test-bucket" request1.folder_id = "test-folder-multi-1" - + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() folder1 = self.servicer.CreateFolder(request1, context_stall) elapsed1 = time.time() - start_time - + self.assertIsNotNone(folder1) - self.assertGreaterEqual(elapsed1, 1.0, "First call should stall for at least 1 second") - + self.assertGreaterEqual( + elapsed1, 1.0, "First call should stall for at least 1 second" + ) + # Second call with stall metadata request2 = storage_control_pb2.CreateFolderRequest() request2.parent = "projects/_/buckets/test-bucket" request2.folder_id = "test-folder-multi-2" - + context_stall2 = self.mock_context(metadata) - + start_time = time.time() folder2 = self.servicer.CreateFolder(request2, context_stall2) elapsed2 = time.time() - start_time - + self.assertIsNotNone(folder2) - self.assertGreaterEqual(elapsed2, 1.0, "Second call should stall for at least 1 second") - + self.assertGreaterEqual( + elapsed2, 1.0, "Second call should stall for at least 1 second" + ) + # Third call without stall metadata request3 = storage_control_pb2.CreateFolderRequest() request3.parent = "projects/_/buckets/test-bucket" request3.folder_id = "test-folder-multi-3" - + context_no_stall = self.mock_context() - + start_time = time.time() folder3 = self.servicer.CreateFolder(request3, context_no_stall) elapsed3 = time.time() - start_time - + self.assertIsNotNone(folder3) - self.assertLess(elapsed3, 1.0, "Third call should complete quickly without stall") + self.assertLess( + elapsed3, 1.0, "Third call should complete quickly without stall" + ) def test_get_storage_layout_no_stall(self): """Test get storage layout without stall instruction.""" request = storage_control_pb2.GetStorageLayoutRequest() request.name = "projects/_/buckets/test-bucket/storageLayout" - + context = self.mock_context() - + start_time = time.time() layout = self.servicer.GetStorageLayout(request, context) elapsed = time.time() - start_time - + self.assertIsNotNone(layout) self.assertEqual(layout.name, "projects/_/buckets/test-bucket/storageLayout") self.assertLess(elapsed, 1.0, "Should complete quickly without stall") @@ -254,14 +275,14 @@ def test_get_storage_layout_stall(self): """Test get storage layout with stall instruction.""" request = storage_control_pb2.GetStorageLayoutRequest() request.name = "projects/_/buckets/test-bucket/storageLayout" - + metadata = [("x-goog-emulator-instructions", "stall-for-1s")] context_stall = self.mock_context(metadata) - + start_time = time.time() layout = self.servicer.GetStorageLayout(request, context_stall) elapsed = time.time() - start_time - + self.assertIsNotNone(layout) self.assertEqual(layout.name, "projects/_/buckets/test-bucket/storageLayout") self.assertEqual(layout.location, "US")