diff --git a/storage/google/cloud/storage/notification.py b/storage/google/cloud/storage/notification.py index 8ee287bf5fcf..89b1d3850d89 100644 --- a/storage/google/cloud/storage/notification.py +++ b/storage/google/cloud/storage/notification.py @@ -233,6 +233,10 @@ def create(self, client=None): client = self._require_client(client) + query_params = {} + if self.bucket.user_project is not None: + query_params['userProject'] = self.bucket.user_project + path = '/b/{}/notificationConfigs'.format(self.bucket.name) properties = self._properties.copy() properties['topic'] = _TOPIC_REF_FMT.format( @@ -240,6 +244,7 @@ def create(self, client=None): self._properties = client._connection.api_request( method='POST', path=path, + query_params=query_params, data=properties, ) @@ -262,8 +267,17 @@ def exists(self, client=None): raise ValueError("Notification not intialized by server") client = self._require_client(client) + + query_params = {} + if self.bucket.user_project is not None: + query_params['userProject'] = self.bucket.user_project + try: - client._connection.api_request(method='GET', path=self.path) + client._connection.api_request( + method='GET', + path=self.path, + query_params=query_params, + ) except NotFound: return False else: @@ -288,7 +302,16 @@ def reload(self, client=None): raise ValueError("Notification not intialized by server") client = self._require_client(client) - response = client._connection.api_request(method='GET', path=self.path) + + query_params = {} + if self.bucket.user_project is not None: + query_params['userProject'] = self.bucket.user_project + + response = client._connection.api_request( + method='GET', + path=self.path, + query_params=query_params, + ) self._set_properties(response) def delete(self, client=None): @@ -310,4 +333,13 @@ def delete(self, client=None): raise ValueError("Notification not intialized by server") client = self._require_client(client) - client._connection.api_request(method='DELETE', path=self.path) + + query_params = {} + if self.bucket.user_project is not None: + query_params['userProject'] = self.bucket.user_project + + client._connection.api_request( + method='DELETE', + path=self.path, + query_params=query_params, + ) diff --git a/storage/tests/system.py b/storage/tests/system.py index 0c8fd194b9de..2830fc33ebfb 100644 --- a/storage/tests/system.py +++ b/storage/tests/system.py @@ -932,3 +932,23 @@ def test_notification_explicit(self): notification.payload_format, self.payload_format()) finally: notification.delete() + + @unittest.skipUnless(USER_PROJECT, 'USER_PROJECT not set in environment.') + def test_notification_w_user_project(self): + new_bucket_name = 'notification-minimal' + unique_resource_id('-') + bucket = retry_429(Config.CLIENT.create_bucket)( + new_bucket_name, requester_pays=True) + self.case_buckets_to_delete.append(new_bucket_name) + with_user_project = Config.CLIENT.bucket( + new_bucket_name, user_project=USER_PROJECT) + self.assertEqual(list(with_user_project.list_notifications()), []) + notification = with_user_project.notification(self.TOPIC_NAME) + retry_429(notification.create)() + try: + self.assertTrue(notification.exists()) + self.assertIsNotNone(notification.notification_id) + notifications = list(with_user_project.list_notifications()) + self.assertEqual(len(notifications), 1) + self.assertEqual(notifications[0].topic_name, self.TOPIC_NAME) + finally: + notification.delete() diff --git a/storage/tests/unit/test_notification.py b/storage/tests/unit/test_notification.py index 2832c217c045..59b8ca4ff70f 100644 --- a/storage/tests/unit/test_notification.py +++ b/storage/tests/unit/test_notification.py @@ -67,10 +67,11 @@ def _make_client(self, project=BUCKET_PROJECT): return mock.Mock(project=project, spec=Client) - def _make_bucket(self, client, name=BUCKET_NAME): - bucket = mock.Mock(spec=['client', 'name']) + def _make_bucket(self, client, name=BUCKET_NAME, user_project=None): + bucket = mock.Mock(spec=['client', 'name', 'user_project']) bucket.client= client bucket.name = name + bucket.user_project = user_project return bucket def test_ctor_defaults(self): @@ -268,13 +269,15 @@ def test_create_w_defaults(self): api_request.assert_called_once_with( method='POST', path=self.CREATE_PATH, + query_params={}, data=data, ) def test_create_w_explicit_client(self): + USER_PROJECT = 'user-project-123' client = self._make_client() alt_client = self._make_client() - bucket = self._make_bucket(client) + bucket = self._make_bucket(client, user_project=USER_PROJECT) notification = self._make_one( bucket, self.TOPIC_NAME, topic_project=self.TOPIC_ALT_PROJECT, @@ -317,6 +320,7 @@ def test_create_w_explicit_client(self): api_request.assert_called_once_with( method='POST', path=self.CREATE_PATH, + query_params={'userProject': USER_PROJECT}, data=data, ) @@ -344,11 +348,13 @@ def test_exists_miss(self): api_request.assert_called_once_with( method='GET', path=self.NOTIFICATION_PATH, + query_params={}, ) def test_exists_hit(self): + USER_PROJECT = 'user-project-123' client = self._make_client() - bucket = self._make_bucket(client) + bucket = self._make_bucket(client, user_project=USER_PROJECT) alt_client = self._make_client() notification = self._make_one(bucket, self.TOPIC_NAME) notification._properties['id'] = self.NOTIFICATION_ID @@ -365,6 +371,7 @@ def test_exists_hit(self): api_request.assert_called_once_with( method='GET', path=self.NOTIFICATION_PATH, + query_params={'userProject': USER_PROJECT}, ) def test_reload_wo_notification_id(self): @@ -392,13 +399,15 @@ def test_reload_miss(self): api_request.assert_called_once_with( method='GET', path=self.NOTIFICATION_PATH, + query_params={}, ) def test_reload_hit(self): from google.cloud.storage.notification import NONE_PAYLOAD_FORMAT + USER_PROJECT = 'user-project-123' client = self._make_client() - bucket = self._make_bucket(client) + bucket = self._make_bucket(client, user_project=USER_PROJECT) alt_client = self._make_client() notification = self._make_one(bucket, self.TOPIC_NAME) notification._properties['id'] = self.NOTIFICATION_ID @@ -423,6 +432,7 @@ def test_reload_hit(self): api_request.assert_called_once_with( method='GET', path=self.NOTIFICATION_PATH, + query_params={'userProject': USER_PROJECT}, ) def test_delete_wo_notification_id(self): @@ -450,11 +460,13 @@ def test_delete_miss(self): api_request.assert_called_once_with( method='DELETE', path=self.NOTIFICATION_PATH, + query_params={}, ) def test_delete_hit(self): + USER_PROJECT = 'user-project-123' client = self._make_client() - bucket = self._make_bucket(client) + bucket = self._make_bucket(client, user_project=USER_PROJECT) alt_client = self._make_client() notification = self._make_one(bucket, self.TOPIC_NAME) notification._properties['id'] = self.NOTIFICATION_ID @@ -466,4 +478,5 @@ def test_delete_hit(self): api_request.assert_called_once_with( method='DELETE', path=self.NOTIFICATION_PATH, + query_params={'userProject': USER_PROJECT}, )