Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 21101e0

Browse filesBrowse files
committed
Merge pull request #1235 from dhermes/bigtable-cluster-from-pb
Adding Bigtable Cluster.from_pb factory.
2 parents d57220c + 083e738 commit 21101e0
Copy full SHA for 21101e0

File tree

Expand file treeCollapse file tree

2 files changed

+146
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+146
-0
lines changed

‎gcloud/bigtable/cluster.py

Copy file name to clipboardExpand all lines: gcloud/bigtable/cluster.py
+63Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,40 @@
1515
"""User friendly container for Google Cloud Bigtable Cluster."""
1616

1717

18+
import re
19+
1820
from gcloud.bigtable.table import Table
1921

2022

23+
_CLUSTER_NAME_RE = re.compile(r'^projects/(?P<project>[^/]+)/'
24+
r'zones/(?P<zone>[^/]+)/clusters/'
25+
r'(?P<cluster_id>[a-z][-a-z0-9]*)$')
26+
27+
28+
def _get_pb_property_value(message_pb, property_name):
29+
"""Return a message field value.
30+
31+
:type message_pb: :class:`google.protobuf.message.Message`
32+
:param message_pb: The message to check for ``property_name``.
33+
34+
:type property_name: str
35+
:param property_name: The property value to check against.
36+
37+
:rtype: object
38+
:returns: The value of ``property_name`` set on ``message_pb``.
39+
:raises: :class:`ValueError <exceptions.ValueError>` if the result returned
40+
from the ``message_pb`` does not contain the ``property_name``
41+
value.
42+
"""
43+
# Make sure `property_name` is set on the response.
44+
# NOTE: As of proto3, HasField() only works for message fields, not for
45+
# singular (non-message) fields.
46+
all_fields = set([field.name for field in message_pb._fields])
47+
if property_name not in all_fields:
48+
raise ValueError('Message does not contain %s.' % (property_name,))
49+
return getattr(message_pb, property_name)
50+
51+
2152
class Cluster(object):
2253
"""Representation of a Google Cloud Bigtable Cluster.
2354
@@ -60,3 +91,35 @@ def table(self, table_id):
6091
:returns: The table owned by this cluster.
6192
"""
6293
return Table(table_id, self)
94+
95+
def _update_from_pb(self, cluster_pb):
96+
self.display_name = _get_pb_property_value(cluster_pb, 'display_name')
97+
self.serve_nodes = _get_pb_property_value(cluster_pb, 'serve_nodes')
98+
99+
@classmethod
100+
def from_pb(cls, cluster_pb, client):
101+
"""Creates a cluster instance from a protobuf.
102+
103+
:type cluster_pb: :class:`bigtable_cluster_data_pb2.Cluster`
104+
:param cluster_pb: A cluster protobuf object.
105+
106+
:type client: :class:`.client.Client`
107+
:param client: The client that owns the cluster.
108+
109+
:rtype: :class:`Cluster`
110+
:returns: The cluster parsed from the protobuf response.
111+
:raises: :class:`ValueError <exceptions.ValueError>` if the cluster
112+
name does not match :data:`_CLUSTER_NAME_RE` or if the parsed
113+
project ID does not match the project ID on the client.
114+
"""
115+
match = _CLUSTER_NAME_RE.match(cluster_pb.name)
116+
if match is None:
117+
raise ValueError('Cluster protobuf name was not in the '
118+
'expected format.', cluster_pb.name)
119+
if match.group('project') != client.project:
120+
raise ValueError('Project ID on cluster does not match the '
121+
'project ID on the client')
122+
123+
result = cls(match.group('zone'), match.group('cluster_id'), client)
124+
result._update_from_pb(cluster_pb)
125+
return result

‎gcloud/bigtable/test_cluster.py

Copy file name to clipboardExpand all lines: gcloud/bigtable/test_cluster.py
+83Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,86 @@ def test_table_factory(self):
6565
self.assertTrue(isinstance(table, Table))
6666
self.assertEqual(table.table_id, table_id)
6767
self.assertEqual(table._cluster, cluster)
68+
69+
def test_from_pb_success(self):
70+
from gcloud.bigtable._generated import (
71+
bigtable_cluster_data_pb2 as data_pb2)
72+
73+
project = 'PROJECT'
74+
zone = 'zone'
75+
cluster_id = 'cluster-id'
76+
client = _Client(project=project)
77+
78+
cluster_name = ('projects/' + project + '/zones/' + zone +
79+
'/clusters/' + cluster_id)
80+
cluster_pb = data_pb2.Cluster(
81+
name=cluster_name,
82+
display_name=cluster_id,
83+
serve_nodes=3,
84+
)
85+
86+
klass = self._getTargetClass()
87+
cluster = klass.from_pb(cluster_pb, client)
88+
self.assertTrue(isinstance(cluster, klass))
89+
self.assertEqual(cluster._client, client)
90+
self.assertEqual(cluster.zone, zone)
91+
self.assertEqual(cluster.cluster_id, cluster_id)
92+
93+
def test_from_pb_bad_cluster_name(self):
94+
from gcloud.bigtable._generated import (
95+
bigtable_cluster_data_pb2 as data_pb2)
96+
97+
cluster_name = 'INCORRECT_FORMAT'
98+
cluster_pb = data_pb2.Cluster(name=cluster_name)
99+
100+
klass = self._getTargetClass()
101+
with self.assertRaises(ValueError):
102+
klass.from_pb(cluster_pb, None)
103+
104+
def test_from_pb_project_mistmatch(self):
105+
from gcloud.bigtable._generated import (
106+
bigtable_cluster_data_pb2 as data_pb2)
107+
108+
project = 'PROJECT'
109+
zone = 'zone'
110+
cluster_id = 'cluster-id'
111+
alt_project = 'ALT_PROJECT'
112+
client = _Client(project=alt_project)
113+
114+
self.assertNotEqual(project, alt_project)
115+
116+
cluster_name = ('projects/' + project + '/zones/' + zone +
117+
'/clusters/' + cluster_id)
118+
cluster_pb = data_pb2.Cluster(name=cluster_name)
119+
120+
klass = self._getTargetClass()
121+
with self.assertRaises(ValueError):
122+
klass.from_pb(cluster_pb, client)
123+
124+
125+
class Test__get_pb_property_value(unittest2.TestCase):
126+
127+
def _callFUT(self, message_pb, property_name):
128+
from gcloud.bigtable.cluster import _get_pb_property_value
129+
return _get_pb_property_value(message_pb, property_name)
130+
131+
def test_it(self):
132+
from gcloud.bigtable._generated import (
133+
bigtable_cluster_data_pb2 as data_pb2)
134+
serve_nodes = 119
135+
cluster_pb = data_pb2.Cluster(serve_nodes=serve_nodes)
136+
result = self._callFUT(cluster_pb, 'serve_nodes')
137+
self.assertEqual(result, serve_nodes)
138+
139+
def test_with_value_unset_on_pb(self):
140+
from gcloud.bigtable._generated import (
141+
bigtable_cluster_data_pb2 as data_pb2)
142+
cluster_pb = data_pb2.Cluster()
143+
with self.assertRaises(ValueError):
144+
self._callFUT(cluster_pb, 'serve_nodes')
145+
146+
147+
class _Client(object):
148+
149+
def __init__(self, project):
150+
self.project = project

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.