Skip to content
Permalink
Browse files
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 <larkee@users.noreply.github.com>
  • Loading branch information
larkee and larkee committed Dec 15, 2020
1 parent c7b3b9e commit ed462b567a1a33f9105ffb37ba1218f379603614
Showing with 47 additions and 4 deletions.
  1. +5 −0 google/cloud/spanner_v1/client.py
  2. +12 −2 google/cloud/spanner_v1/instance.py
  3. +4 −0 tests/unit/test_client.py
  4. +26 −2 tests/unit/test_instance.py
@@ -289,6 +289,7 @@ def instance(
configuration_name=None,
display_name=None,
node_count=DEFAULT_NODE_COUNT,
labels=None,
):
"""Factory to create a instance associated with this client.
@@ -313,6 +314,9 @@ def instance(
:param node_count: (Optional) The number of nodes in the instance's
cluster; used to set up the instance's cluster.
:type labels: dict (str -> str) or None
:param labels: (Optional) User-assigned labels for this instance.
:rtype: :class:`~google.cloud.spanner_v1.instance.Instance`
:returns: an instance owned by this client.
"""
@@ -323,6 +327,7 @@ def instance(
node_count,
display_name,
self._emulator_host,
labels,
)

def list_instances(self, filter_="", page_size=None):
@@ -99,6 +99,9 @@ class Instance(object):
Cloud Console UI. (Must be between 4 and 30
characters.) If this value is not set in the
constructor, will fall back to the instance ID.
:type labels: dict (str -> str) or None
:param labels: (Optional) User-assigned labels for this instance.
"""

def __init__(
@@ -109,13 +112,17 @@ def __init__(
node_count=DEFAULT_NODE_COUNT,
display_name=None,
emulator_host=None,
labels=None,
):
self.instance_id = instance_id
self._client = client
self.configuration_name = configuration_name
self.node_count = node_count
self.display_name = display_name or instance_id
self.emulator_host = emulator_host
if labels is None:
labels = {}
self.labels = labels

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

@classmethod
def from_pb(cls, instance_pb, client):
@@ -242,6 +250,7 @@ def create(self):
config=self.configuration_name,
display_name=self.display_name,
node_count=self.node_count,
labels=self.labels,
)
metadata = _metadata_with_prefix(self.name)

@@ -296,7 +305,7 @@ def update(self):
.. note::
Updates the ``display_name`` and ``node_count``. To change those
Updates the ``display_name``, ``node_count`` and ``labels``. To change those
values before updating, set them via
.. code:: python
@@ -316,8 +325,9 @@ def update(self):
config=self.configuration_name,
display_name=self.display_name,
node_count=self.node_count,
labels=self.labels,
)
field_mask = FieldMask(paths=["config", "display_name", "node_count"])
field_mask = FieldMask(paths=["config", "display_name", "node_count", "labels"])
metadata = _metadata_with_prefix(self.name)

future = api.update_instance(
@@ -37,6 +37,7 @@ class TestClient(unittest.TestCase):
INSTANCE_NAME = "%s/instances/%s" % (PATH, INSTANCE_ID)
DISPLAY_NAME = "display-name"
NODE_COUNT = 5
LABELS = {"test": "true"}
TIMEOUT_SECONDS = 80

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

def test_instance_factory_explicit(self):
@@ -531,13 +533,15 @@ def test_instance_factory_explicit(self):
self.CONFIGURATION_NAME,
display_name=self.DISPLAY_NAME,
node_count=self.NODE_COUNT,
labels=self.LABELS,
)

self.assertIsInstance(instance, Instance)
self.assertEqual(instance.instance_id, self.INSTANCE_ID)
self.assertEqual(instance.configuration_name, self.CONFIGURATION_NAME)
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
self.assertEqual(instance.node_count, self.NODE_COUNT)
self.assertEqual(instance.labels, self.LABELS)
self.assertIs(instance._client, client)

def test_list_instances(self):
@@ -38,6 +38,7 @@ class TestInstance(unittest.TestCase):
TIMEOUT_SECONDS = 1
DATABASE_ID = "database_id"
DATABASE_NAME = "%s/databases/%s" % (INSTANCE_NAME, DATABASE_ID)
LABELS = {"test": "true"}

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

def test_constructor_non_default(self):
DISPLAY_NAME = "display_name"
@@ -68,12 +70,14 @@ def test_constructor_non_default(self):
configuration_name=self.CONFIG_NAME,
node_count=self.NODE_COUNT,
display_name=DISPLAY_NAME,
labels=self.LABELS,
)
self.assertEqual(instance.instance_id, self.INSTANCE_ID)
self.assertIs(instance._client, client)
self.assertEqual(instance.configuration_name, self.CONFIG_NAME)
self.assertEqual(instance.node_count, self.NODE_COUNT)
self.assertEqual(instance.display_name, DISPLAY_NAME)
self.assertEqual(instance.labels, self.LABELS)

def test_copy(self):
DISPLAY_NAME = "display_name"
@@ -145,6 +149,7 @@ def test_from_pb_success(self):
name=self.INSTANCE_NAME,
config=self.CONFIG_NAME,
display_name=self.INSTANCE_ID,
labels=self.LABELS,
)

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

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

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

def test_labels_property(self):
client = _Client(project=self.PROJECT)

instance = self._make_one(
self.INSTANCE_ID, client, self.CONFIG_NAME, labels=self.LABELS
)
self.assertEqual(instance.labels, self.LABELS)

def test___eq__(self):
client = object()
instance1 = self._make_one(self.INSTANCE_ID, client, self.CONFIG_NAME)
@@ -231,6 +245,7 @@ def test_create_success(self):
configuration_name=self.CONFIG_NAME,
display_name=self.DISPLAY_NAME,
node_count=self.NODE_COUNT,
labels=self.LABELS,
)

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

def test_exists_instance_grpc_error(self):
@@ -327,6 +343,7 @@ def test_reload_success(self):
config=self.CONFIG_NAME,
display_name=self.DISPLAY_NAME,
node_count=self.NODE_COUNT,
labels=self.LABELS,
)
api = client.instance_admin_api = _FauxInstanceAdminAPI(
_get_instance_response=instance_pb
@@ -338,6 +355,7 @@ def test_reload_success(self):
self.assertEqual(instance.configuration_name, self.CONFIG_NAME)
self.assertEqual(instance.node_count, self.NODE_COUNT)
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
self.assertEqual(instance.labels, self.LABELS)

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

instance, field_mask, metadata = api._updated_instance
self.assertEqual(field_mask.paths, ["config", "display_name", "node_count"])
self.assertEqual(
field_mask.paths, ["config", "display_name", "node_count", "labels"]
)
self.assertEqual(instance.name, self.INSTANCE_NAME)
self.assertEqual(instance.config, self.CONFIG_NAME)
self.assertEqual(instance.display_name, self.INSTANCE_ID)
@@ -390,18 +410,22 @@ def test_update_success(self):
configuration_name=self.CONFIG_NAME,
node_count=self.NODE_COUNT,
display_name=self.DISPLAY_NAME,
labels=self.LABELS,
)

future = instance.update()

self.assertIs(future, op_future)

instance, field_mask, metadata = api._updated_instance
self.assertEqual(field_mask.paths, ["config", "display_name", "node_count"])
self.assertEqual(
field_mask.paths, ["config", "display_name", "node_count", "labels"]
)
self.assertEqual(instance.name, self.INSTANCE_NAME)
self.assertEqual(instance.config, self.CONFIG_NAME)
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
self.assertEqual(instance.node_count, self.NODE_COUNT)
self.assertEqual(instance.labels, self.LABELS)
self.assertEqual(metadata, [("google-cloud-resource-prefix", instance.name)])

def test_delete_grpc_error(self):

0 comments on commit ed462b5

Please sign in to comment.