diff --git a/third_party/terraform/resources/resource_bigtable_instance.go b/third_party/terraform/resources/resource_bigtable_instance.go index ef33e3a59ea7..de12259ba4c9 100644 --- a/third_party/terraform/resources/resource_bigtable_instance.go +++ b/third_party/terraform/resources/resource_bigtable_instance.go @@ -19,6 +19,10 @@ func resourceBigtableInstance() *schema.Resource { Update: resourceBigtableInstanceUpdate, Delete: resourceBigtableInstanceDestroy, + Importer: &schema.ResourceImporter{ + State: resourceBigtableInstanceImport, + }, + CustomizeDiff: customdiff.All( resourceBigtableInstanceValidateDevelopment, resourceBigtableInstanceClusterReorderTypeList, @@ -185,22 +189,31 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro d.Set("project", project) - clusters := d.Get("cluster").([]interface{}) - clusterState := []map[string]interface{}{} - for _, cl := range clusters { - cluster := cl.(map[string]interface{}) - clus, err := c.GetCluster(ctx, instance.Name, cluster["cluster_id"].(string)) - if err != nil { - if isGoogleApiErrorWithCode(err, 404) { - log.Printf("[WARN] Cluster %q not found, not setting it in state", cluster["cluster_id"].(string)) - continue + clusters, err := c.Clusters(ctx, instance.Name) + if err != nil { + return fmt.Errorf("Error retrieving instance clusters. %s", err) + } + + clustersNewState := []map[string]interface{}{} + for i, cluster := range clusters { + // DEVELOPMENT clusters have num_nodes = 0 on their first (and only) + // cluster while PRODUCTION clusters will have at least 3. + if i == 0 { + var instanceType string + if cluster.ServeNodes == 0 { + instanceType = "DEVELOPMENT" + } else { + instanceType = "PRODUCTION" } - return fmt.Errorf("Error retrieving cluster %q: %s", cluster["cluster_id"].(string), err.Error()) + + d.Set("instance_type", instanceType) } - clusterState = append(clusterState, flattenBigtableCluster(clus, cluster["storage_type"].(string))) + + clustersNewState = append(clustersNewState, flattenBigtableCluster(cluster)) } - err = d.Set("cluster", clusterState) + log.Printf("[DEBUG] Setting clusters in state: %#v", clustersNewState) + err = d.Set("cluster", clustersNewState) if err != nil { return fmt.Errorf("Error setting clusters in state: %s", err.Error()) } @@ -279,7 +292,15 @@ func resourceBigtableInstanceDestroy(d *schema.ResourceData, meta interface{}) e return nil } -func flattenBigtableCluster(c *bigtable.ClusterInfo, storageType string) map[string]interface{} { +func flattenBigtableCluster(c *bigtable.ClusterInfo) map[string]interface{} { + var storageType string + switch c.StorageType { + case bigtable.SSD: + storageType = "SSD" + case bigtable.HDD: + storageType = "HDD" + } + return map[string]interface{}{ "zone": c.Zone, "num_nodes": c.ServeNodes, @@ -366,3 +387,23 @@ func resourceBigtableInstanceClusterReorderTypeList(diff *schema.ResourceDiff, m return nil } + +func resourceBigtableInstanceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/instances/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} diff --git a/third_party/terraform/tests/resource_bigtable_instance_test.go b/third_party/terraform/tests/resource_bigtable_instance_test.go index aa7fd5219a08..42be4974b733 100644 --- a/third_party/terraform/tests/resource_bigtable_instance_test.go +++ b/third_party/terraform/tests/resource_bigtable_instance_test.go @@ -27,17 +27,19 @@ func TestAccBigtableInstance_basic(t *testing.T) { }, { Config: testAccBigtableInstance(instanceName, 3), - Check: resource.ComposeTestCheckFunc( - testAccBigtableInstanceExists( - "google_bigtable_instance.instance", 3), - ), + }, + { + ResourceName: "google_bigtable_instance.instance", + ImportState: true, + ImportStateVerify: true, }, { Config: testAccBigtableInstance(instanceName, 4), - Check: resource.ComposeTestCheckFunc( - testAccBigtableInstanceExists( - "google_bigtable_instance.instance", 4), - ), + }, + { + ResourceName: "google_bigtable_instance.instance", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -59,17 +61,19 @@ func TestAccBigtableInstance_cluster(t *testing.T) { }, { Config: testAccBigtableInstance_cluster(instanceName, 3), - Check: resource.ComposeTestCheckFunc( - testAccBigtableInstanceExists( - "google_bigtable_instance.instance", 3), - ), + }, + { + ResourceName: "google_bigtable_instance.instance", + ImportState: true, + ImportStateVerify: true, }, { Config: testAccBigtableInstance_cluster_reordered(instanceName, 5), - Check: resource.ComposeTestCheckFunc( - testAccBigtableInstanceExists( - "google_bigtable_instance.instance", 5), - ), + }, + { + ResourceName: "google_bigtable_instance.instance", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -95,10 +99,11 @@ func TestAccBigtableInstance_development(t *testing.T) { }, { Config: testAccBigtableInstance_development(instanceName), - Check: resource.ComposeTestCheckFunc( - testAccBigtableInstanceExists( - "google_bigtable_instance.instance", 0), - ), + }, + { + ResourceName: "google_bigtable_instance.instance", + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -128,49 +133,6 @@ func testAccCheckBigtableInstanceDestroy(s *terraform.State) error { return nil } -func testAccBigtableInstanceExists(n string, numNodes int) resource.TestCheckFunc { - var ctx = context.Background() - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - config := testAccProvider.Meta().(*Config) - c, err := config.bigtableClientFactory.NewInstanceAdminClient(config.Project) - if err != nil { - return fmt.Errorf("Error starting instance admin client. %s", err) - } - - defer c.Close() - - _, err = c.InstanceInfo(ctx, rs.Primary.Attributes["name"]) - if err != nil { - return fmt.Errorf("Error retrieving instance %s.", rs.Primary.Attributes["name"]) - } - - clusters, err := c.Clusters(ctx, rs.Primary.Attributes["name"]) - if err != nil { - return fmt.Errorf("Error retrieving cluster list for instance %s.", rs.Primary.Attributes["name"]) - } - - for _, c := range clusters { - if c.ServeNodes != numNodes { - return fmt.Errorf("Expected cluster %s to have %d nodes but got %d nodes for instance %s.", - c.Name, - numNodes, - c.ServeNodes, - rs.Primary.Attributes["name"]) - } - } - - return nil - } -} - func testAccBigtableInstance(instanceName string, numNodes int) string { return fmt.Sprintf(` resource "google_bigtable_instance" "instance" { diff --git a/third_party/terraform/website/docs/r/bigtable_instance.html.markdown b/third_party/terraform/website/docs/r/bigtable_instance.html.markdown index afdf48974adf..ceeff0f1b187 100644 --- a/third_party/terraform/website/docs/r/bigtable_instance.html.markdown +++ b/third_party/terraform/website/docs/r/bigtable_instance.html.markdown @@ -76,3 +76,13 @@ The `cluster` block supports the following arguments: ## Attributes Reference Only the arguments listed above are exposed as attributes. + +## Import + +Bigtable Instances can be imported using any of these accepted formats: + +``` +$ terraform import google_bigtable_instance.default projects/{{project}}/instances/{{name}} +$ terraform import google_bigtable_instance.default {{project}}/{{name}} +$ terraform import google_bigtable_instance.default {{name}} +```