Skip to content

Commit 7867201

Browse files
committed
Implementing Bigtable Operation.finished().
This method is intended to be used to check if a create, update or undelete operation has completed.
1 parent b11e8fd commit 7867201

2 files changed

Lines changed: 105 additions & 4 deletions

File tree

gcloud/bigtable/cluster.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
bigtable_cluster_service_messages_pb2 as messages_pb2)
2525
from gcloud.bigtable._generated import (
2626
bigtable_table_service_messages_pb2 as table_messages_pb2)
27+
from gcloud.bigtable._generated import operations_pb2
2728
from gcloud.bigtable.table import Table
2829

2930

@@ -169,23 +170,54 @@ class Operation(object):
169170
170171
:type begin: :class:`datetime.datetime`
171172
:param begin: The time when the operation was started.
173+
174+
:type cluster: :class:`Cluster`
175+
:param cluster: The cluster that created the operation.
172176
"""
173177

174-
def __init__(self, op_type, op_id, begin):
178+
def __init__(self, op_type, op_id, begin, cluster=None):
175179
self.op_type = op_type
176180
self.op_id = op_id
177181
self.begin = begin
182+
self._cluster = cluster
183+
self._complete = False
178184

179185
def __eq__(self, other):
180186
if not isinstance(other, self.__class__):
181187
return False
182188
return (other.op_type == self.op_type and
183189
other.op_id == self.op_id and
184-
other.begin == self.begin)
190+
other.begin == self.begin and
191+
other._cluster == self._cluster and
192+
other._complete == self._complete)
185193

186194
def __ne__(self, other):
187195
return not self.__eq__(other)
188196

197+
def finished(self):
198+
"""Check if the operation has finished.
199+
200+
:rtype: bool
201+
:returns: A boolean indicating if the current operation has completed.
202+
:raises: :class:`ValueError <exceptions.ValueError>` if the operation
203+
has already completed.
204+
"""
205+
if self._complete:
206+
raise ValueError('The operation has completed.')
207+
208+
operation_name = ('operations/' + self._cluster.name +
209+
'/operations/%d' % (self.op_id,))
210+
request_pb = operations_pb2.GetOperationRequest(name=operation_name)
211+
# We expact a `._generated.operations_pb2.Operation`.
212+
operation_pb = self._cluster._client._operations_stub.GetOperation(
213+
request_pb, self._cluster._client.timeout_seconds)
214+
215+
if operation_pb.done:
216+
self._complete = True
217+
return True
218+
else:
219+
return False
220+
189221

190222
class Cluster(object):
191223
"""Representation of a Google Cloud Bigtable Cluster.

gcloud/bigtable/test_cluster.py

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,25 @@ def _getTargetClass(self):
2525
def _makeOne(self, *args, **kwargs):
2626
return self._getTargetClass()(*args, **kwargs)
2727

28-
def test_constructor(self):
28+
def _constructor_test_helper(self, cluster=None):
2929
import datetime
3030
op_type = 'fake-op'
3131
op_id = 8915
3232
begin = datetime.datetime(2015, 10, 22, 1, 1)
33-
operation = self._makeOne(op_type, op_id, begin)
33+
operation = self._makeOne(op_type, op_id, begin, cluster=cluster)
3434

3535
self.assertEqual(operation.op_type, op_type)
3636
self.assertEqual(operation.op_id, op_id)
3737
self.assertEqual(operation.begin, begin)
38+
self.assertEqual(operation._cluster, cluster)
39+
self.assertFalse(operation._complete)
40+
41+
def test_constructor_defaults(self):
42+
self._constructor_test_helper()
43+
44+
def test_constructor_explicit_cluster(self):
45+
cluster = object()
46+
self._constructor_test_helper(cluster=cluster)
3847

3948
def test___eq__(self):
4049
import datetime
@@ -65,6 +74,66 @@ def test___ne__(self):
6574
operation2 = self._makeOne('bar', 456, None)
6675
self.assertNotEqual(operation1, operation2)
6776

77+
def test_finished_without_operation(self):
78+
operation = self._makeOne(None, None, None)
79+
operation._complete = True
80+
with self.assertRaises(ValueError):
81+
operation.finished()
82+
83+
def _finished_helper(self, done):
84+
import datetime
85+
from gcloud.bigtable._generated import operations_pb2
86+
from gcloud.bigtable._testing import _FakeStub
87+
from gcloud.bigtable.cluster import Cluster
88+
89+
project = 'PROJECT'
90+
zone = 'zone'
91+
cluster_id = 'cluster-id'
92+
op_type = 'fake-op'
93+
op_id = 789
94+
begin = datetime.datetime(2015, 10, 22, 1, 1)
95+
timeout_seconds = 1
96+
97+
client = _Client(project, timeout_seconds=timeout_seconds)
98+
cluster = Cluster(zone, cluster_id, client)
99+
operation = self._makeOne(op_type, op_id, begin, cluster=cluster)
100+
101+
# Create request_pb
102+
op_name = ('operations/projects/' + project + '/zones/' +
103+
zone + '/clusters/' + cluster_id +
104+
'/operations/%d' % (op_id,))
105+
request_pb = operations_pb2.GetOperationRequest(name=op_name)
106+
107+
# Create response_pb
108+
response_pb = operations_pb2.Operation(done=done)
109+
110+
# Patch the stub used by the API method.
111+
client._operations_stub = stub = _FakeStub(response_pb)
112+
113+
# Create expected_result.
114+
expected_result = done
115+
116+
# Perform the method and check the result.
117+
result = operation.finished()
118+
119+
self.assertEqual(result, expected_result)
120+
self.assertEqual(stub.method_calls, [(
121+
'GetOperation',
122+
(request_pb, timeout_seconds),
123+
{},
124+
)])
125+
126+
if done:
127+
self.assertTrue(operation._complete)
128+
else:
129+
self.assertFalse(operation._complete)
130+
131+
def test_finished(self):
132+
self._finished_helper(done=True)
133+
134+
def test_finished_not_done(self):
135+
self._finished_helper(done=False)
136+
68137

69138
class TestCluster(unittest2.TestCase):
70139

0 commit comments

Comments
 (0)