Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storage): add get notification method #77

Merged
merged 5 commits into from Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 42 additions & 2 deletions google/cloud/storage/bucket.py
Expand Up @@ -617,12 +617,13 @@ def blob(

def notification(
self,
topic_name,
topic_name=None,
topic_project=None,
custom_attributes=None,
event_types=None,
blob_name_prefix=None,
payload_format=NONE_PAYLOAD_FORMAT,
notification_id=None,
):
"""Factory: create a notification resource for the bucket.

Expand All @@ -632,12 +633,13 @@ def notification(
"""
return BucketNotification(
self,
topic_name,
topic_name=topic_name,
topic_project=topic_project,
custom_attributes=custom_attributes,
event_types=event_types,
blob_name_prefix=blob_name_prefix,
payload_format=payload_format,
notification_id=notification_id,
)

def exists(self, client=None, timeout=_DEFAULT_TIMEOUT):
Expand Down Expand Up @@ -1021,6 +1023,44 @@ def list_notifications(self, client=None, timeout=_DEFAULT_TIMEOUT):
iterator.bucket = self
return iterator

def get_notification(self, notification_id, client=None, timeout=_DEFAULT_TIMEOUT):
"""Get Pub / Sub notification for this bucket.

See:
https://cloud.google.com/storage/docs/json_api/v1/notifications/get

If :attr:`user_project` is set, bills the API request to that project.

:type notification_id: str
:param notification_id: The notification id to retrieve the notification configuration.

:type client: :class:`~google.cloud.storage.client.Client` or
``NoneType``
:param client: (optional) The client to use. If not passed, falls back
to the ``client`` stored on the current bucket.
:type timeout: float or tuple
:param timeout: (optional) The amount of time, in seconds, to wait
for the server response.

Can also be passed as a tuple (connect_timeout, read_timeout).
See :meth:`requests.Session.request` documentation for details.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an example of how to use this helper method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.


:rtype: :class:`.BucketNotification`
:returns: notification instance.

Example:
Get notification using notification id.

>>> from google.cloud import storage
>>> client = storage.Client()
>>> bucket = client.get_bucket('my-bucket-name') # API request.
>>> notification = bucket.get_notification(notification_id='id') # API request.

"""
notification = self.notification(notification_id=notification_id)
notification.reload(client=client, timeout=timeout)
return notification

def delete(self, force=False, client=None, timeout=_DEFAULT_TIMEOUT):
"""Delete this bucket.

Expand Down
15 changes: 12 additions & 3 deletions google/cloud/storage/notification.py
Expand Up @@ -50,7 +50,8 @@ class BucketNotification(object):
:param bucket: Bucket to which the notification is bound.

:type topic_name: str
:param topic_name: Topic name to which notifications are published.
:param topic_name:
(Optional) Topic name to which notifications are published.

:type topic_project: str
:param topic_project:
Expand All @@ -63,7 +64,7 @@ class BucketNotification(object):

:type event_types: list(str)
:param event_types:
(Optional) event types for which notificatin events are published.
(Optional) event types for which notification events are published.

:type blob_name_prefix: str
:param blob_name_prefix:
Expand All @@ -73,17 +74,22 @@ class BucketNotification(object):
:type payload_format: str
:param payload_format:
(Optional) format of payload for notification events.

:type notification_id: str
:param notification_id:
(Optional) The ID of the notification.
"""

def __init__(
self,
bucket,
topic_name,
topic_name=None,
topic_project=None,
custom_attributes=None,
event_types=None,
blob_name_prefix=None,
payload_format=NONE_PAYLOAD_FORMAT,
notification_id=None,
):
self._bucket = bucket
self._topic_name = topic_name
Expand All @@ -107,6 +113,9 @@ def __init__(
if blob_name_prefix is not None:
self._properties["object_name_prefix"] = blob_name_prefix

if notification_id is not None:
self._properties["id"] = notification_id

self._properties["payload_format"] = payload_format

@classmethod
Expand Down
26 changes: 25 additions & 1 deletion tests/system/test_system.py
Expand Up @@ -1433,6 +1433,7 @@ def test_notification_minimal(self):
bucket = retry_429_503(Config.CLIENT.create_bucket)(new_bucket_name)
self.case_buckets_to_delete.append(new_bucket_name)
self.assertEqual(list(bucket.list_notifications()), [])

notification = bucket.notification(self.TOPIC_NAME)
retry_429_503(notification.create)()
try:
Expand All @@ -1449,7 +1450,7 @@ def test_notification_explicit(self):
bucket = retry_429_503(Config.CLIENT.create_bucket)(new_bucket_name)
self.case_buckets_to_delete.append(new_bucket_name)
notification = bucket.notification(
self.TOPIC_NAME,
topic_name=self.TOPIC_NAME,
custom_attributes=self.CUSTOM_ATTRIBUTES,
event_types=self.event_types(),
blob_name_prefix=self.BLOB_NAME_PREFIX,
Expand All @@ -1463,6 +1464,7 @@ def test_notification_explicit(self):
self.assertEqual(notification.event_types, self.event_types())
self.assertEqual(notification.blob_name_prefix, self.BLOB_NAME_PREFIX)
self.assertEqual(notification.payload_format, self.payload_format())

finally:
notification.delete()

Expand All @@ -1486,6 +1488,28 @@ def test_notification_w_user_project(self):
finally:
notification.delete()

def test_get_notification(self):
new_bucket_name = "get-notification" + unique_resource_id("-")
bucket = retry_429_503(Config.CLIENT.create_bucket)(new_bucket_name)
self.case_buckets_to_delete.append(new_bucket_name)

notification = bucket.notification(
topic_name=self.TOPIC_NAME,
custom_attributes=self.CUSTOM_ATTRIBUTES,
payload_format=self.payload_format(),
)
retry_429_503(notification.create)()
try:
self.assertTrue(notification.exists())
self.assertIsNotNone(notification.notification_id)
notification_id = notification.notification_id
notification = bucket.get_notification(notification_id)
self.assertEqual(notification.notification_id, notification_id)
self.assertEqual(notification.custom_attributes, self.CUSTOM_ATTRIBUTES)
self.assertEqual(notification.payload_format, self.payload_format())
finally:
notification.delete()


class TestAnonymousClient(unittest.TestCase):

Expand Down
39 changes: 39 additions & 0 deletions tests/unit/test_bucket.py
Expand Up @@ -826,6 +826,45 @@ def test_list_notifications(self):
notification.payload_format, resource.get("payload_format")
)

def test_get_notification(self):
from google.cloud.storage.notification import _TOPIC_REF_FMT
from google.cloud.storage.notification import JSON_API_V1_PAYLOAD_FORMAT

NAME = "name"
ETAG = "FACECABB"
NOTIFICATION_ID = "1"
SELF_LINK = "https://example.com/notification/1"
resources = {
"topic": _TOPIC_REF_FMT.format("my-project-123", "topic-1"),
"id": NOTIFICATION_ID,
"etag": ETAG,
"selfLink": SELF_LINK,
"payload_format": JSON_API_V1_PAYLOAD_FORMAT,
}

connection = _make_connection(resources)
client = _Client(connection, project="my-project-123")
bucket = self._make_one(client=client, name=NAME)
notification = bucket.get_notification(notification_id=NOTIFICATION_ID)

self.assertEqual(notification.notification_id, NOTIFICATION_ID)
self.assertEqual(notification.etag, ETAG)
self.assertEqual(notification.self_link, SELF_LINK)
self.assertIsNone(notification.custom_attributes)
self.assertIsNone(notification.event_types)
self.assertIsNone(notification.blob_name_prefix)
self.assertEqual(notification.payload_format, JSON_API_V1_PAYLOAD_FORMAT)

def test_get_notification_miss(self):
from google.cloud.exceptions import NotFound

response = NotFound("testing")
connection = _make_connection(response)
client = _Client(connection, project="my-project-123")
bucket = self._make_one(client=client, name="name")
with self.assertRaises(NotFound):
bucket.get_notification(notification_id="1")

def test_delete_miss(self):
from google.cloud.exceptions import NotFound

Expand Down