Skip to content

Commit ed462b5

Browse files
authored
feat: add support for instance labels (#193)
* feat: add support for instance labels * docs: update parameter docstrings * docs: add missing literal end-string * style: fix lint errors * docs: update labels type * docs: revert emulator_host docstring Co-authored-by: larkee <[email protected]>
1 parent c7b3b9e commit ed462b5

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

google/cloud/spanner_v1/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ def instance(
289289
configuration_name=None,
290290
display_name=None,
291291
node_count=DEFAULT_NODE_COUNT,
292+
labels=None,
292293
):
293294
"""Factory to create a instance associated with this client.
294295
@@ -313,6 +314,9 @@ def instance(
313314
:param node_count: (Optional) The number of nodes in the instance's
314315
cluster; used to set up the instance's cluster.
315316
317+
:type labels: dict (str -> str) or None
318+
:param labels: (Optional) User-assigned labels for this instance.
319+
316320
:rtype: :class:`~google.cloud.spanner_v1.instance.Instance`
317321
:returns: an instance owned by this client.
318322
"""
@@ -323,6 +327,7 @@ def instance(
323327
node_count,
324328
display_name,
325329
self._emulator_host,
330+
labels,
326331
)
327332

328333
def list_instances(self, filter_="", page_size=None):

google/cloud/spanner_v1/instance.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ class Instance(object):
9999
Cloud Console UI. (Must be between 4 and 30
100100
characters.) If this value is not set in the
101101
constructor, will fall back to the instance ID.
102+
103+
:type labels: dict (str -> str) or None
104+
:param labels: (Optional) User-assigned labels for this instance.
102105
"""
103106

104107
def __init__(
@@ -109,13 +112,17 @@ def __init__(
109112
node_count=DEFAULT_NODE_COUNT,
110113
display_name=None,
111114
emulator_host=None,
115+
labels=None,
112116
):
113117
self.instance_id = instance_id
114118
self._client = client
115119
self.configuration_name = configuration_name
116120
self.node_count = node_count
117121
self.display_name = display_name or instance_id
118122
self.emulator_host = emulator_host
123+
if labels is None:
124+
labels = {}
125+
self.labels = labels
119126

120127
def _update_from_pb(self, instance_pb):
121128
"""Refresh self from the server-provided protobuf.
@@ -127,6 +134,7 @@ def _update_from_pb(self, instance_pb):
127134
self.display_name = instance_pb.display_name
128135
self.configuration_name = instance_pb.config
129136
self.node_count = instance_pb.node_count
137+
self.labels = instance_pb.labels
130138

131139
@classmethod
132140
def from_pb(cls, instance_pb, client):
@@ -242,6 +250,7 @@ def create(self):
242250
config=self.configuration_name,
243251
display_name=self.display_name,
244252
node_count=self.node_count,
253+
labels=self.labels,
245254
)
246255
metadata = _metadata_with_prefix(self.name)
247256

@@ -296,7 +305,7 @@ def update(self):
296305
297306
.. note::
298307
299-
Updates the ``display_name`` and ``node_count``. To change those
308+
Updates the ``display_name``, ``node_count`` and ``labels``. To change those
300309
values before updating, set them via
301310
302311
.. code:: python
@@ -316,8 +325,9 @@ def update(self):
316325
config=self.configuration_name,
317326
display_name=self.display_name,
318327
node_count=self.node_count,
328+
labels=self.labels,
319329
)
320-
field_mask = FieldMask(paths=["config", "display_name", "node_count"])
330+
field_mask = FieldMask(paths=["config", "display_name", "node_count", "labels"])
321331
metadata = _metadata_with_prefix(self.name)
322332

323333
future = api.update_instance(

tests/unit/test_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class TestClient(unittest.TestCase):
3737
INSTANCE_NAME = "%s/instances/%s" % (PATH, INSTANCE_ID)
3838
DISPLAY_NAME = "display-name"
3939
NODE_COUNT = 5
40+
LABELS = {"test": "true"}
4041
TIMEOUT_SECONDS = 80
4142

4243
def _get_target_class(self):
@@ -518,6 +519,7 @@ def test_instance_factory_defaults(self):
518519
self.assertIsNone(instance.configuration_name)
519520
self.assertEqual(instance.display_name, self.INSTANCE_ID)
520521
self.assertEqual(instance.node_count, DEFAULT_NODE_COUNT)
522+
self.assertEqual(instance.labels, {})
521523
self.assertIs(instance._client, client)
522524

523525
def test_instance_factory_explicit(self):
@@ -531,13 +533,15 @@ def test_instance_factory_explicit(self):
531533
self.CONFIGURATION_NAME,
532534
display_name=self.DISPLAY_NAME,
533535
node_count=self.NODE_COUNT,
536+
labels=self.LABELS,
534537
)
535538

536539
self.assertIsInstance(instance, Instance)
537540
self.assertEqual(instance.instance_id, self.INSTANCE_ID)
538541
self.assertEqual(instance.configuration_name, self.CONFIGURATION_NAME)
539542
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
540543
self.assertEqual(instance.node_count, self.NODE_COUNT)
544+
self.assertEqual(instance.labels, self.LABELS)
541545
self.assertIs(instance._client, client)
542546

543547
def test_list_instances(self):

tests/unit/test_instance.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class TestInstance(unittest.TestCase):
3838
TIMEOUT_SECONDS = 1
3939
DATABASE_ID = "database_id"
4040
DATABASE_NAME = "%s/databases/%s" % (INSTANCE_NAME, DATABASE_ID)
41+
LABELS = {"test": "true"}
4142

