Skip to content

Add DeletionProtectionEnabled to Redis Cluster #7995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/10367.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
redis: added a `deletion_protection_enabled` field with a default value of `true` to the `google_redis_cluster` resource
```
35 changes: 35 additions & 0 deletions google-beta/services/redis/resource_redis_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ projects/{network_project_id_or_number}/global/networks/{network_id}.`,
Description: `Optional. The authorization mode of the Redis cluster. If not provided, auth feature is disabled for the cluster. Default value: "AUTH_MODE_DISABLED" Possible values: ["AUTH_MODE_UNSPECIFIED", "AUTH_MODE_IAM_AUTH", "AUTH_MODE_DISABLED"]`,
Default: "AUTH_MODE_DISABLED",
},
"deletion_protection_enabled": {
Type: schema.TypeBool,
Optional: true,
Description: `Optional. Indicates if the cluster is deletion protected or not.
If the value if set to true, any delete cluster operation will fail.
Default value is true.`,
Default: true,
},
"node_type": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -347,6 +355,12 @@ func resourceRedisClusterCreate(d *schema.ResourceData, meta interface{}) error
} else if v, ok := d.GetOkExists("shard_count"); !tpgresource.IsEmptyValue(reflect.ValueOf(shardCountProp)) && (ok || !reflect.DeepEqual(v, shardCountProp)) {
obj["shardCount"] = shardCountProp
}
deletionProtectionEnabledProp, err := expandRedisClusterDeletionProtectionEnabled(d.Get("deletion_protection_enabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("deletion_protection_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(deletionProtectionEnabledProp)) && (ok || !reflect.DeepEqual(v, deletionProtectionEnabledProp)) {
obj["deletionProtectionEnabled"] = deletionProtectionEnabledProp
}
redisConfigsProp, err := expandRedisClusterRedisConfigs(d.Get("redis_configs"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -502,6 +516,9 @@ func resourceRedisClusterRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("shard_count", flattenRedisClusterShardCount(res["shardCount"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("deletion_protection_enabled", flattenRedisClusterDeletionProtectionEnabled(res["deletionProtectionEnabled"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("redis_configs", flattenRedisClusterRedisConfigs(res["redisConfigs"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
Expand Down Expand Up @@ -543,6 +560,12 @@ func resourceRedisClusterUpdate(d *schema.ResourceData, meta interface{}) error
} else if v, ok := d.GetOkExists("shard_count"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, shardCountProp)) {
obj["shardCount"] = shardCountProp
}
deletionProtectionEnabledProp, err := expandRedisClusterDeletionProtectionEnabled(d.Get("deletion_protection_enabled"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("deletion_protection_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, deletionProtectionEnabledProp)) {
obj["deletionProtectionEnabled"] = deletionProtectionEnabledProp
}
redisConfigsProp, err := expandRedisClusterRedisConfigs(d.Get("redis_configs"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -571,6 +594,10 @@ func resourceRedisClusterUpdate(d *schema.ResourceData, meta interface{}) error
updateMask = append(updateMask, "shardCount")
}

if d.HasChange("deletion_protection_enabled") {
updateMask = append(updateMask, "deletionProtectionEnabled")
}

if d.HasChange("redis_configs") {
updateMask = append(updateMask, "redisConfigs")
}
Expand Down Expand Up @@ -958,6 +985,10 @@ func flattenRedisClusterShardCount(v interface{}, d *schema.ResourceData, config
return v // let terraform core handle it otherwise
}

func flattenRedisClusterDeletionProtectionEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenRedisClusterRedisConfigs(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
Expand Down Expand Up @@ -1042,6 +1073,10 @@ func expandRedisClusterShardCount(v interface{}, d tpgresource.TerraformResource
return v, nil
}

func expandRedisClusterDeletionProtectionEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandRedisClusterRedisConfigs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func TestAccRedisCluster_redisClusterHaExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"prevent_destroy": false,
"random_suffix": acctest.RandString(t, 10),
"deletion_protection_enabled": false,
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
Expand Down Expand Up @@ -72,16 +72,14 @@ resource "google_redis_cluster" "cluster-ha" {
redis_configs = {
maxmemory-policy = "volatile-ttl"
}
deletion_protection_enabled = false

zone_distribution_config {
mode = "MULTI_ZONE"
}
depends_on = [
google_network_connectivity_service_connection_policy.default
]

lifecycle {
prevent_destroy = %{prevent_destroy}
}
}

resource "google_network_connectivity_service_connection_policy" "default" {
Expand Down Expand Up @@ -113,8 +111,8 @@ func TestAccRedisCluster_redisClusterHaSingleZoneExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"prevent_destroy": false,
"random_suffix": acctest.RandString(t, 10),
"deletion_protection_enabled": false,
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
Expand Down Expand Up @@ -148,13 +146,11 @@ resource "google_redis_cluster" "cluster-ha-single-zone" {
mode = "SINGLE_ZONE"
zone = "us-central1-f"
}
deletion_protection_enabled = false
depends_on = [
google_network_connectivity_service_connection_policy.default
]

lifecycle {
prevent_destroy = %{prevent_destroy}
}
}

resource "google_network_connectivity_service_connection_policy" "default" {
Expand Down
97 changes: 63 additions & 34 deletions google-beta/services/redis/resource_redis_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

func TestAccRedisCluster_createClusterWithNodeType(t *testing.T) {

t.Parallel()

name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t))
Expand All @@ -23,7 +24,7 @@ func TestAccRedisCluster_createClusterWithNodeType(t *testing.T) {
Steps: []resource.TestStep{
{
// create cluster with replica count 1
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, deletionProtectionEnabled: true, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -33,7 +34,7 @@ func TestAccRedisCluster_createClusterWithNodeType(t *testing.T) {
},
{
// clean up the resource
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, deletionProtectionEnabled: false, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE"}),
},
},
})
Expand All @@ -52,7 +53,7 @@ func TestAccRedisCluster_createClusterWithZoneDistribution(t *testing.T) {
Steps: []resource.TestStep{
{
// create cluster with replica count 1
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false, zoneDistributionMode: "SINGLE_ZONE", zone: "us-central1-b"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "SINGLE_ZONE", zone: "us-central1-b"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -62,7 +63,7 @@ func TestAccRedisCluster_createClusterWithZoneDistribution(t *testing.T) {
},
{
// clean up the resource
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false, zoneDistributionMode: "SINGLE_ZONE", zone: "us-central1-b"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "SINGLE_ZONE", zone: "us-central1-b"}),
},
},
})
Expand All @@ -81,7 +82,7 @@ func TestAccRedisCluster_updateReplicaCount(t *testing.T) {
Steps: []resource.TestStep{
{
// create cluster with replica count 1
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -91,21 +92,17 @@ func TestAccRedisCluster_updateReplicaCount(t *testing.T) {
},
{
// update replica count to 2
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 2, shardCount: 3, preventDestroy: true, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 2, shardCount: 3, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"psc_configs"},
},
{
// clean up the resource
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: false, zoneDistributionMode: "MULTI_ZONE"}),
},
{
// update replica count to 0
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: true, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -115,7 +112,7 @@ func TestAccRedisCluster_updateReplicaCount(t *testing.T) {
},
{
// clean up the resource
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE"}),
},
},
})
Expand All @@ -134,7 +131,7 @@ func TestAccRedisCluster_updateShardCount(t *testing.T) {
Steps: []resource.TestStep{
{
// create cluster with shard count 3
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -144,7 +141,7 @@ func TestAccRedisCluster_updateShardCount(t *testing.T) {
},
{
// update shard count to 5
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, preventDestroy: true, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
Expand All @@ -154,7 +151,7 @@ func TestAccRedisCluster_updateShardCount(t *testing.T) {
},
{
// clean up the resource
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, preventDestroy: false, zoneDistributionMode: "MULTI_ZONE"}),
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE"}),
},
},
})
Expand Down Expand Up @@ -212,25 +209,57 @@ func TestAccRedisCluster_updateRedisConfigs(t *testing.T) {
})
}

// Validate that deletion protection enabled/disabled cluster is created updated
func TestAccRedisCluster_createUpdateDeletionProtection(t *testing.T) {
t.Parallel()

name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t))

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
CheckDestroy: testAccCheckRedisClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
// create cluster with deletion protection set to false
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"psc_configs"},
},
{
// update deletion protection to true
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: true, zoneDistributionMode: "MULTI_ZONE"}),
},
{
ResourceName: "google_redis_cluster.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"psc_configs"},
},
{
// update deletion protection to false and delete the cluster
Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE"}),
},
},
})
}

