Skip to content

Commit 465a888

Browse files
chemelnucfindhermes
authored andcommitted
Logging: Adding unique writer identity to Sink. (googleapis#4595)
1 parent 157b498 commit 465a888

6 files changed

Lines changed: 107 additions & 13 deletions

File tree

logging/google/cloud/logging/_gax.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ def list_sinks(self, project, page_size=0, page_token=None):
192192
return page_iterator._GAXIterator(
193193
self._client, page_iter, _item_to_sink)
194194

195-
def sink_create(self, project, sink_name, filter_, destination):
195+
def sink_create(self, project, sink_name, filter_, destination,
196+
unique_writer_identity=False):
196197
"""API call: create a sink resource.
197198
198199
See
@@ -211,13 +212,23 @@ def sink_create(self, project, sink_name, filter_, destination):
211212
:type destination: str
212213
:param destination: destination URI for the entries exported by
213214
the sink.
215+
216+
:type unique_writer_identity: bool
217+
:param unique_writer_identity: (Optional) determines the kind of
218+
IAM identity returned as
219+
writer_identity in the new sink.
214220
"""
215221
options = None
216222
parent = 'projects/%s' % (project,)
217223
sink_pb = LogSink(name=sink_name, filter=filter_,
218224
destination=destination)
219225
try:
220-
self._gax_api.create_sink(parent, sink_pb, options=options)
226+
self._gax_api.create_sink(
227+
parent,
228+
sink_pb,
229+
unique_writer_identity=unique_writer_identity,
230+
options=options,
231+
)
221232
except GaxError as exc:
222233
if exc_to_code(exc.cause) == StatusCode.FAILED_PRECONDITION:
223234
path = 'projects/%s/sinks/%s' % (project, sink_name)

logging/google/cloud/logging/_http.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ def list_sinks(self, project, page_size=None, page_token=None):
229229
page_token=page_token,
230230
extra_params=extra_params)
231231

232-
def sink_create(self, project, sink_name, filter_, destination):
232+
def sink_create(self, project, sink_name, filter_, destination,
233+
unique_writer_identity=False):
233234
"""API call: create a sink resource.
234235
235236
See
@@ -248,14 +249,25 @@ def sink_create(self, project, sink_name, filter_, destination):
248249
:type destination: str
249250
:param destination: destination URI for the entries exported by
250251
the sink.
252+
253+
:type unique_writer_identity: bool
254+
:param unique_writer_identity: (Optional) determines the kind of
255+
IAM identity returned as
256+
writer_identity in the new sink.
251257
"""
252258
target = '/projects/%s/sinks' % (project,)
253259
data = {
254260
'name': sink_name,
255261
'filter': filter_,
256262
'destination': destination,
257263
}
258-
self.api_request(method='POST', path=target, data=data)
264+
query_params = {'uniqueWriterIdentity': unique_writer_identity}
265+
self.api_request(
266+
method='POST',
267+
path=target,
268+
data=data,
269+
query_params=query_params,
270+
)
259271

260272
def sink_get(self, project, sink_name):
261273
"""API call: retrieve a sink resource.

logging/google/cloud/logging/sink.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,19 @@ class Sink(object):
3939
:type client: :class:`google.cloud.logging.client.Client`
4040
:param client: A client which holds credentials and project configuration
4141
for the sink (which requires a project).
42+
43+
:type unique_writer_identity: bool
44+
:param unique_writer_identity: (Optional) determines the kind of
45+
IAM identity returned as
46+
writer_identity in the new sink.
4247
"""
43-
def __init__(self, name, filter_=None, destination=None, client=None):
48+
def __init__(self, name, filter_=None, destination=None, client=None,
49+
unique_writer_identity=False):
4450
self.name = name
4551
self.filter_ = filter_
4652
self.destination = destination
4753
self._client = client
54+
self._unique_writer_identity = unique_writer_identity
4855

4956
@property
5057
def client(self):
@@ -116,7 +123,9 @@ def create(self, client=None):
116123
"""
117124
client = self._require_client(client)
118125
client.sinks_api.sink_create(
119-
self.project, self.name, self.filter_, self.destination)
126+
self.project, self.name, self.filter_, self.destination,
127+
unique_writer_identity=self._unique_writer_identity,
128+
)
120129

121130
def exists(self, client=None):
122131
"""API call: test for the existence of the sink via a GET request

logging/tests/unit/test__gax.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -737,14 +737,34 @@ def test_sink_create_ok(self):
737737
api.sink_create(
738738
self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI)
739739

