diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/bigtable/InstanceAdminExample.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/bigtable/InstanceAdminExample.java
new file mode 100644
index 000000000000..bfeb1bb42c7f
--- /dev/null
+++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/bigtable/InstanceAdminExample.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.cloud.examples.bigtable;
+
+import com.google.api.gax.rpc.AlreadyExistsException;
+import com.google.api.gax.rpc.NotFoundException;
+import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient;
+import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminSettings;
+import com.google.cloud.bigtable.admin.v2.models.Cluster;
+import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest;
+import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest;
+import com.google.cloud.bigtable.admin.v2.models.Instance;
+import com.google.cloud.bigtable.admin.v2.models.PartialListInstancesException;
+import com.google.cloud.bigtable.admin.v2.models.StorageType;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An example of using Google Cloud Bigtable.
+ *
+ *
This example demonstrates the usage of BigtableInstanceAdminClient to create, configure, and
+ * delete Cloud Bigtable Instances and Clusters.
+ *
+ *
+ * - creates production instance
+ *
- lists instances
+ *
- gets instance
+ *
- lists clusters
+ *
- adds cluster
+ *
- deletes cluster
+ *
- deletes instance
+ *
+ */
+public class InstanceAdminExample {
+
+ private static final String CLUSTER = "cluster";
+ private final String clusterId;
+ private final String instanceId;
+ private final BigtableInstanceAdminClient adminClient;
+
+ public static void main(String[] args) throws IOException {
+
+ if (args.length != 1) {
+ System.out.println("Missing required project id");
+ return;
+ }
+ String projectId = args[0];
+
+ InstanceAdminExample instanceAdmin =
+ new InstanceAdminExample(projectId, "ssd-instance", "ssd-cluster");
+ instanceAdmin.run();
+ }
+
+ public InstanceAdminExample(String projectId, String instanceId, String clusterId)
+ throws IOException {
+ this.instanceId = instanceId;
+ this.clusterId = clusterId;
+
+ // [START connecting_to_bigtable]
+ // Creates the settings to configure a bigtable instance admin client.
+ BigtableInstanceAdminSettings instanceAdminSettings =
+ BigtableInstanceAdminSettings.newBuilder().setProjectId(projectId).build();
+
+ // Creates a bigtable instance admin client.
+ adminClient = BigtableInstanceAdminClient.create(instanceAdminSettings);
+ // [END connecting_to_bigtable]
+ }
+
+ public void run() {
+ createProdInstance();
+ listInstances();
+ getInstance();
+ listClusters();
+ addCluster();
+ deleteCluster();
+ deleteInstance();
+ adminClient.close();
+ }
+
+ /** Demonstrates how to create a Production instance within a provided project. */
+ public void createProdInstance() {
+ // Checks if instance exists, creates instance if does not exists.
+ if (!adminClient.exists(instanceId)) {
+ System.out.println("Instance does not exist, creating a PRODUCTION instance");
+ // [START bigtable_create_prod_instance]
+ // Creates a Production Instance with the ID "ssd-instance",
+ // cluster id "ssd-cluster", 3 nodes and location "us-central1-f".
+ CreateInstanceRequest createInstanceRequest =
+ CreateInstanceRequest.of(instanceId)
+ .addCluster(clusterId, "us-central1-f", 3, StorageType.SSD)
+ .setType(Instance.Type.PRODUCTION)
+ .addLabel("department", "accounting");
+ // Creates a production instance with the given request.
+ try {
+ Instance instance = adminClient.createInstance(createInstanceRequest);
+ System.out.printf("PRODUCTION type instance %s created successfully%n", instance.getId());
+ } catch (Exception e) {
+ System.err.println("Failed to create instance: " + e.getMessage());
+ throw e;
+ }
+ // [END bigtable_create_prod_instance]
+ }
+ }
+
+ /** Demonstrates how to list all instances within a project. */
+ public void listInstances() {
+ System.out.println("\nListing Instances");
+ // [START bigtable_list_instances]
+ try {
+ List instances = adminClient.listInstances();
+ for (Instance instance : instances) {
+ System.out.println(instance.getId());
+ }
+ } catch (PartialListInstancesException e) {
+ System.err.println("Failed to list instances: " + e.getMessage());
+ System.err.println("The following zones are unavailable: " + e.getUnavailableZones());
+ System.err.println("But the following instances are reachable: " + e.getInstances());
+ }
+ // [END bigtable_list_instances]
+ }
+
+ /** Demonstrates how to get an instance. */
+ public Instance getInstance() {
+ System.out.println("\nGet Instance");
+ // [START bigtable_get_instance]
+ Instance instance = null;
+ try {
+ instance = adminClient.getInstance(instanceId);
+ System.out.println("Instance ID: " + instance.getId());
+ System.out.println("Display Name: " + instance.getDisplayName());
+ System.out.print("Labels: ");
+ Map labels = instance.getLabels();
+ for (String key : labels.keySet()) {
+ System.out.printf("%s - %s", key, labels.get(key));
+ }
+ System.out.println("\nState: " + instance.getState());
+ System.out.println("Type: " + instance.getType());
+ } catch (NotFoundException e) {
+ System.err.println("Failed to get non-existent instance: " + e.getMessage());
+ }
+ // [END bigtable_get_instance]
+ return instance;
+ }
+
+ /** Demonstrates how to list clusters within an instance. */
+ public void listClusters() {
+ System.out.println("\nListing Clusters");
+ // [START bigtable_get_clusters]
+ try {
+ List clusters = adminClient.listClusters(instanceId);
+ for (Cluster cluster : clusters) {
+ System.out.println(cluster.getId());
+ }
+ } catch (NotFoundException e) {
+ System.err.println("Failed to list clusters from a non-existent instance: " + e.getMessage());
+ }
+ // [END bigtable_get_clusters]
+ }
+
+ /** Demonstrates how to delete an instance. */
+ public void deleteInstance() {
+ System.out.println("\nDeleting Instance");
+ // [START bigtable_delete_instance]
+ try {
+ adminClient.deleteInstance(instanceId);
+ System.out.println("Instance deleted: " + instanceId);
+ } catch (NotFoundException e) {
+ System.err.println("Failed to delete non-existent instance: " + e.getMessage());
+ }
+ // [END bigtable_delete_instance]
+ }
+
+ /** Demonstrates how to add a cluster to an instance. */
+ public void addCluster() {
+ System.out.printf("%nAdding cluster: %s to instance: %s%n", CLUSTER, instanceId);
+ // [START bigtable_create_cluster]
+ try {
+ adminClient.createCluster(
+ CreateClusterRequest.of(instanceId, CLUSTER)
+ .setZone("us-central1-c")
+ .setServeNodes(3)
+ .setStorageType(StorageType.SSD));
+ System.out.printf("Cluster: %s created successfully%n", CLUSTER);
+ } catch (AlreadyExistsException e) {
+ System.err.println("Failed to add cluster, already exists: " + e.getMessage());
+ }
+ // [END bigtable_create_cluster]
+ }
+
+ /** Demonstrates how to delete a cluster from an instance. */
+ public void deleteCluster() {
+ System.out.printf("%nDeleting cluster: %s from instance: %s%n", CLUSTER, instanceId);
+ // [START bigtable_delete_cluster]
+ try {
+ adminClient.deleteCluster(instanceId, CLUSTER);
+ System.out.printf("Cluster: %s deleted successfully%n", CLUSTER);
+ } catch (NotFoundException e) {
+ System.err.println("Failed to delete a non-existent cluster: " + e.getMessage());
+ }
+ // [END bigtable_delete_cluster]
+ }
+}
diff --git a/google-cloud-examples/src/test/java/com/google/cloud/examples/bigtable/ITInstanceAdminExample.java b/google-cloud-examples/src/test/java/com/google/cloud/examples/bigtable/ITInstanceAdminExample.java
new file mode 100644
index 000000000000..bb800f683838
--- /dev/null
+++ b/google-cloud-examples/src/test/java/com/google/cloud/examples/bigtable/ITInstanceAdminExample.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.cloud.examples.bigtable;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.gax.rpc.NotFoundException;
+import com.google.bigtable.admin.v2.InstanceName;
+import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient;
+import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminSettings;
+import com.google.cloud.bigtable.admin.v2.models.Cluster;
+import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest;
+import com.google.cloud.bigtable.admin.v2.models.Instance;
+import com.google.cloud.bigtable.admin.v2.models.Instance.Type;
+import com.google.cloud.bigtable.admin.v2.models.StorageType;
+import java.io.IOException;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.AssumptionViolatedException;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Integration tests for {@link InstanceAdminExample} */
+public class ITInstanceAdminExample {
+
+ private static final String INSTANCE_PROPERTY_NAME = "bigtable.instance";
+ private static final String ID_PREFIX = "instanceadmin";
+ private static final String CLUSTER = "cluster";
+ private static String projectName;
+ private static BigtableInstanceAdminClient adminClient;
+ private String clusterId;
+ private String instanceId;
+ private InstanceAdminExample instanceAdmin;
+
+ @BeforeClass
+ public static void beforeClass() throws IOException {
+ String targetProject = System.getProperty(INSTANCE_PROPERTY_NAME);
+ if (targetProject == null) {
+ adminClient = null;
+ return;
+ }
+ projectName = InstanceName.parse(targetProject).getProject();
+ BigtableInstanceAdminSettings instanceAdminSettings =
+ BigtableInstanceAdminSettings.newBuilder().setProjectId(projectName).build();
+ adminClient = BigtableInstanceAdminClient.create(instanceAdminSettings);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ garbageCollect();
+ adminClient.close();
+ }
+
+ @Before
+ public void setup() throws IOException {
+ if (adminClient == null) {
+ throw new AssumptionViolatedException(
+ INSTANCE_PROPERTY_NAME + " property is not set, skipping integration tests.");
+ }
+ instanceId = generateId();
+ clusterId = generateId();
+ instanceAdmin = new InstanceAdminExample(projectName, instanceId, clusterId);
+ adminClient.createInstance(
+ CreateInstanceRequest.of(instanceId)
+ .addCluster(clusterId, "us-central1-f", 3, StorageType.SSD)
+ .setType(Type.PRODUCTION)
+ .addLabel("example", "instance_admin"));
+ }
+
+ @After
+ public void after() {
+ if (adminClient.exists(instanceId)) {
+ adminClient.deleteInstance(instanceId);
+ }
+ }
+
+ @Test
+ public void testCreateAndDeleteInstance() throws IOException {
+ // Creates an instance.
+ String testInstance = generateId();
+ String testCluster = generateId();
+ InstanceAdminExample testInstanceAdmin =
+ new InstanceAdminExample(projectName, testInstance, testCluster);
+ testInstanceAdmin.createProdInstance();
+ assertTrue(adminClient.exists(testInstance));
+
+ // Deletes an instance.
+ testInstanceAdmin.deleteInstance();
+ assertFalse(adminClient.exists(testInstance));
+ }
+
+ @Test
+ public void testGetInstance() {
+ // Gets an instance.
+ Instance instance = instanceAdmin.getInstance();
+ assertNotNull(instance);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testAddAndDeleteCluster() {
+ // Adds a cluster.
+ instanceAdmin.addCluster();
+ Cluster cluster = adminClient.getCluster(instanceId, CLUSTER);
+ assertNotNull(cluster);
+
+ // Deletes a cluster.
+ instanceAdmin.deleteCluster();
+ adminClient.getCluster(instanceId, CLUSTER);
+ }
+
+ // TODO: add test for instanceAdmin.listInstances()
+ // TODO: and test for instanceAdmin.listClusters()
+
+ @Test
+ public void testRunDoesNotFail() {
+ instanceAdmin.run();
+ }
+
+ private static String generateId() {
+ return String.format("%s-%x", ID_PREFIX, new Random().nextInt());
+ }
+
+ private static void garbageCollect() {
+ Pattern timestampPattern = Pattern.compile(ID_PREFIX + "-([0-9a-f]+)");
+ System.out.println();
+ for (Instance instance : adminClient.listInstances()) {
+ Matcher matcher = timestampPattern.matcher(instance.getId());
+ if (!matcher.matches()) {
+ continue;
+ }
+ System.out.println("Garbage collecting orphaned table: " + instance);
+ adminClient.deleteInstance(instance.getId());
+ }
+ }
+}