Skip to content

Commit

Permalink
Implementing Table.exists().
Browse files Browse the repository at this point in the history
This corresponds to the GetTable method in the table
service.
  • Loading branch information
dhermes committed Jul 28, 2015
1 parent 1638be0 commit 44f0849
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 8 deletions.
21 changes: 15 additions & 6 deletions gcloud_bigtable/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ def project_id(self):
"""
return self._client.project_id

@property
def credentials(self):
"""Getter for cluster's credentials.
:rtype: :class:`oauth2client.client.OAuth2Credentials`
:returns: The credentials stored on the cluster's client.
"""
return self._client.credentials

@property
def name(self):
"""Cluster name used in requests.
Expand Down Expand Up @@ -250,7 +259,7 @@ def reload(self, timeout_seconds=TIMEOUT_SECONDS):
If not passed, defaults to ``TIMEOUT_SECONDS``.
"""
request_pb = messages_pb2.GetClusterRequest(name=self.name)
stub = make_stub(self.client._credentials, CLUSTER_STUB_FACTORY,
stub = make_stub(self.credentials, CLUSTER_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.GetCluster.async(request_pb, timeout_seconds)
Expand Down Expand Up @@ -278,7 +287,7 @@ def operation_finished(self, timeout_seconds=TIMEOUT_SECONDS):
operation_name = ('operations/' + self.name +
'/operations/%d' % (self._operation_id,))
request_pb = operations_pb2.GetOperationRequest(name=operation_name)
stub = make_stub(self.client._credentials, OPERATIONS_STUB_FACTORY,
stub = make_stub(self.credentials, OPERATIONS_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.GetOperation.async(request_pb, timeout_seconds)
Expand Down Expand Up @@ -315,7 +324,7 @@ def create(self, timeout_seconds=TIMEOUT_SECONDS):
If not passed, defaults to ``TIMEOUT_SECONDS``.
"""
request_pb = _prepare_create_request(self)
stub = make_stub(self.client._credentials, CLUSTER_STUB_FACTORY,
stub = make_stub(self.credentials, CLUSTER_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.CreateCluster.async(request_pb, timeout_seconds)
Expand Down Expand Up @@ -350,7 +359,7 @@ def update(self, timeout_seconds=TIMEOUT_SECONDS):
display_name=self.display_name,
serve_nodes=self.serve_nodes,
)
stub = make_stub(self.client._credentials, CLUSTER_STUB_FACTORY,
stub = make_stub(self.credentials, CLUSTER_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.UpdateCluster.async(request_pb, timeout_seconds)
Expand All @@ -369,7 +378,7 @@ def delete(self, timeout_seconds=TIMEOUT_SECONDS):
If not passed, defaults to ``TIMEOUT_SECONDS``.
"""
request_pb = messages_pb2.DeleteClusterRequest(name=self.name)
stub = make_stub(self.client._credentials, CLUSTER_STUB_FACTORY,
stub = make_stub(self.credentials, CLUSTER_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.DeleteCluster.async(request_pb, timeout_seconds)
Expand All @@ -384,7 +393,7 @@ def undelete(self, timeout_seconds=TIMEOUT_SECONDS):
If not passed, defaults to ``TIMEOUT_SECONDS``.
"""
request_pb = messages_pb2.UndeleteClusterRequest(name=self.name)
stub = make_stub(self.client._credentials, CLUSTER_STUB_FACTORY,
stub = make_stub(self.credentials, CLUSTER_STUB_FACTORY,
CLUSTER_ADMIN_HOST, CLUSTER_ADMIN_PORT)
with stub:
response = stub.UndeleteCluster.async(request_pb, timeout_seconds)
Expand Down
61 changes: 61 additions & 0 deletions gcloud_bigtable/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,40 @@
"""User friendly container for Google Cloud Bigtable Table."""


from gcloud_bigtable._generated import (
bigtable_table_service_messages_pb2 as messages_pb2)
from gcloud_bigtable._generated import bigtable_table_service_pb2
from gcloud_bigtable.connection import TIMEOUT_SECONDS
from gcloud_bigtable.connection import make_stub


TABLE_STUB_FACTORY = (bigtable_table_service_pb2.
early_adopter_create_BigtableTableService_stub)
TABLE_ADMIN_HOST = 'bigtabletableadmin.googleapis.com'
"""Table Admin API request host."""
TABLE_ADMIN_PORT = 443
"""Table Admin API request port."""


class Table(object):
"""Representation of a Google Cloud Bigtable Table.
.. note::
We don't define any properties on a table other than the name. As
the proto says, in a request:
"The `name` field of the Table and all of its ColumnFamilies must
be left blank, and will be populated in the response."
This leaves only the ``current_operation`` and ``granularity``
fields. The ``current_operation`` is only used for responses while
``granularity`` is an enum with only one value.
We can use a :class:`Table` to:
* Check if it :meth:`Table.exists`
:type table_id: string
:param table_id: The ID of the table.
Expand All @@ -38,6 +69,15 @@ def cluster(self):
"""
return self._cluster

@property
def credentials(self):
"""Getter for table's credentials.
:rtype: :class:`oauth2client.client.OAuth2Credentials`
:returns: The credentials stored on the table's client.
"""
return self._cluster.credentials

@property
def name(self):
"""Table name used in requests.
Expand All @@ -53,3 +93,24 @@ def name(self):
:returns: The table name.
"""
return self.cluster.name + '/tables/' + self.table_id

def exists(self, timeout_seconds=TIMEOUT_SECONDS):
"""Reload the metadata for this table.
:type timeout_seconds: integer
:param timeout_seconds: Number of seconds for request time-out.
If not passed, defaults to ``TIMEOUT_SECONDS``.
:rtype: boolean
:returns: Boolean indicating if this table exists. If it does not
exist, an exception will be thrown by the API call.
"""
request_pb = messages_pb2.GetTableRequest(name=self.name)
stub = make_stub(self.credentials, TABLE_STUB_FACTORY,
TABLE_ADMIN_HOST, TABLE_ADMIN_PORT)
with stub:
response = stub.GetTable.async(request_pb, timeout_seconds)
# We expect a `._generated.bigtable_table_data_pb2.Table`
response.result()

return True
53 changes: 51 additions & 2 deletions gcloud_bigtable/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,32 @@
# limitations under the License.


import unittest2
from gcloud_bigtable._grpc_mocks import GRPCMockTestMixin


PROJECT_ID = 'project-id'
TABLE_ID = 'table-id'


class TestTable(unittest2.TestCase):
class TestTable(GRPCMockTestMixin):

@classmethod
def setUpClass(cls):
from gcloud_bigtable import client
from gcloud_bigtable import table as MUT
cls._MUT = MUT
cls._STUB_SCOPES = [client.DATA_SCOPE]
cls._STUB_FACTORY_NAME = 'TABLE_STUB_FACTORY'
cls._STUB_HOST = MUT.TABLE_ADMIN_HOST
cls._STUB_PORT = MUT.TABLE_ADMIN_PORT

@classmethod
def tearDownClass(cls):
del cls._MUT
del cls._STUB_SCOPES
del cls._STUB_FACTORY_NAME
del cls._STUB_HOST
del cls._STUB_PORT

def _getTargetClass(self):
from gcloud_bigtable.table import Table
Expand All @@ -46,6 +65,36 @@ def test_name_property(self):
expected_name = cluster_name + '/tables/' + TABLE_ID
self.assertEqual(table.name, expected_name)

def test_exists(self):
from gcloud_bigtable._generated import (
bigtable_table_service_messages_pb2 as messages_pb2)

zone = 'zone'
cluster_id = 'cluster-id'

# Create request_pb
table_name = ('projects/' + PROJECT_ID + '/zones/' + zone +
'/clusters/' + cluster_id + '/tables/' + TABLE_ID)
request_pb = messages_pb2.GetTableRequest(name=table_name)

# Create response_pb
response_pb = None

# Create expected_result.
expected_result = True

# We must create the cluster with the client passed in.
TEST_CASE = self

def result_method(client):
cluster = client.cluster(zone, cluster_id)
table = TEST_CASE._makeOne(TABLE_ID, cluster)
return table.exists()

self._grpc_client_test_helper('GetTable', result_method,
request_pb, response_pb, expected_result,
PROJECT_ID)


class _Cluster(object):

Expand Down

0 comments on commit 44f0849

Please sign in to comment.