Repository: googleapis/google-cloud-python

Issue:
Get Sink By Name
I think there should be an easier way to get a sink by name. Currently you have to create it with a filter and destination and then do a reload. It would make more sense to me if filter/destination were optional, so you could just create it by name and then do a reload() to pull it in.



Discussion:

Resolving patch:
diff --git a/gcloud/logging/client.py b/gcloud/logging/client.py
--- a/gcloud/logging/client.py
+++ b/gcloud/logging/client.py
@@ -165,19 +165,23 @@ def list_entries(self, projects=None, filter_=None, order_by=None,
                    for resource in resources]
         return entries, token
 
-    def sink(self, name, filter_, destination):
+    def sink(self, name, filter_=None, destination=None):
         """Creates a sink bound to the current client.
 
         :type name: str
         :param name: the name of the sink to be constructed.
 
         :type filter_: str
-        :param filter_: the advanced logs filter expression defining the
-                        entries exported by the sink.
+        :param filter_: (optional) the advanced logs filter expression
+                        defining the entries exported by the sink.  If not
+                        passed, the instance should already exist, to be
+                        refreshed via :meth:`Sink.reload`.
 
         :type destination: str
         :param destination: destination URI for the entries exported by
-                            the sink.
+                            the sink.  If not passed, the instance should
+                            already exist, to be refreshed via
+                            :meth:`Sink.reload`.
 
         :rtype: :class:`gcloud.logging.sink.Sink`
         :returns: Sink created with the current client.
@@ -211,7 +215,7 @@ def list_sinks(self, page_size=None, page_token=None):
                  for resource in resources]
         return sinks, token
 
-    def metric(self, name, filter_, description=''):
+    def metric(self, name, filter_=None, description=''):
         """Creates a metric bound to the current client.
 
         :type name: str
@@ -219,10 +223,14 @@ def metric(self, name, filter_, description=''):
 
         :type filter_: str
         :param filter_: the advanced logs filter expression defining the
-                        entries tracked by the metric.
+                        entries tracked by the metric.  If not
+                        passed, the instance should already exist, to be
+                        refreshed via :meth:`Metric.reload`.
 
         :type description: str
         :param description: the description of the metric to be constructed.
+                            If not passed, the instance should already exist,
+                            to be refreshed via :meth:`Metric.reload`.
 
         :rtype: :class:`gcloud.logging.metric.Metric`
         :returns: Metric created with the current client.
diff --git a/gcloud/logging/metric.py b/gcloud/logging/metric.py
--- a/gcloud/logging/metric.py
+++ b/gcloud/logging/metric.py
@@ -28,16 +28,17 @@ class Metric(object):
 
     :type filter_: string
     :param filter_: the advanced logs filter expression defining the entries
-                   tracked by the metric.
+                   tracked by the metric.  If not passed, the instance should
+                   already exist, to be refreshed via :meth:`reload`.
 
     :type client: :class:`gcloud.logging.client.Client`
     :param client: A client which holds credentials and project configuration
                    for the metric (which requires a project).
 
     :type description: string
-    :param description: an optional description of the metric
+    :param description: an optional description of the metric.
     """
-    def __init__(self, name, filter_, client, description=''):
+    def __init__(self, name, filter_=None, client=None, description=''):
         self.name = name
         self._client = client
         self.filter_ = filter_
diff --git a/gcloud/logging/sink.py b/gcloud/logging/sink.py
--- a/gcloud/logging/sink.py
+++ b/gcloud/logging/sink.py
@@ -28,16 +28,19 @@ class Sink(object):
 
     :type filter_: string
     :param filter_: the advanced logs filter expression defining the entries
-                    exported by the sink.
+                    exported by the sink.  If not passed, the instance should
+                    already exist, to be refreshed via :meth:`reload`.
 
     :type destination: string
     :param destination: destination URI for the entries exported by the sink.
+                        If not passed, the instance should already exist, to
+                        be refreshed via :meth:`reload`.
 
     :type client: :class:`gcloud.logging.client.Client`
     :param client: A client which holds credentials and project configuration
                    for the sink (which requires a project).
     """
-    def __init__(self, name, filter_, destination, client):
+    def __init__(self, name, filter_=None, destination=None, client=None):
         self.name = name
         self.filter_ = filter_
         self.destination = destination


