Getting Started with Bigtable Instance Administrative Operations
This example is a very simple "Instance Admin" application, which illustrates how to:
- Create a production instance.
- List the existing instances.
- Get the metadata for an instance.
- List all the clusters in an instance.
- Delete an instance.
Run the example
This example uses the Cloud Bigtable C++ Client Library to communicate with Cloud Bigtable.
To run the example program, follow the instructions for the example on GitHub.
Include the Necessary Headers
The example uses the following headers:
#include "google/cloud/bigtable/admin/bigtable_instance_admin_client.h"
Define aliases
To make the example less verbose we define some aliases:
namespace cbt = ::google::cloud::bigtable;
namespace cbta = ::google::cloud::bigtable_admin;
using ::google::cloud::future;
using ::google::cloud::Project;
using ::google::cloud::Status;
using ::google::cloud::StatusOr;
Connect to the Cloud Bigtable Instance Admin Endpoint.
Create an object of type bigtable_admin::BigtableInstanceAdminClient
to obtain information about Instances, Clusters, Application Profiles, and to change the IAM permissions in a Cloud Bigtable instance:
auto instance_admin = cbta::BigtableInstanceAdminClient(
cbta::MakeBigtableInstanceAdminConnection());
See Also
https://cloud.google.com/bigtable/docs/instances-clusters-nodes for more information about Cloud Bigtable instances, clusters, and nodes.
See Also
https://cloud.google.com/bigtable/docs/app-profiles for more information about Cloud Bigtable application profiles.
See Also
https://cloud.google.com/bigtable/docs/access-control for more information about access controls via IAM permissions on Cloud Bigtable.
Check if an Instance already exists
std::cout << "\nCheck Instance exists:\n";
std::string const project_name = Project(project_id).FullName();
StatusOr<google::bigtable::admin::v2::ListInstancesResponse> instances =
instance_admin.ListInstances(project_name);
if (!instances) throw std::move(instances).status();
if (!instances->failed_locations().empty()) {
std::cerr
<< "The service tells us it has no information about these locations:";
for (auto const& failed_location : instances->failed_locations()) {
std::cerr << " " << failed_location;
}
std::cerr << ". Continuing anyway\n";
}
std::string const instance_name = cbt::InstanceName(project_id, instance_id);
auto is_instance =
[&instance_name](google::bigtable::admin::v2::Instance const& i) {
return i.name() == instance_name;
};
auto const& ins = instances->instances();
auto instance_exists =
std::find_if(ins.begin(), ins.end(), is_instance) != ins.end();
std::cout << "The instance " << instance_id
<< (instance_exists ? " already exists" : " does not exist")
<< "\n";
See Also
BigtableInstanceAdminClient::GetInstance()
for another operation to query if an instance exists.
Create a Production Instance
Use BigtableInstanceAdminClient::CreateInstance()
to create a new instance:
std::cout << "\nCreating a PRODUCTION Instance: ";
// production instance needs at least 3 nodes
google::bigtable::admin::v2::Cluster c;
c.set_location(project_name + "/locations/" + zone);
c.set_serve_nodes(3);
c.set_default_storage_type(google::bigtable::admin::v2::HDD);
google::bigtable::admin::v2::Instance in;
in.set_display_name("Sample Instance");
in.set_type(google::bigtable::admin::v2::Instance::PRODUCTION);
future<void> creation_done =
instance_admin
.CreateInstance(project_name, instance_id, std::move(in),
{{cluster_id, std::move(c)}})
.then(
[instance_id](
future<StatusOr<google::bigtable::admin::v2::Instance>> f) {
auto instance = f.get();
if (!instance) {
std::cerr << "Could not create instance " << instance_id
<< "\n";
throw std::move(instance).status();
}
std::cout << "Successfully created instance: "
<< instance->DebugString() << "\n";
});
// Note how this blocks until the instance is created. In production code
// you may want to perform this task asynchronously.
creation_done.get();
std::cout << "DONE\n";
List Instances in a Project
Use BigtableInstanceAdminClient::ListInstances()
to list all the instances in the project:
std::cout << "\nListing Instances:\n";
instances = instance_admin.ListInstances(project_name);
if (!instances) throw std::move(instances).status();
if (!instances->failed_locations().empty()) {
std::cerr
<< "The service tells us it has no information about these locations:";
for (auto const& failed_location : instances->failed_locations()) {
std::cerr << " " << failed_location;
}
std::cerr << ". Continuing anyway\n";
}
for (auto const& instance : instances->instances()) {
std::cout << " " << instance.name() << "\n";
}
std::cout << "DONE\n";
See Also
The gRPC API documentation for ListInstances has more details on when failed_locations
might be populated.
Get an Instance Metadata
Use BigtableInstanceAdminClient::GetInstance()
to retrieve the metadata of an instance:
std::cout << "\nGet Instance:\n";
auto instance = instance_admin.GetInstance(instance_name);
if (!instance) throw std::move(instance).status();
std::cout << "Instance details :\n" << instance->DebugString() << "\n";
List clusters in an Instance
Use BigtableInstanceAdminClient::ListClusters()
to list all the clusters in an instance (or all the clusters in a project):
std::cout << "\nListing Clusters:\n";
StatusOr<google::bigtable::admin::v2::ListClustersResponse> cluster_list =
instance_admin.ListClusters(instance_name);
if (!cluster_list) throw std::move(cluster_list).status();
if (!cluster_list->failed_locations().empty()) {
std::cout << "The Cloud Bigtable service reports that the following "
"locations are temporarily unavailable and no information "
"about clusters in these locations can be obtained:\n";
for (auto const& failed_location : cluster_list->failed_locations()) {
std::cout << failed_location << "\n";
}
}
std::cout << "Cluster Name List:\n";
for (auto const& cluster : cluster_list->clusters()) {
std::cout << "Cluster Name: " << cluster.name() << "\n";
}
std::cout << "DONE\n";
See Also
The bigtable_admin::BigtableInstanceAdminClient
class also has functions to create, update, delete, and retrieve the metadata of a Cluster.
See Also
The gRPC API documentation for ListClusters has more details on when failed_locations
might be populated.
Delete an instance
Finally, use BigtableInstanceAdminClient::DeleteInstance()
to delete an instance:
std::cout << "Deleting instance " << instance_id << "\n";
Status delete_status = instance_admin.DeleteInstance(instance_name);
if (!delete_status.ok()) throw std::runtime_error(delete_status.message());
std::cout << "DONE\n";
Put it all together
Here is the full example
#include "google/cloud/bigtable/admin/bigtable_instance_admin_client.h"
#include "google/cloud/bigtable/examples/bigtable_examples_common.h"
#include "google/cloud/bigtable/resource_names.h"
#include "google/cloud/bigtable/testing/cleanup_stale_resources.h"
#include "google/cloud/bigtable/testing/random_names.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/random.h"
#include "google/cloud/log.h"
#include "google/cloud/project.h"
#include <algorithm>
#include <iostream>
namespace {
using ::google::cloud::bigtable::examples::Usage;
void BigtableHelloInstance(std::vector<std::string> const& argv) {
if (argv.size() != 4) {
throw Usage{
"bigtable-hello-instance <project-id> <instance-id> <cluster-id> "
"<zone>"};
}
std::string const& project_id = argv[0];
std::string const& instance_id = argv[1];
std::string const& cluster_id = argv[2];
std::string const& zone = argv[3];
namespace cbt = ::google::cloud::bigtable;
namespace cbta = ::google::cloud::bigtable_admin;
using ::google::cloud::future;
using ::google::cloud::Project;
using ::google::cloud::Status;
using ::google::cloud::StatusOr;
// Connect to the Cloud Bigtable admin endpoint.
auto instance_admin = cbta::BigtableInstanceAdminClient(
cbta::MakeBigtableInstanceAdminConnection());
std::cout << "\nCheck Instance exists:\n";
std::string const project_name = Project(project_id).FullName();
StatusOr<google::bigtable::admin::v2::ListInstancesResponse> instances =
instance_admin.ListInstances(project_name);
if (!instances) throw std::move(instances).status();
if (!instances->failed_locations().empty()) {
std::cerr
<< "The service tells us it has no information about these locations:";
for (auto const& failed_location : instances->failed_locations()) {
std::cerr << " " << failed_location;
}
std::cerr << ". Continuing anyway\n";
}
std::string const instance_name = cbt::InstanceName(project_id, instance_id);
auto is_instance =
[&instance_name](google::bigtable::admin::v2::Instance const& i) {
return i.name() == instance_name;
};
auto const& ins = instances->instances();
auto instance_exists =
std::find_if(ins.begin(), ins.end(), is_instance) != ins.end();
std::cout << "The instance " << instance_id
<< (instance_exists ? " already exists" : " does not exist")
<< "\n";
// Create instance if it does not exist
if (!instance_exists) {
std::cout << "\nCreating a PRODUCTION Instance: ";
// production instance needs at least 3 nodes
google::bigtable::admin::v2::Cluster c;
c.set_location(project_name + "/locations/" + zone);
c.set_serve_nodes(3);
c.set_default_storage_type(google::bigtable::admin::v2::HDD);
google::bigtable::admin::v2::Instance in;
in.set_display_name("Sample Instance");
in.set_type(google::bigtable::admin::v2::Instance::PRODUCTION);
future<void> creation_done =
instance_admin
.CreateInstance(project_name, instance_id, std::move(in),
{{cluster_id, std::move(c)}})
.then(
[instance_id](
future<StatusOr<google::bigtable::admin::v2::Instance>> f) {
auto instance = f.get();
if (!instance) {
std::cerr << "Could not create instance " << instance_id
<< "\n";
throw std::move(instance).status();
}
std::cout << "Successfully created instance: "
<< instance->DebugString() << "\n";
});
// Note how this blocks until the instance is created. In production code
// you may want to perform this task asynchronously.
creation_done.get();
std::cout << "DONE\n";
}
std::cout << "\nListing Instances:\n";
instances = instance_admin.ListInstances(project_name);
if (!instances) throw std::move(instances).status();
if (!instances->failed_locations().empty()) {
std::cerr
<< "The service tells us it has no information about these locations:";
for (auto const& failed_location : instances->failed_locations()) {
std::cerr << " " << failed_location;
}
std::cerr << ". Continuing anyway\n";
}
for (auto const& instance : instances->instances()) {
std::cout << " " << instance.name() << "\n";
}
std::cout << "DONE\n";
std::cout << "\nGet Instance:\n";
auto instance = instance_admin.GetInstance(instance_name);
if (!instance) throw std::move(instance).status();
std::cout << "Instance details :\n" << instance->DebugString() << "\n";
std::cout << "\nListing Clusters:\n";
StatusOr<google::bigtable::admin::v2::ListClustersResponse> cluster_list =
instance_admin.ListClusters(instance_name);
if (!cluster_list) throw std::move(cluster_list).status();
if (!cluster_list->failed_locations().empty()) {
std::cout << "The Cloud Bigtable service reports that the following "
"locations are temporarily unavailable and no information "
"about clusters in these locations can be obtained:\n";
for (auto const& failed_location : cluster_list->failed_locations()) {
std::cout << failed_location << "\n";
}
}
std::cout << "Cluster Name List:\n";
for (auto const& cluster : cluster_list->clusters()) {
std::cout << "Cluster Name: " << cluster.name() << "\n";
}
std::cout << "DONE\n";
std::cout << "Deleting instance " << instance_id << "\n";
Status delete_status = instance_admin.DeleteInstance(instance_name);
if (!delete_status.ok()) throw std::runtime_error(delete_status.message());
std::cout << "DONE\n";
}
void RunAll(std::vector<std::string> const& argv) {
namespace examples = ::google::cloud::bigtable::examples;
namespace cbta = ::google::cloud::bigtable_admin;
if (!argv.empty()) throw Usage{"auto"};
if (!examples::RunAdminIntegrationTests()) return;
examples::CheckEnvironmentVariablesAreSet({
"GOOGLE_CLOUD_PROJECT",
"GOOGLE_CLOUD_CPP_BIGTABLE_TEST_ZONE_A",
});
auto const project_id =
google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
auto const zone_a =
google::cloud::internal::GetEnv("GOOGLE_CLOUD_CPP_BIGTABLE_TEST_ZONE_A")
.value();
auto generator = google::cloud::internal::DefaultPRNG(std::random_device{}());
google::cloud::bigtable::testing::CleanupStaleInstances(
cbta::MakeBigtableInstanceAdminConnection(), project_id);
auto const instance_id =
google::cloud::bigtable::testing::RandomInstanceId(generator);
auto const cluster_id = instance_id + "-c1";
std::cout << "\nRunning the BigtableHelloInstance() example" << std::endl;
BigtableHelloInstance({project_id, instance_id, cluster_id, zone_a});
}
} // namespace
int main(int argc, char* argv[]) try {
google::cloud::bigtable::examples::Example example({
{"auto", RunAll},
{"hello-instance", BigtableHelloInstance},
});
return example.Run(argc, argv);
} catch (std::exception const& ex) {
std::cerr << ex.what() << "\n";
::google::cloud::LogSink::Instance().Flush();
return 1;
}