From 4f7ee13f179c2d80b6462af744e0f66954988b7b Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Fri, 27 Sep 2019 10:55:13 -0400 Subject: [PATCH] feat(storage): support predefined ACLs in 'Bucket.create' Closes #9295. --- storage/google/cloud/storage/bucket.py | 30 +++++++++++++- storage/tests/unit/test_bucket.py | 54 ++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py index cf272928119c..4ff76e4b037e 100644 --- a/storage/google/cloud/storage/bucket.py +++ b/storage/google/cloud/storage/bucket.py @@ -595,7 +595,14 @@ def exists(self, client=None): except NotFound: return False - def create(self, client=None, project=None, location=None): + def create( + self, + client=None, + project=None, + location=None, + predefined_acl=None, + predefined_default_object_acl=None, + ): """Creates current bucket. If the bucket already exists, will raise @@ -622,6 +629,16 @@ def create(self, client=None, project=None, location=None): :param location: 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 + + :type predefined_acl: str + :param predefined_acl: + Optional. Name of predefined ACL to apply to bucket. See: + https://cloud.google.com/storage/docs/access-control/lists#predefined-acl + + :type predefined_default_object_acl: str + :param predefined_default_object_acl: + Optional. Name of predefined ACL to apply to bucket's objects. See: + https://cloud.google.com/storage/docs/access-control/lists#predefined-acl """ if self.user_project is not None: raise ValueError("Cannot create bucket with 'user_project' set.") @@ -635,6 +652,17 @@ def create(self, client=None, project=None, location=None): raise ValueError("Client project not set: pass an explicit project.") query_params = {"project": project} + + if predefined_acl is not None: + predefined_acl = BucketACL.validate_predefined(predefined_acl) + query_params["predefinedAcl"] = predefined_acl + + if predefined_default_object_acl is not None: + predefined_default_object_acl = DefaultObjectACL.validate_predefined( + predefined_default_object_acl + ) + query_params["predefinedDefaultObjectAcl"] = predefined_default_object_acl + properties = {key: self._properties[key] for key in self._changes} properties["name"] = self.name diff --git a/storage/tests/unit/test_bucket.py b/storage/tests/unit/test_bucket.py index b09aea81f515..de943339e200 100644 --- a/storage/tests/unit/test_bucket.py +++ b/storage/tests/unit/test_bucket.py @@ -646,6 +646,60 @@ def test_create_w_extra_properties(self): self.assertEqual(kw["query_params"], {"project": PROJECT}) self.assertEqual(kw["data"], DATA) + def test_create_w_predefined_acl_invalid(self): + PROJECT = "PROJECT" + BUCKET_NAME = "bucket-name" + DATA = {"name": BUCKET_NAME} + connection = _Connection(DATA) + client = _Client(connection, project=PROJECT) + bucket = self._make_one(client=client, name=BUCKET_NAME) + + with self.assertRaises(ValueError): + bucket.create(predefined_acl="bogus") + + def test_create_w_predefined_acl_valid(self): + PROJECT = "PROJECT" + BUCKET_NAME = "bucket-name" + DATA = {"name": BUCKET_NAME} + connection = _Connection(DATA) + client = _Client(connection, project=PROJECT) + bucket = self._make_one(client=client, name=BUCKET_NAME) + bucket.create(predefined_acl="publicRead") + + kw, = connection._requested + self.assertEqual(kw["method"], "POST") + self.assertEqual(kw["path"], "/b") + expected_qp = {"project": PROJECT, "predefinedAcl": "publicRead"} + self.assertEqual(kw["query_params"], expected_qp) + self.assertEqual(kw["data"], DATA) + + def test_create_w_predefined_default_object_acl_invalid(self): + PROJECT = "PROJECT" + BUCKET_NAME = "bucket-name" + DATA = {"name": BUCKET_NAME} + connection = _Connection(DATA) + client = _Client(connection, project=PROJECT) + bucket = self._make_one(client=client, name=BUCKET_NAME) + + with self.assertRaises(ValueError): + bucket.create(predefined_default_object_acl="bogus") + + def test_create_w_predefined_default_object_acl_valid(self): + PROJECT = "PROJECT" + BUCKET_NAME = "bucket-name" + DATA = {"name": BUCKET_NAME} + connection = _Connection(DATA) + client = _Client(connection, project=PROJECT) + bucket = self._make_one(client=client, name=BUCKET_NAME) + bucket.create(predefined_default_object_acl="publicRead") + + kw, = connection._requested + self.assertEqual(kw["method"], "POST") + self.assertEqual(kw["path"], "/b") + expected_qp = {"project": PROJECT, "predefinedDefaultObjectAcl": "publicRead"} + self.assertEqual(kw["query_params"], expected_qp) + self.assertEqual(kw["data"], DATA) + def test_acl_property(self): from google.cloud.storage.acl import BucketACL