From add3c01f0974e22df7f0b50504d5e83e4235fd81 Mon Sep 17 00:00:00 2001 From: cojenco Date: Wed, 22 May 2024 10:10:58 -0700 Subject: [PATCH] feat: support HNS enablement in bucket metadata (#1278) * feat: support HNS enablement in bucket metadata * update docstrings --- google/cloud/storage/bucket.py | 29 +++++++++++++++++++++++++++++ tests/system/test_bucket.py | 29 +++++++++++++++++++++++++++++ tests/unit/test_bucket.py | 13 +++++++++++++ 3 files changed, 71 insertions(+) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index 15fb408e8..7b6421d29 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -2957,6 +2957,35 @@ def object_retention_mode(self): if object_retention is not None: return object_retention.get("mode") + @property + def hierarchical_namespace_enabled(self): + """Whether hierarchical namespace is enabled for this bucket. + + :setter: Update whether hierarchical namespace is enabled for this bucket. + :getter: Query whether hierarchical namespace is enabled for this bucket. + + :rtype: bool + :returns: True if enabled, else False. + """ + hns = self._properties.get("hierarchicalNamespace", {}) + return hns.get("enabled") + + @hierarchical_namespace_enabled.setter + def hierarchical_namespace_enabled(self, value): + """Enable or disable hierarchical namespace at the bucket-level. + + :type value: convertible to boolean + :param value: If true, enable hierarchical namespace for this bucket. + If false, disable hierarchical namespace for this bucket. + + .. note:: + To enable hierarchical namespace, you must set it at bucket creation time. + Currently, hierarchical namespace configuration cannot be changed after bucket creation. + """ + hns = self._properties.get("hierarchicalNamespace", {}) + hns["enabled"] = bool(value) + self._patch_property("hierarchicalNamespace", hns) + def configure_website(self, main_page_suffix=None, not_found_page=None): """Configure website-related properties. diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 735570f6c..270a77ad1 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -1236,3 +1236,32 @@ def test_soft_delete_policy( bucket.soft_delete_policy.retention_duration_seconds = new_duration_secs bucket.patch() assert bucket.soft_delete_policy.retention_duration_seconds == new_duration_secs + + +def test_new_bucket_with_hierarchical_namespace( + storage_client, + buckets_to_delete, +): + # Test new bucket without specifying hierarchical namespace + bucket_name = _helpers.unique_name("new-wo-hns") + bucket_obj = storage_client.bucket(bucket_name) + bucket = storage_client.create_bucket(bucket_obj) + buckets_to_delete.append(bucket) + assert bucket.hierarchical_namespace_enabled is None + + # Test new bucket with hierarchical namespace disabled + bucket_name = _helpers.unique_name("new-hns-disabled") + bucket_obj = storage_client.bucket(bucket_name) + bucket_obj.hierarchical_namespace_enabled = False + bucket = storage_client.create_bucket(bucket_obj) + buckets_to_delete.append(bucket) + assert bucket.hierarchical_namespace_enabled is False + + # Test new bucket with hierarchical namespace enabled + bucket_name = _helpers.unique_name("new-hns-enabled") + bucket_obj = storage_client.bucket(bucket_name) + bucket_obj.hierarchical_namespace_enabled = True + bucket_obj.iam_configuration.uniform_bucket_level_access_enabled = True + bucket = storage_client.create_bucket(bucket_obj) + buckets_to_delete.append(bucket) + assert bucket.hierarchical_namespace_enabled is True diff --git a/tests/unit/test_bucket.py b/tests/unit/test_bucket.py index 2df41c3ff..030fba72b 100644 --- a/tests/unit/test_bucket.py +++ b/tests/unit/test_bucket.py @@ -3163,6 +3163,19 @@ def test_soft_delete_policy_setter(self): self.assertTrue("softDeletePolicy" in bucket._changes) self.assertEqual(bucket.soft_delete_policy.retention_duration_seconds, seconds) + def test_hierarchical_namespace_enabled_getter_and_setter(self): + # Test hierarchical_namespace configuration unset + bucket = self._make_one() + self.assertIsNone(bucket.hierarchical_namespace_enabled) + + # Test hierarchical_namespace configuration explicitly set + properties = {"hierarchicalNamespace": {"enabled": True}} + bucket = self._make_one(properties=properties) + self.assertTrue(bucket.hierarchical_namespace_enabled) + bucket.hierarchical_namespace_enabled = False + self.assertIn("hierarchicalNamespace", bucket._changes) + self.assertFalse(bucket.hierarchical_namespace_enabled) + def test_configure_website_defaults(self): NAME = "name" UNSET = {"website": {"mainPageSuffix": None, "notFoundPage": None}}