Skip to content

Commit

Permalink
add deletion_protection field for bigtable instance (#3450) (#6357)
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored May 12, 2020
1 parent b369300 commit 35de36a
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changelog/3450.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:enhancement
* bigtable: added `deletion_protection` field to `google_bigtable_instance` to make deleting them require an explicit intent.
```
```release-note:note
* `google_bigtable_instance` resources now cannot be destroyed unless `deletion_protection = false` is set in state for the resource.
```
10 changes: 8 additions & 2 deletions google/resource_bigtable_app_profile_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ func TestAccBigtableAppProfile_bigtableAppProfileMulticlusterExample(t *testing.
t.Parallel()

context := map[string]interface{}{
"random_suffix": randString(t, 10),
"deletion_protection": false,
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
Expand Down Expand Up @@ -58,6 +59,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = 3
storage_type = "HDD"
}
deletion_protection = "%{deletion_protection}"
}
resource "google_bigtable_app_profile" "ap" {
Expand All @@ -74,7 +77,8 @@ func TestAccBigtableAppProfile_bigtableAppProfileSingleclusterExample(t *testing
t.Parallel()

context := map[string]interface{}{
"random_suffix": randString(t, 10),
"deletion_protection": false,
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
Expand Down Expand Up @@ -105,6 +109,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = 3
storage_type = "HDD"
}
deletion_protection = "%{deletion_protection}"
}
resource "google_bigtable_app_profile" "ap" {
Expand Down
4 changes: 4 additions & 0 deletions google/resource_bigtable_app_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = 3
storage_type = "HDD"
}
deletion_protection = false
}
resource "google_bigtable_app_profile" "ap" {
Expand All @@ -71,6 +73,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = 3
storage_type = "HDD"
}
deletion_protection = false
}
resource "google_bigtable_app_profile" "ap" {
Expand Down
2 changes: 2 additions & 0 deletions google/resource_bigtable_gc_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ resource "google_bigtable_instance" "instance" {
}
instance_type = "DEVELOPMENT"
deletion_protection = false
}
resource "google_bigtable_table" "table" {
Expand Down Expand Up @@ -170,6 +171,7 @@ resource "google_bigtable_instance" "instance" {
}
instance_type = "DEVELOPMENT"
deletion_protection = false
}
resource "google_bigtable_table" "table" {
Expand Down
18 changes: 18 additions & 0 deletions google/resource_bigtable_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ func resourceBigtableInstance() *schema.Resource {
resourceBigtableInstanceClusterReorderTypeList,
),

SchemaVersion: 1,
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceBigtableInstanceResourceV0().CoreConfigSchema().ImpliedType(),
Upgrade: resourceBigtableInstanceUpgradeV0,
Version: 0,
},
},

// ----------------------------------------------------------------------
// IMPORTANT: Do not add any additional ForceNew fields to this resource.
// Destroying/recreating instances can lead to data loss for users.
Expand Down Expand Up @@ -82,6 +91,12 @@ func resourceBigtableInstance() *schema.Resource {
ValidateFunc: validation.StringInSlice([]string{"DEVELOPMENT", "PRODUCTION"}, false),
},

"deletion_protection": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},

"project": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -235,6 +250,9 @@ func resourceBigtableInstanceUpdate(d *schema.ResourceData, meta interface{}) er
}

func resourceBigtableInstanceDestroy(d *schema.ResourceData, meta interface{}) error {
if d.Get("deletion_protection").(bool) {
return fmt.Errorf("cannot destroy instance without setting deletion_protection=false and running `terraform apply`")
}
config := meta.(*Config)
ctx := context.Background()

Expand Down
2 changes: 2 additions & 0 deletions google/resource_bigtable_instance_iam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,7 @@ resource "google_bigtable_instance" "instance" {
zone = "us-central1-b"
storage_type = "HDD"
}
deletion_protection = false
}
`
80 changes: 80 additions & 0 deletions google/resource_bigtable_instance_migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package google

import (
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceBigtableInstanceResourceV0() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"cluster": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cluster_id": {
Type: schema.TypeString,
Required: true,
},
"zone": {
Type: schema.TypeString,
Required: true,
},
"num_nodes": {
Type: schema.TypeInt,
Optional: true,
// DEVELOPMENT instances could get returned with either zero or one node,
// so mark as computed.
Computed: true,
ValidateFunc: validation.IntAtLeast(1),
},
"storage_type": {
Type: schema.TypeString,
Optional: true,
Default: "SSD",
ValidateFunc: validation.StringInSlice([]string{"SSD", "HDD"}, false),
},
},
},
},
"display_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"instance_type": {
Type: schema.TypeString,
Optional: true,
Default: "PRODUCTION",
ValidateFunc: validation.StringInSlice([]string{"DEVELOPMENT", "PRODUCTION"}, false),
},

