diff --git a/google/cloud/spanner_v1/client.py b/google/cloud/spanner_v1/client.py index b433f0c7b0..f4cd6ef910 100644 --- a/google/cloud/spanner_v1/client.py +++ b/google/cloud/spanner_v1/client.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): diff --git a/google/cloud/spanner_v1/instance.py b/google/cloud/spanner_v1/instance.py index be49dd2d84..e6972487a7 100644 --- a/google/cloud/spanner_v1/instance.py +++ b/google/cloud/spanner_v1/instance.py @@ -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,6 +112,7 @@ def __init__( node_count=DEFAULT_NODE_COUNT, display_name=None, emulator_host=None, + labels=None, ): self.instance_id = instance_id self._client = client @@ -116,6 +120,9 @@ def __init__( 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( diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index a3001e61ae..9c260c5f95 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -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,6 +533,7 @@ 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) @@ -538,6 +541,7 @@ def test_instance_factory_explicit(self): 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): diff --git a/tests/unit/test_instance.py b/tests/unit/test_instance.py index 0694d438a2..082ef9e122 100644 --- a/tests/unit/test_instance.py +++ b/tests/unit/test_instance.py @@ -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,6 +158,7 @@ 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) @@ -160,6 +166,14 @@ def test_name_property(self): 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,6 +410,7 @@ 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() @@ -397,11 +418,14 @@ def test_update_success(self): 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):