Test patch:
diff --git a/gcloud/logging/test_client.py b/gcloud/logging/test_client.py
--- a/gcloud/logging/test_client.py
+++ b/gcloud/logging/test_client.py
@@ -192,7 +192,19 @@ def test_list_entries_explicit(self):
             api._list_entries_called_with,
             ([PROJECT1, PROJECT2], FILTER, DESCENDING, PAGE_SIZE, TOKEN))
 
-    def test_sink(self):
+    def test_sink_defaults(self):
+        from gcloud.logging.sink import Sink
+        creds = _Credentials()
+        client = self._makeOne(project=self.PROJECT, credentials=creds)
+        sink = client.sink(self.SINK_NAME)
+        self.assertTrue(isinstance(sink, Sink))
+        self.assertEqual(sink.name, self.SINK_NAME)
+        self.assertEqual(sink.filter_, None)
+        self.assertEqual(sink.destination, None)
+        self.assertTrue(sink.client is client)
+        self.assertEqual(sink.project, self.PROJECT)
+
+    def test_sink_explicit(self):
         from gcloud.logging.sink import Sink
         creds = _Credentials()
         client = self._makeOne(project=self.PROJECT, credentials=creds)
@@ -260,7 +272,20 @@ def test_list_sinks_with_paging(self):
         self.assertEqual(api._list_sinks_called_with,
                          (PROJECT, PAGE_SIZE, TOKEN))
 
-    def test_metric(self):
+    def test_metric_defaults(self):
+        from gcloud.logging.metric import Metric
+        creds = _Credentials()
+
+        client_obj = self._makeOne(project=self.PROJECT, credentials=creds)
+        metric = client_obj.metric(self.METRIC_NAME)
+        self.assertTrue(isinstance(metric, Metric))
+        self.assertEqual(metric.name, self.METRIC_NAME)
+        self.assertEqual(metric.filter_, None)
+        self.assertEqual(metric.description, '')
+        self.assertTrue(metric.client is client_obj)
+        self.assertEqual(metric.project, self.PROJECT)
+
+    def test_metric_explicit(self):
         from gcloud.logging.metric import Metric
         creds = _Credentials()
 
diff --git a/gcloud/logging/test_metric.py b/gcloud/logging/test_metric.py
--- a/gcloud/logging/test_metric.py
+++ b/gcloud/logging/test_metric.py
@@ -32,9 +32,9 @@ def _makeOne(self, *args, **kw):
     def test_ctor_defaults(self):
         FULL = 'projects/%s/metrics/%s' % (self.PROJECT, self.METRIC_NAME)
         client = _Client(self.PROJECT)
-        metric = self._makeOne(self.METRIC_NAME, self.FILTER, client=client)
+        metric = self._makeOne(self.METRIC_NAME, client=client)
         self.assertEqual(metric.name, self.METRIC_NAME)
-        self.assertEqual(metric.filter_, self.FILTER)
+        self.assertEqual(metric.filter_, None)
         self.assertEqual(metric.description, '')
         self.assertTrue(metric.client is client)
         self.assertEqual(metric.project, self.PROJECT)
diff --git a/gcloud/logging/test_sink.py b/gcloud/logging/test_sink.py
--- a/gcloud/logging/test_sink.py
+++ b/gcloud/logging/test_sink.py
@@ -29,7 +29,19 @@ def _getTargetClass(self):
     def _makeOne(self, *args, **kw):
         return self._getTargetClass()(*args, **kw)
 
-    def test_ctor(self):
+    def test_ctor_defaults(self):
+        FULL = 'projects/%s/sinks/%s' % (self.PROJECT, self.SINK_NAME)
+        client = _Client(self.PROJECT)
+        sink = self._makeOne(self.SINK_NAME, client=client)
+        self.assertEqual(sink.name, self.SINK_NAME)
+        self.assertEqual(sink.filter_, None)
+        self.assertEqual(sink.destination, None)
+        self.assertTrue(sink.client is client)
+        self.assertEqual(sink.project, self.PROJECT)
+        self.assertEqual(sink.full_name, FULL)
+        self.assertEqual(sink.path, '/%s' % (FULL,))
+
+    def test_ctor_explicit(self):
         FULL = 'projects/%s/sinks/%s' % (self.PROJECT, self.SINK_NAME)
         client = _Client(self.PROJECT)
         sink = self._makeOne(self.SINK_NAME, self.FILTER, self.DESTINATION_URI,