740-
parent, sink, options = (
740+
parent, sink, options, unique_writer_identity = (
741741
gax_api._create_sink_called_with)
742742
self.assertEqual(parent, self.PROJECT_PATH)
743743
self.assertIsInstance(sink, LogSink)
744744
self.assertEqual(sink.name, self.SINK_NAME)
745745
self.assertEqual(sink.filter, self.FILTER)
746746
self.assertEqual(sink.destination, self.DESTINATION_URI)
747747
self.assertIsNone(options)
748+
self.assertFalse(unique_writer_identity)
749+
750+
def test_sink_create_with_unique_writer_identity(self):
751+
from google.cloud.proto.logging.v2.logging_config_pb2 import LogSink
752+
753+
gax_api = _GAXSinksAPI()
754+
api = self._make_one(gax_api, None)
755+
api.sink_create(
756+
self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI,
757+
unique_writer_identity=True,
758+
)
759+
parent, sink, options, unique_writer_identity = (
760+
gax_api._create_sink_called_with)
761+
self.assertEqual(parent, self.PROJECT_PATH)
762+
self.assertIsInstance(sink, LogSink)
763+
self.assertEqual(sink.name, self.SINK_NAME)
764+
self.assertEqual(sink.filter, self.FILTER)
765+
self.assertEqual(sink.destination, self.DESTINATION_URI)
766+
self.assertIsNone(options)
767+
self.assertTrue(unique_writer_identity)
748768

749769
def test_sink_get_error(self):
750770
from google.cloud.exceptions import NotFound
@@ -1462,10 +1482,10 @@ def list_sinks(self, parent, page_size, options):
14621482
self._list_sinks_called_with = parent, page_size, options
14631483
return self._list_sinks_response
14641484

1465-
def create_sink(self, parent, sink, options):
1485+
def create_sink(self, parent, sink, options, unique_writer_identity=False):
14661486
from google.gax.errors import GaxError
14671487

1468-
self._create_sink_called_with = parent, sink, options
1488+
self._create_sink_called_with = parent, sink, options, unique_writer_identity
14691489
if self._random_gax_error:
14701490
raise GaxError('error')
14711491
if self._create_sink_conflict:

logging/tests/unit/test__http.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,33 @@ def test_sink_create_ok(self):
476476
self.assertEqual(conn._called_with['path'], path)
477477
self.assertEqual(conn._called_with['data'], SENT)
478478

479+
def test_sink_create_unique_writer_identity(self):
480+
sent = {
481+
'name': self.SINK_NAME,
482+
'filter': self.FILTER,
483+
'destination': self.DESTINATION_URI,
484+
}
485+
486+
conn = _Connection({})
487+
client = _Client(conn)
488+
api = self._make_one(client)
489+
490+
api.sink_create(
491+
self.PROJECT,
492+
self.SINK_NAME,
493+
self.FILTER,
494+
self.DESTINATION_URI,
495+
unique_writer_identity=True,
496+
)
497+
path = '/projects/%s/sinks' % (self.PROJECT,)
498+
expected = {
499+
'method': 'POST',
500+
'path': path,
501+
'data': sent,
502+
'query_params': {'uniqueWriterIdentity': True},
503+
}
504+
self.assertEqual(conn._called_with, expected)
505+
479506
def test_sink_get_miss(self):
480507
from google.cloud.exceptions import NotFound
481508

logging/tests/unit/test_sink.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,14 @@ def test_create_w_bound_client(self):
102102

103103
self.assertEqual(
104104
api._sink_create_called_with,
105-
(self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI))
105+
(
106+
self.PROJECT,
107+
self.SINK_NAME,
108+
self.FILTER,
109+
self.DESTINATION_URI,
110+
False,
111+
),
112+
)
106113

107114
def test_create_w_alternate_client(self):
108115
client1 = _Client(project=self.PROJECT)
@@ -116,7 +123,14 @@ def test_create_w_alternate_client(self):
116123

117124
self.assertEqual(
118125
api._sink_create_called_with,
119-
(self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI))
126+
(
127+
self.PROJECT,
128+
self.SINK_NAME,
129+
self.FILTER,
130+
self.DESTINATION_URI,
131+
False,
132+
),
133+
)
120134

121135
def test_exists_miss_w_bound_client(self):
122136
client = _Client(project=self.PROJECT)
@@ -255,9 +269,10 @@ def __init__(self, project):
255269

256270
class _DummySinksAPI(object):
257271

258-
def sink_create(self, project, sink_name, filter_, destination):
272+
def sink_create(self, project, sink_name, filter_, destination,
273+
unique_writer_identity=False):
259274
self._sink_create_called_with = (
260-
project, sink_name, filter_, destination)
275+
project, sink_name, filter_, destination, unique_writer_identity)
261276

262277
def sink_get(self, project, sink_name):
263278
from google.cloud.exceptions import NotFound

0 commit comments

Comments
 (0)