type ClusterParams struct {
name string
replicaCount int
shardCount int
preventDestroy bool
nodeType string
redisConfigs map[string]string
zoneDistributionMode string
zone string
name string
replicaCount int
shardCount int
deletionProtectionEnabled bool
nodeType string
redisConfigs map[string]string
zoneDistributionMode string
zone string
}

func createOrUpdateRedisCluster(params *ClusterParams) string {
lifecycleBlock := ""
if params.preventDestroy {
lifecycleBlock = `
lifecycle {
prevent_destroy = true
}`
}
var strBuilder strings.Builder
for key, value := range params.redisConfigs {
strBuilder.WriteString(fmt.Sprintf("%s = \"%s\"\n", key, value))
Expand All @@ -253,6 +282,7 @@ resource "google_redis_cluster" "test" {
replica_count = %d
shard_count = %d
node_type = "%s"
deletion_protection_enabled = %v
region = "us-central1"
psc_configs {
network = google_compute_network.producer_net.id
Expand All @@ -262,9 +292,8 @@ resource "google_redis_cluster" "test" {
}
%s
depends_on = [
google_network_connectivity_service_connection_policy.default
]
%s
google_network_connectivity_service_connection_policy.default
]
}

resource "google_network_connectivity_service_connection_policy" "default" {
Expand Down Expand Up @@ -292,5 +321,5 @@ resource "google_compute_network" "producer_net" {
name = "%s"
auto_create_subnetworks = false
}
`, params.name, params.replicaCount, params.shardCount, params.nodeType, strBuilder.String(), zoneDistributionConfigBlock, lifecycleBlock, params.name, params.name, params.name)
`, params.name, params.replicaCount, params.shardCount, params.nodeType, params.deletionProtectionEnabled, strBuilder.String(), zoneDistributionConfigBlock, params.name, params.name, params.name)
}
Loading