4243
def _getTargetClass(self):
4344
from google.cloud.spanner_v1.instance import Instance
@@ -57,6 +58,7 @@ def test_constructor_defaults(self):
5758
self.assertIs(instance.configuration_name, None)
5859
self.assertEqual(instance.node_count, DEFAULT_NODE_COUNT)
5960
self.assertEqual(instance.display_name, self.INSTANCE_ID)
61+
self.assertEqual(instance.labels, {})
6062

6163
def test_constructor_non_default(self):
6264
DISPLAY_NAME = "display_name"
@@ -68,12 +70,14 @@ def test_constructor_non_default(self):
6870
configuration_name=self.CONFIG_NAME,
6971
node_count=self.NODE_COUNT,
7072
display_name=DISPLAY_NAME,
73+
labels=self.LABELS,
7174
)
7275
self.assertEqual(instance.instance_id, self.INSTANCE_ID)
7376
self.assertIs(instance._client, client)
7477
self.assertEqual(instance.configuration_name, self.CONFIG_NAME)
7578
self.assertEqual(instance.node_count, self.NODE_COUNT)
7679
self.assertEqual(instance.display_name, DISPLAY_NAME)
80+
self.assertEqual(instance.labels, self.LABELS)
7781

7882
def test_copy(self):
7983
DISPLAY_NAME = "display_name"
@@ -145,6 +149,7 @@ def test_from_pb_success(self):
145149
name=self.INSTANCE_NAME,
146150
config=self.CONFIG_NAME,
147151
display_name=self.INSTANCE_ID,
152+
labels=self.LABELS,
148153
)
149154

150155
klass = self._getTargetClass()
@@ -153,13 +158,22 @@ def test_from_pb_success(self):
153158
self.assertEqual(instance._client, client)
154159
self.assertEqual(instance.instance_id, self.INSTANCE_ID)
155160
self.assertEqual(instance.configuration_name, self.CONFIG_NAME)
161+
self.assertEqual(instance.labels, self.LABELS)
156162

157163
def test_name_property(self):
158164
client = _Client(project=self.PROJECT)
159165

160166
instance = self._make_one(self.INSTANCE_ID, client, self.CONFIG_NAME)
161167
self.assertEqual(instance.name, self.INSTANCE_NAME)
162168

169+
def test_labels_property(self):
170+
client = _Client(project=self.PROJECT)
171+
172+
instance = self._make_one(
173+
self.INSTANCE_ID, client, self.CONFIG_NAME, labels=self.LABELS
174+
)
175+
self.assertEqual(instance.labels, self.LABELS)
176+
163177
def test___eq__(self):
164178
client = object()
165179
instance1 = self._make_one(self.INSTANCE_ID, client, self.CONFIG_NAME)
@@ -231,6 +245,7 @@ def test_create_success(self):
231245
configuration_name=self.CONFIG_NAME,
232246
display_name=self.DISPLAY_NAME,
233247
node_count=self.NODE_COUNT,
248+
labels=self.LABELS,
234249
)
235250

236251
future = instance.create()
@@ -244,6 +259,7 @@ def test_create_success(self):
244259
self.assertEqual(instance.config, self.CONFIG_NAME)
245260
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
246261
self.assertEqual(instance.node_count, self.NODE_COUNT)
262+
self.assertEqual(instance.labels, self.LABELS)
247263
self.assertEqual(metadata, [("google-cloud-resource-prefix", instance.name)])
248264

249265
def test_exists_instance_grpc_error(self):
@@ -327,6 +343,7 @@ def test_reload_success(self):
327343
config=self.CONFIG_NAME,
328344
display_name=self.DISPLAY_NAME,
329345
node_count=self.NODE_COUNT,
346+
labels=self.LABELS,
330347
)
331348
api = client.instance_admin_api = _FauxInstanceAdminAPI(
332349
_get_instance_response=instance_pb
@@ -338,6 +355,7 @@ def test_reload_success(self):
338355
self.assertEqual(instance.configuration_name, self.CONFIG_NAME)
339356
self.assertEqual(instance.node_count, self.NODE_COUNT)
340357
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
358+
self.assertEqual(instance.labels, self.LABELS)
341359

342360
name, metadata = api._got_instance
343361
self.assertEqual(name, self.INSTANCE_NAME)
@@ -371,7 +389,9 @@ def test_update_not_found(self):
371389
instance.update()
372390

373391
instance, field_mask, metadata = api._updated_instance
374-
self.assertEqual(field_mask.paths, ["config", "display_name", "node_count"])
392+
self.assertEqual(
393+
field_mask.paths, ["config", "display_name", "node_count", "labels"]
394+
)
375395
self.assertEqual(instance.name, self.INSTANCE_NAME)
376396
self.assertEqual(instance.config, self.CONFIG_NAME)
377397
self.assertEqual(instance.display_name, self.INSTANCE_ID)
@@ -390,18 +410,22 @@ def test_update_success(self):
390410
configuration_name=self.CONFIG_NAME,
391411
node_count=self.NODE_COUNT,
392412
display_name=self.DISPLAY_NAME,
413+
labels=self.LABELS,
393414
)
394415

395416
future = instance.update()
396417

397418
self.assertIs(future, op_future)
398419

399420
instance, field_mask, metadata = api._updated_instance
400-
self.assertEqual(field_mask.paths, ["config", "display_name", "node_count"])
421+
self.assertEqual(
422+
field_mask.paths, ["config", "display_name", "node_count", "labels"]
423+
)
401424
self.assertEqual(instance.name, self.INSTANCE_NAME)
402425
self.assertEqual(instance.config, self.CONFIG_NAME)
403426
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
404427
self.assertEqual(instance.node_count, self.NODE_COUNT)
428+
self.assertEqual(instance.labels, self.LABELS)
405429
self.assertEqual(metadata, [("google-cloud-resource-prefix", instance.name)])
406430

407431
def test_delete_grpc_error(self):

0 commit comments

Comments
 (0)