"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}

func resourceBigtableInstanceUpgradeV0(rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
log.Printf("[DEBUG] Attributes before migration: %#v", rawState)

rawState["deletion_protection"] = true

log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
return rawState, nil
}
71 changes: 64 additions & 7 deletions google/resource_bigtable_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestAccBigtableInstance_basic(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
{
Config: testAccBigtableInstance(instanceName, 4),
Expand All @@ -40,7 +40,7 @@ func TestAccBigtableInstance_basic(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
},
})
Expand All @@ -67,7 +67,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
{
Config: testAccBigtableInstance_clusterReordered(instanceName, 5),
Expand All @@ -76,7 +76,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
{
Config: testAccBigtableInstance_clusterModified(instanceName, 5),
Expand All @@ -85,7 +85,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
{
Config: testAccBigtableInstance_clusterReordered(instanceName, 5),
Expand All @@ -94,7 +94,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
},
})
Expand All @@ -117,7 +117,38 @@ func TestAccBigtableInstance_development(t *testing.T) {
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"instance_type"}, // we don't read instance type back
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
},
})
}

func TestAccBigtableInstance_allowDestroy(t *testing.T) {
t.Parallel()

instanceName := fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckBigtableInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccBigtableInstance_noAllowDestroy(instanceName, 3),
},
{
ResourceName: "google_bigtable_instance.instance",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back
},
{
Config: testAccBigtableInstance_noAllowDestroy(instanceName, 3),
Destroy: true,
ExpectError: regexp.MustCompile("deletion_protection"),
},
{
Config: testAccBigtableInstance(instanceName, 3),
},
},
})
Expand Down Expand Up @@ -159,6 +190,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = %d
storage_type = "HDD"
}
deletion_protection = false
}
`, instanceName, instanceName, numNodes)
}
Expand Down Expand Up @@ -199,6 +232,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = %d
storage_type = "HDD"
}
deletion_protection = false
}
`, instanceName, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes)
}
Expand Down Expand Up @@ -237,6 +272,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = 3
storage_type = "HDD"
}
deletion_protection = false
}
`, instanceName, instanceName, instanceName, instanceName, instanceName, instanceName)
}
Expand Down Expand Up @@ -269,6 +306,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = %d
storage_type = "HDD"
}
deletion_protection = false
}
`, instanceName, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes)
}
Expand All @@ -295,6 +334,8 @@ resource "google_bigtable_instance" "instance" {
num_nodes = %d
storage_type = "HDD"
}
deletion_protection = false
}
`, instanceName, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes)
}
Expand All @@ -308,6 +349,22 @@ resource "google_bigtable_instance" "instance" {
zone = "us-central1-b"
}
instance_type = "DEVELOPMENT"
deletion_protection = false
}
`, instanceName, instanceName)
}

func testAccBigtableInstance_noAllowDestroy(instanceName string, numNodes int) string {
return fmt.Sprintf(`
resource "google_bigtable_instance" "instance" {
name = "%s"
cluster {
cluster_id = "%s"
zone = "us-central1-b"
num_nodes = %d
storage_type = "HDD"
}
}
`, instanceName, instanceName, numNodes)
}
Loading

0 comments on commit 35de36a

Please sign in to comment.