From edeb027733d6399ccd6b5373a88be555704cd843 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 13 Oct 2021 13:32:15 -0600 Subject: [PATCH 01/18] feat: add turbo replication support --- google/cloud/storage/bucket.py | 21 +++++++++++++++++++++ google/cloud/storage/client.py | 4 ++++ google/cloud/storage/constants.py | 12 ++++++++++++ tests/system/test_bucket.py | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index 77e87515b..b26bd7539 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -55,6 +55,8 @@ from google.cloud.storage.constants import REGIONAL_LEGACY_STORAGE_CLASS from google.cloud.storage.constants import REGION_LOCATION_TYPE from google.cloud.storage.constants import STANDARD_STORAGE_CLASS +from google.cloud.storage.constants import RPO_DEFAULT +from google.cloud.storage.constants import RPO_ASYNC_TURBO from google.cloud.storage.notification import BucketNotification from google.cloud.storage.notification import NONE_PAYLOAD_FORMAT from google.cloud.storage.retry import DEFAULT_RETRY @@ -633,6 +635,25 @@ def _set_properties(self, value): self._label_removals.clear() return super(Bucket, self)._set_properties(value) + @property + def rpo(self): + """Get the RPO (Recovery Point Objective) of this bucket + + "ASYNC_TURBO" or "DEFAULT" + :rtype: str + """ + return self._properties.get("rpo") + + @rpo.setter + def rpo(self, value): + """ + Set the RPO (Recovery Point Objective) of this bucket. + + :type value: str + :param value: "ASYNC_TURBO" or "DEFAULT" + """ + self._patch_property("rpo", value) + @property def user_project(self): """Project ID to be billed for API requests made via this bucket. diff --git a/google/cloud/storage/client.py b/google/cloud/storage/client.py index bef05ea91..0c1708e6e 100644 --- a/google/cloud/storage/client.py +++ b/google/cloud/storage/client.py @@ -832,6 +832,7 @@ def create_bucket( location=None, predefined_acl=None, predefined_default_object_acl=None, + rpo=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY, ): @@ -953,6 +954,9 @@ def create_bucket( if location is not None: properties["location"] = location + if rpo is not None: + properties["rpo"] = rpo + api_response = self._post_resource( "/b", properties, diff --git a/google/cloud/storage/constants.py b/google/cloud/storage/constants.py index 2e1c1dd2a..fcb0a4864 100644 --- a/google/cloud/storage/constants.py +++ b/google/cloud/storage/constants.py @@ -117,3 +117,15 @@ See: https://cloud.google.com/storage/docs/public-access-prevention """ + +RPO_ASYNC_TURBO = "ASYNC_TURBO" +"""Turbo Replication RPO + +See: https://cloud.google.com/storage/docs/managing-turbo-replication +""" + +RPO_DEFAULT = "DEFAULT" +"""Default RPO + +See: https://cloud.google.com/storage/docs/managing-turbo-replication +""" \ No newline at end of file diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index a9d638efb..67d7954d7 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -886,3 +886,21 @@ def test_new_bucket_created_w_enforced_pap( constants.PUBLIC_ACCESS_PREVENTION_INHERITED, ] assert not bucket.iam_configuration.uniform_bucket_level_access_enabled + +def test_new_bucket_with_rpo( + storage_client, buckets_to_delete, blobs_to_delete, +): + from google.cloud.storage import constants + + bucket_name = _helpers.unique_name("new-w-turbo-replication") + bucket = storage_client.create_bucket(bucket_name, location="NAM4", rpo=constants.RPO_ASYNC_TURBO) + buckets_to_delete.append(bucket) + + assert bucket.rpo == constants.RPO_ASYNC_TURBO + + bucket.rpo = constants.RPO_DEFAULT + bucket.patch() + + bucket_from_server = storage_client.get_bucket(bucket_name) + + assert bucket_from_server.rpo == constants.RPO_DEFAULT \ No newline at end of file From c03605338bd271c4c764a35f998bd67d0d95becf Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 13 Oct 2021 14:00:38 -0600 Subject: [PATCH 02/18] lintfix --- google/cloud/storage/constants.py | 2 +- tests/system/test_bucket.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/google/cloud/storage/constants.py b/google/cloud/storage/constants.py index fcb0a4864..132f4e40a 100644 --- a/google/cloud/storage/constants.py +++ b/google/cloud/storage/constants.py @@ -128,4 +128,4 @@ """Default RPO See: https://cloud.google.com/storage/docs/managing-turbo-replication -""" \ No newline at end of file +""" diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 67d7954d7..e34aafe61 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -893,7 +893,9 @@ def test_new_bucket_with_rpo( from google.cloud.storage import constants bucket_name = _helpers.unique_name("new-w-turbo-replication") - bucket = storage_client.create_bucket(bucket_name, location="NAM4", rpo=constants.RPO_ASYNC_TURBO) + bucket = storage_client.create_bucket( + bucket_name, location="NAM4", rpo=constants.RPO_ASYNC_TURBO + ) buckets_to_delete.append(bucket) assert bucket.rpo == constants.RPO_ASYNC_TURBO @@ -903,4 +905,4 @@ def test_new_bucket_with_rpo( bucket_from_server = storage_client.get_bucket(bucket_name) - assert bucket_from_server.rpo == constants.RPO_DEFAULT \ No newline at end of file + assert bucket_from_server.rpo == constants.RPO_DEFAULT From e7430026641138fc7f9e364b7b52005a46aa8613 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 13 Oct 2021 14:34:46 -0600 Subject: [PATCH 03/18] nother-lint-fix --- tests/system/test_bucket.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index e34aafe61..48c6bf900 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -858,7 +858,9 @@ def test_new_bucket_created_w_inherited_pap( @pytest.mark.skip(reason="Unspecified PAP is changing to inherited") def test_new_bucket_created_w_enforced_pap( - storage_client, buckets_to_delete, blobs_to_delete, + storage_client, + buckets_to_delete, + blobs_to_delete, ): from google.cloud.storage import constants From 2de90a585a5e0b06afc27ce4a2af930f3560e9f7 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 13 Oct 2021 15:03:40 -0600 Subject: [PATCH 04/18] hmm weird --- tests/system/test_bucket.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 48c6bf900..0c8e33f9a 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -890,7 +890,9 @@ def test_new_bucket_created_w_enforced_pap( assert not bucket.iam_configuration.uniform_bucket_level_access_enabled def test_new_bucket_with_rpo( - storage_client, buckets_to_delete, blobs_to_delete, + storage_client, + buckets_to_delete, + blobs_to_delete, ): from google.cloud.storage import constants From 8fa18a46a62a3b484586de0c464632a2a0772e8a Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 13 Oct 2021 15:28:43 -0600 Subject: [PATCH 05/18] i need to learn how to use lint better... --- tests/system/test_bucket.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 0c8e33f9a..80fb2fba4 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -889,6 +889,7 @@ def test_new_bucket_created_w_enforced_pap( ] assert not bucket.iam_configuration.uniform_bucket_level_access_enabled + def test_new_bucket_with_rpo( storage_client, buckets_to_delete, From b276aab63eed283b3b17bf0be9d210d853b5c7db Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 09:13:26 -0600 Subject: [PATCH 06/18] . --- tests/system/test_bucket.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 80fb2fba4..c00a44e84 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -858,9 +858,7 @@ def test_new_bucket_created_w_inherited_pap( @pytest.mark.skip(reason="Unspecified PAP is changing to inherited") def test_new_bucket_created_w_enforced_pap( - storage_client, - buckets_to_delete, - blobs_to_delete, + storage_client, buckets_to_delete, blobs_to_delete, ): from google.cloud.storage import constants From 896ce91e9a9af8b236b27313603316a1b03cc37b Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 09:53:01 -0600 Subject: [PATCH 07/18] . --- tests/system/test_bucket.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index c00a44e84..6a5d20c53 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -889,9 +889,7 @@ def test_new_bucket_created_w_enforced_pap( def test_new_bucket_with_rpo( - storage_client, - buckets_to_delete, - blobs_to_delete, + storage_client, buckets_to_delete, dblobs_to_delete, ): from google.cloud.storage import constants From 1032084814511e3931ac0cd85c3c34fa7ada2151 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 11:19:09 -0600 Subject: [PATCH 08/18] how about now? --- google/cloud/storage/bucket.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index b26bd7539..3a27dcdc6 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -55,8 +55,6 @@ from google.cloud.storage.constants import REGIONAL_LEGACY_STORAGE_CLASS from google.cloud.storage.constants import REGION_LOCATION_TYPE from google.cloud.storage.constants import STANDARD_STORAGE_CLASS -from google.cloud.storage.constants import RPO_DEFAULT -from google.cloud.storage.constants import RPO_ASYNC_TURBO from google.cloud.storage.notification import BucketNotification from google.cloud.storage.notification import NONE_PAYLOAD_FORMAT from google.cloud.storage.retry import DEFAULT_RETRY From 1f2a347edbf3b13a976783fbc5df44aefec8b071 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 12:29:48 -0600 Subject: [PATCH 09/18] take rpo out of constructor --- google/cloud/storage/client.py | 4 ---- tests/system/test_bucket.py | 12 +++++------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/google/cloud/storage/client.py b/google/cloud/storage/client.py index 0c1708e6e..bef05ea91 100644 --- a/google/cloud/storage/client.py +++ b/google/cloud/storage/client.py @@ -832,7 +832,6 @@ def create_bucket( location=None, predefined_acl=None, predefined_default_object_acl=None, - rpo=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY, ): @@ -954,9 +953,6 @@ def create_bucket( if location is not None: properties["location"] = location - if rpo is not None: - properties["rpo"] = rpo - api_response = self._post_resource( "/b", properties, diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 6a5d20c53..97f90984e 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -889,21 +889,19 @@ def test_new_bucket_created_w_enforced_pap( def test_new_bucket_with_rpo( - storage_client, buckets_to_delete, dblobs_to_delete, + storage_client, buckets_to_delete, blobs_to_delete, ): from google.cloud.storage import constants bucket_name = _helpers.unique_name("new-w-turbo-replication") - bucket = storage_client.create_bucket( - bucket_name, location="NAM4", rpo=constants.RPO_ASYNC_TURBO - ) + bucket = storage_client.create_bucket(bucket_name, location="NAM4") buckets_to_delete.append(bucket) - assert bucket.rpo == constants.RPO_ASYNC_TURBO + assert bucket.rpo == constants.RPO_DEFAULT - bucket.rpo = constants.RPO_DEFAULT + bucket.rpo = constants.RPO_ASYNC_TURBO bucket.patch() bucket_from_server = storage_client.get_bucket(bucket_name) - assert bucket_from_server.rpo == constants.RPO_DEFAULT + assert bucket_from_server.rpo == constants.RPO_ASYNC_TURBO From d046b1f9104c4a9c1326cc880fa6eac271c5d623 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 14:09:53 -0600 Subject: [PATCH 10/18] add unit tests --- tests/unit/test_bucket.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit/test_bucket.py b/tests/unit/test_bucket.py index 321de717c..45b41c0bd 100644 --- a/tests/unit/test_bucket.py +++ b/tests/unit/test_bucket.py @@ -25,6 +25,8 @@ from google.cloud.storage.constants import PUBLIC_ACCESS_PREVENTION_ENFORCED from google.cloud.storage.constants import PUBLIC_ACCESS_PREVENTION_INHERITED from google.cloud.storage.constants import PUBLIC_ACCESS_PREVENTION_UNSPECIFIED +from google.cloud.storage.constants import RPO_DEFAULT +from google.cloud.storage.constants import RPO_ASYNC_TURBO def _create_signing_credentials(): @@ -2476,6 +2478,13 @@ def test_location_type_getter_set(self): bucket = self._make_one(properties=properties) self.assertEqual(bucket.location_type, REGION_LOCATION_TYPE) + def test_rpo_getter_and_setter(self): + bucket = self._make_one() + bucket.rpo = RPO_ASYNC_TURBO + self.assertEqual(bucket.rpo, RPO_ASYNC_TURBO) + bucket.rpo = RPO_DEFAULT + self.assertEqual(bucket.rpo, RPO_DEFAULT) + def test_get_logging_w_prefix(self): NAME = "name" LOG_BUCKET = "logs" From 57f5df7bc2110e3f8c33c5b00850615a7cb0a220 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 15:06:24 -0600 Subject: [PATCH 11/18] add link to docs --- google/cloud/storage/bucket.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index 3a27dcdc6..5798cbef3 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -637,6 +637,8 @@ def _set_properties(self, value): def rpo(self): """Get the RPO (Recovery Point Objective) of this bucket + See: https://cloud.google.com/storage/docs/managing-turbo-replication + "ASYNC_TURBO" or "DEFAULT" :rtype: str """ @@ -647,6 +649,8 @@ def rpo(self, value): """ Set the RPO (Recovery Point Objective) of this bucket. + See: https://cloud.google.com/storage/docs/managing-turbo-replication + :type value: str :param value: "ASYNC_TURBO" or "DEFAULT" """ From 0ab5ce8c76a5317421b932d6376cb290cedc40e6 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Thu, 14 Oct 2021 15:24:29 -0600 Subject: [PATCH 12/18] ensure inclusion of "rpo" in bucket._changes --- tests/unit/test_bucket.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_bucket.py b/tests/unit/test_bucket.py index 45b41c0bd..9af60b862 100644 --- a/tests/unit/test_bucket.py +++ b/tests/unit/test_bucket.py @@ -2483,6 +2483,7 @@ def test_rpo_getter_and_setter(self): bucket.rpo = RPO_ASYNC_TURBO self.assertEqual(bucket.rpo, RPO_ASYNC_TURBO) bucket.rpo = RPO_DEFAULT + self.assertIn("rpo", bucket._changes) self.assertEqual(bucket.rpo, RPO_DEFAULT) def test_get_logging_w_prefix(self): From 6dddfe2843f9bb7379c9550111d7ee9c81175ea6 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Tue, 19 Oct 2021 15:49:37 -0600 Subject: [PATCH 13/18] add rpo samples --- samples/snippets/rpo_test.py | 60 +++++++++++++++++++ ...storage_create_bucket_turbo_replication.py | 48 +++++++++++++++ samples/snippets/storage_get_rpo.py | 46 ++++++++++++++ .../snippets/storage_set_rpo_async_turbo.py | 48 +++++++++++++++ samples/snippets/storage_set_rpo_default.py | 48 +++++++++++++++ 5 files changed, 250 insertions(+) create mode 100644 samples/snippets/rpo_test.py create mode 100644 samples/snippets/storage_create_bucket_turbo_replication.py create mode 100644 samples/snippets/storage_get_rpo.py create mode 100644 samples/snippets/storage_set_rpo_async_turbo.py create mode 100644 samples/snippets/storage_set_rpo_default.py diff --git a/samples/snippets/rpo_test.py b/samples/snippets/rpo_test.py new file mode 100644 index 000000000..f5f79aa03 --- /dev/null +++ b/samples/snippets/rpo_test.py @@ -0,0 +1,60 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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 uuid +import pytest +from google.cloud import storage + +import storage_get_rpo +import storage_set_rpo_async_turbo +import storage_set_rpo_default +import storage_create_bucket_turbo_replication + + +@pytest.fixture +def dr_bucket(): + """Yields a dual region bucket that is deleted after the test completes.""" + bucket = None + while bucket is None or bucket.exists(): + bucket_name = "bucket-lock-{}".format(uuid.uuid4()) + bucket = storage.Client().bucket(bucket_name) + bucket.location = "NAM4" + bucket.create() + yield bucket + bucket.delete(force=True) + + +def test_get_rpo(dr_bucket, capsys): + storage_get_rpo.get_rpo(dr_bucket.name) + out, _ = capsys.readouterr() + assert f"RPO for {dr_bucket.name} is DEFAULT." in out + + +def test_set_rpo_async_turbo(dr_bucket, capsys): + storage_set_rpo_async_turbo.set_rpo_async_turbo(dr_bucket.name) + out, _ = capsys.readouterr() + assert f"RPO is ASYNC_TURBO for {dr_bucket.name}." in out + + +def test_set_rpo_default(dr_bucket, capsys): + storage_set_rpo_default.set_rpo_default(dr_bucket.name) + out, _ = capsys.readouterr() + assert f"RPO is DEFAULT for {dr_bucket.name}." in out + + +def test_create_bucket_turbo_replication(capsys): + bucket_name = "test-rpo-{}".format(uuid.uuid4()) + storage_create_bucket_turbo_replication.create_bucket_turbo_replication(bucket_name) + out, _ = capsys.readouterr() + assert f"{bucket_name} created with RPO ASYNC_TURBO in NAM4." in out diff --git a/samples/snippets/storage_create_bucket_turbo_replication.py b/samples/snippets/storage_create_bucket_turbo_replication.py new file mode 100644 index 000000000..68f0ba482 --- /dev/null +++ b/samples/snippets/storage_create_bucket_turbo_replication.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# 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 new bucket with dual-region and turbo replication. +This sample is used on this page: + https://cloud.google.com/storage/docs/managing-turbo-replication +For more information, see README.md. +""" + +# [START storage_create_bucket_turbo_replication] + +from google.cloud import storage +from google.cloud.storage.constants import RPO_ASYNC_TURBO + + +def create_bucket_turbo_replication(bucket_name): + """Creates dual-region bucket with turbo replication enabled.""" + # The ID of your GCS bucket + # bucket_name = "my-bucket" + + storage_client = storage.Client() + bucket = storage_client.bucket(bucket_name) + bucket.location = "NAM4" + bucket.rpo = RPO_ASYNC_TURBO + bucket.create() + + print(f"{bucket.name} created with RPO {bucket.rpo} in {bucket.location}.") + + +# [END storage_create_bucket_turbo_replication] + +if __name__ == "__main__": + create_bucket_turbo_replication(bucket_name=sys.argv[1]) diff --git a/samples/snippets/storage_get_rpo.py b/samples/snippets/storage_get_rpo.py new file mode 100644 index 000000000..12f06b825 --- /dev/null +++ b/samples/snippets/storage_get_rpo.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# 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 gets RPO (Recovery Point Objective) of a bucket +This sample is used on this page: + https://cloud.google.com/storage/docs/managing-turbo-replication +For more information, see README.md. +""" + +# [START storage_get_rpo] + +from google.cloud import storage + + +def get_rpo(bucket_name): + """Gets the RPO of the bucket""" + # The ID of your GCS bucket + # bucket_name = "my-bucket" + + storage_client = storage.Client() + bucket = storage_client.get_bucket(bucket_name) + + rpo = bucket.rpo + + print(f"RPO for {bucket.name} is {rpo}.") + + +# [END storage_get_rpo] + +if __name__ == "__main__": + get_rpo(bucket_name=sys.argv[1]) diff --git a/samples/snippets/storage_set_rpo_async_turbo.py b/samples/snippets/storage_set_rpo_async_turbo.py new file mode 100644 index 000000000..315697944 --- /dev/null +++ b/samples/snippets/storage_set_rpo_async_turbo.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# 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 sets RPO (Recovery Point Objective) to ASYNC_TURBO +This sample is used on this page: + https://cloud.google.com/storage/docs/managing-turbo-replication +For more information, see README.md. +""" + +# [START storage_set_rpo_async_turbo] + +from google.cloud import storage +from google.cloud.storage.constants import RPO_ASYNC_TURBO + + +def set_rpo_async_turbo(bucket_name): + """Sets the RPO to ASYNC_TURBO, enabling the turbo replication feature""" + # The ID of your GCS bucket + # bucket_name = "my-bucket" + + storage_client = storage.Client() + bucket = storage_client.get_bucket(bucket_name) + + bucket.rpo = RPO_ASYNC_TURBO + bucket.patch() + + print(f"RPO is ASYNC_TURBO for {bucket.name}.") + + +# [END storage_set_rpo_async_turbo] + +if __name__ == "__main__": + set_rpo_async_turbo(bucket_name=sys.argv[1]) diff --git a/samples/snippets/storage_set_rpo_default.py b/samples/snippets/storage_set_rpo_default.py new file mode 100644 index 000000000..4c4e78064 --- /dev/null +++ b/samples/snippets/storage_set_rpo_default.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# 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 sets RPO (Recovery Point Objective) to default +This sample is used on this page: + https://cloud.google.com/storage/docs/managing-turbo-replication +For more information, see README.md. +""" + +# [START storage_set_rpo_default] + +from google.cloud import storage +from google.cloud.storage.constants import RPO_DEFAULT + + +def set_rpo_default(bucket_name): + """Sets the RPO to DEFAULT, disabling the turbo replication feature""" + # The ID of your GCS bucket + # bucket_name = "my-bucket" + + storage_client = storage.Client() + bucket = storage_client.get_bucket(bucket_name) + + bucket.rpo = RPO_DEFAULT + bucket.patch() + + print(f"RPO is DEFAULT for {bucket.name}.") + + +# [END storage_set_rpo_default] + +if __name__ == "__main__": + set_rpo_default(bucket_name=sys.argv[1]) From b43e04fa5072cd7d1aaf322519adaa58afe08510 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Tue, 19 Oct 2021 15:58:35 -0600 Subject: [PATCH 14/18] lint it --- samples/snippets/rpo_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/snippets/rpo_test.py b/samples/snippets/rpo_test.py index f5f79aa03..bfedd0d30 100644 --- a/samples/snippets/rpo_test.py +++ b/samples/snippets/rpo_test.py @@ -13,13 +13,14 @@ # limitations under the License. import uuid -import pytest + from google.cloud import storage +import pytest +import storage_create_bucket_turbo_replication import storage_get_rpo import storage_set_rpo_async_turbo import storage_set_rpo_default -import storage_create_bucket_turbo_replication @pytest.fixture From 325e5eba278648c9cbd75a74463b10a4344a8cbb Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 20 Oct 2021 14:03:19 -0600 Subject: [PATCH 15/18] address cathys nits --- samples/snippets/rpo_test.py | 20 +++++++++---------- samples/snippets/storage_get_rpo.py | 2 +- .../snippets/storage_set_rpo_async_turbo.py | 2 +- samples/snippets/storage_set_rpo_default.py | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/snippets/rpo_test.py b/samples/snippets/rpo_test.py index bfedd0d30..d084710a9 100644 --- a/samples/snippets/rpo_test.py +++ b/samples/snippets/rpo_test.py @@ -24,7 +24,7 @@ @pytest.fixture -def dr_bucket(): +def dual_region_bucket(): """Yields a dual region bucket that is deleted after the test completes.""" bucket = None while bucket is None or bucket.exists(): @@ -36,22 +36,22 @@ def dr_bucket(): bucket.delete(force=True) -def test_get_rpo(dr_bucket, capsys): - storage_get_rpo.get_rpo(dr_bucket.name) +def test_get_rpo(dual_region_bucket, capsys): + storage_get_rpo.get_rpo(dual_region_bucket.name) out, _ = capsys.readouterr() - assert f"RPO for {dr_bucket.name} is DEFAULT." in out + assert f"RPO for {dual_region_bucket.name} is DEFAULT." in out -def test_set_rpo_async_turbo(dr_bucket, capsys): - storage_set_rpo_async_turbo.set_rpo_async_turbo(dr_bucket.name) +def test_set_rpo_async_turbo(dual_region_bucket, capsys): + storage_set_rpo_async_turbo.set_rpo_async_turbo(dual_region_bucket.name) out, _ = capsys.readouterr() - assert f"RPO is ASYNC_TURBO for {dr_bucket.name}." in out + assert f"RPO is ASYNC_TURBO for {dual_region_bucket.name}." in out -def test_set_rpo_default(dr_bucket, capsys): - storage_set_rpo_default.set_rpo_default(dr_bucket.name) +def test_set_rpo_default(dual_region_bucket, capsys): + storage_set_rpo_default.set_rpo_default(dual_region_bucket.name) out, _ = capsys.readouterr() - assert f"RPO is DEFAULT for {dr_bucket.name}." in out + assert f"RPO is DEFAULT for {dual_region_bucket.name}." in out def test_create_bucket_turbo_replication(capsys): diff --git a/samples/snippets/storage_get_rpo.py b/samples/snippets/storage_get_rpo.py index 12f06b825..fc70381c4 100644 --- a/samples/snippets/storage_get_rpo.py +++ b/samples/snippets/storage_get_rpo.py @@ -33,7 +33,7 @@ def get_rpo(bucket_name): # bucket_name = "my-bucket" storage_client = storage.Client() - bucket = storage_client.get_bucket(bucket_name) + bucket = storage_client.bucket(bucket_name) rpo = bucket.rpo diff --git a/samples/snippets/storage_set_rpo_async_turbo.py b/samples/snippets/storage_set_rpo_async_turbo.py index 315697944..10b4c67a3 100644 --- a/samples/snippets/storage_set_rpo_async_turbo.py +++ b/samples/snippets/storage_set_rpo_async_turbo.py @@ -34,7 +34,7 @@ def set_rpo_async_turbo(bucket_name): # bucket_name = "my-bucket" storage_client = storage.Client() - bucket = storage_client.get_bucket(bucket_name) + bucket = storage_client.bucket(bucket_name) bucket.rpo = RPO_ASYNC_TURBO bucket.patch() diff --git a/samples/snippets/storage_set_rpo_default.py b/samples/snippets/storage_set_rpo_default.py index 4c4e78064..8d41b1fe0 100644 --- a/samples/snippets/storage_set_rpo_default.py +++ b/samples/snippets/storage_set_rpo_default.py @@ -34,7 +34,7 @@ def set_rpo_default(bucket_name): # bucket_name = "my-bucket" storage_client = storage.Client() - bucket = storage_client.get_bucket(bucket_name) + bucket = storage_client.bucket(bucket_name) bucket.rpo = RPO_DEFAULT bucket.patch() From 93c2af6d5bd3972b1947fda61c073939034a37ea Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Wed, 20 Oct 2021 14:15:43 -0600 Subject: [PATCH 16/18] fix a little test thing --- samples/snippets/storage_get_rpo.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/snippets/storage_get_rpo.py b/samples/snippets/storage_get_rpo.py index fc70381c4..29ae186fa 100644 --- a/samples/snippets/storage_get_rpo.py +++ b/samples/snippets/storage_get_rpo.py @@ -25,6 +25,7 @@ # [START storage_get_rpo] from google.cloud import storage +from google.cloud.storage.constants import RPO_DEFAULT def get_rpo(bucket_name): @@ -35,6 +36,7 @@ def get_rpo(bucket_name): storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) + bucket.rpo = RPO_DEFAULT rpo = bucket.rpo print(f"RPO for {bucket.name} is {rpo}.") From d671e4b9307cf7f75ac7fb42d2080358e69ae7fe Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Tue, 18 Jan 2022 09:38:05 -0700 Subject: [PATCH 17/18] start to fix weirdness, creating issue to address more fully --- samples/snippets/rpo_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/rpo_test.py b/samples/snippets/rpo_test.py index d084710a9..fb758b9e8 100644 --- a/samples/snippets/rpo_test.py +++ b/samples/snippets/rpo_test.py @@ -27,7 +27,7 @@ def dual_region_bucket(): """Yields a dual region bucket that is deleted after the test completes.""" bucket = None - while bucket is None or bucket.exists(): + while bucket is None: bucket_name = "bucket-lock-{}".format(uuid.uuid4()) bucket = storage.Client().bucket(bucket_name) bucket.location = "NAM4" From e6595b06dc6105aa2601631286250cf471bd9203 Mon Sep 17 00:00:00 2001 From: Aaron Gabriel Neyer Date: Tue, 18 Jan 2022 10:29:04 -0700 Subject: [PATCH 18/18] change it back --- samples/snippets/rpo_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/rpo_test.py b/samples/snippets/rpo_test.py index fb758b9e8..d084710a9 100644 --- a/samples/snippets/rpo_test.py +++ b/samples/snippets/rpo_test.py @@ -27,7 +27,7 @@ def dual_region_bucket(): """Yields a dual region bucket that is deleted after the test completes.""" bucket = None - while bucket is None: + while bucket is None or bucket.exists(): bucket_name = "bucket-lock-{}".format(uuid.uuid4()) bucket = storage.Client().bucket(bucket_name) bucket.location = "NAM4"