diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index 0fa5894b7..85c9302f7 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -2316,7 +2316,7 @@ def location(self): """Retrieve location configured for this bucket. See https://cloud.google.com/storage/docs/json_api/v1/buckets and - https://cloud.google.com/storage/docs/bucket-locations + https://cloud.google.com/storage/docs/locations Returns ``None`` if the property has not been set before creation, or if the bucket's resource has not been loaded from the server. diff --git a/google/cloud/storage/client.py b/google/cloud/storage/client.py index 3b335cf7b..8b63a0198 100644 --- a/google/cloud/storage/client.py +++ b/google/cloud/storage/client.py @@ -875,8 +875,9 @@ def create_bucket( made via created bucket. location (str): (Optional) The location of the bucket. If not passed, - the default location, US, will be used. See - https://cloud.google.com/storage/docs/bucket-locations + the default location, US, will be used. If specifying a dual-region, + can be specified as a string, e.g., 'US-CENTRAL1+US-WEST1'. See: + https://cloud.google.com/storage/docs/locations predefined_acl (str): (Optional) Name of predefined ACL to apply to bucket. See: https://cloud.google.com/storage/docs/access-control/lists#predefined-acl diff --git a/samples/README.md b/samples/README.md index fbbc45aa2..2d9080067 100644 --- a/samples/README.md +++ b/samples/README.md @@ -63,6 +63,7 @@ for more detailed instructions. * [CORS Configuration](#cors-configuration) * [Create Bucket](#create-bucket) * [Create Bucket Class Location](#create-bucket-class-location) +* [Create Bucket Dual Region](#create-bucket-dual-region) * [Create Bucket Notifications](#create-bucket-notifications) * [Create Bucket Turbo Replication](#create-bucket-turbo-replication) * [Create HMAC Key](#create-hmac-key) @@ -316,6 +317,15 @@ View the [source code](https://github.com/googleapis/python-storage/blob/main/sa `python storage_create_bucket_class_location.py ` +----- +### Create Bucket Dual Region +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/python-storage&page=editor&open_in_editor=samples/snippets/storage_create_bucket_dual_region.py,samples/README.md) + +View the [source code](https://github.com/googleapis/python-storage/blob/main/samples/snippets/storage_create_bucket_dual_region.py). To run this sample: + + +`python storage_create_bucket_dual_region.py ` + ----- ### Create Bucket Notifications [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/python-storage&page=editor&open_in_editor=samples/snippets/storage_create_bucket_notifications.py,samples/README.md) diff --git a/samples/snippets/snippets_test.py b/samples/snippets/snippets_test.py index 581134102..7a5a3a64f 100644 --- a/samples/snippets/snippets_test.py +++ b/samples/snippets/snippets_test.py @@ -36,6 +36,7 @@ import storage_copy_file_archived_generation import storage_cors_configuration import storage_create_bucket_class_location +import storage_create_bucket_dual_region import storage_define_bucket_website_configuration import storage_delete_file import storage_delete_file_archived_generation @@ -433,6 +434,16 @@ def test_create_bucket_class_location(test_bucket_create): assert bucket.storage_class == "COLDLINE" +def test_create_bucket_dual_region(test_bucket_create, capsys): + region_1 = "US-EAST1" + region_2 = "US-WEST1" + storage_create_bucket_dual_region.create_bucket_dual_region( + test_bucket_create.name, region_1, region_2 + ) + out, _ = capsys.readouterr() + assert f"Bucket {test_bucket_create.name} created in {region_1}+{region_2}" in out + + def test_bucket_delete_default_kms_key(test_bucket, capsys): test_bucket.default_kms_key_name = KMS_KEY test_bucket.patch() diff --git a/samples/snippets/storage_create_bucket_dual_region.py b/samples/snippets/storage_create_bucket_dual_region.py new file mode 100644 index 000000000..e6f4ac01f --- /dev/null +++ b/samples/snippets/storage_create_bucket_dual_region.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +# Copyright 2022 Google LLC. All Rights Reserved. +# +# 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. + +import sys + +""" +Sample that creates a dual region bucket. +""" + +# [START storage_create_bucket_dual_region] +from google.cloud import storage + + +def create_bucket_dual_region(bucket_name, region_1, region_2): + """Creates a Dual-Region Bucket with provided locations.""" + # The ID of your GCS bucket + # bucket_name = "your-bucket-name" + + # The bucket's pair of regions. Case-insensitive. + # See this documentation for other valid locations: + # https://cloud.google.com/storage/docs/locations + # region_1 = "US-EAST1" + # region_2 = "US-WEST1" + + storage_client = storage.Client() + storage_client.create_bucket(bucket_name, location=f"{region_1}+{region_2}") + + print(f"Bucket {bucket_name} created in {region_1}+{region_2}.") + + +# [END storage_create_bucket_dual_region] + + +if __name__ == "__main__": + create_bucket_dual_region( + bucket_name=sys.argv[1], region_1=sys.argv[2], region_2=sys.argv[3] + ) diff --git a/tests/system/test_client.py b/tests/system/test_client.py index 3329ee7a3..9d9526a03 100644 --- a/tests/system/test_client.py +++ b/tests/system/test_client.py @@ -64,6 +64,27 @@ def test_create_bucket_simple(storage_client, buckets_to_delete): assert created.name == new_bucket_name +def test_create_bucket_dual_region(storage_client, buckets_to_delete): + from google.cloud.storage.constants import DUAL_REGION_LOCATION_TYPE + + new_bucket_name = _helpers.unique_name("dual-region-bucket") + region_1 = "US-EAST1" + region_2 = "US-WEST1" + dual_region = f"{region_1}+{region_2}" + + with pytest.raises(exceptions.NotFound): + storage_client.get_bucket(new_bucket_name) + + created = _helpers.retry_429_503(storage_client.create_bucket)( + new_bucket_name, location=dual_region + ) + buckets_to_delete.append(created) + + assert created.name == new_bucket_name + assert created.location == dual_region + assert created.location_type == DUAL_REGION_LOCATION_TYPE + + def test_list_buckets(storage_client, buckets_to_delete): buckets_to_create = [ _helpers.unique_name("new"),