From 0e0e2387bd3f09de88797c7faed09fbf0fd6ed5b Mon Sep 17 00:00:00 2001 From: Calvin Liu Date: Tue, 23 Apr 2024 09:34:01 -0700 Subject: [PATCH] Add redis_configs parameters to Redis Cluster --- mmv1/products/redis/Cluster.yaml | 6 + .../examples/redis_cluster_ha.tf.erb | 3 + .../redis/resource_redis_cluster_test.go.erb | 217 ++++++++++++------ 3 files changed, 152 insertions(+), 74 deletions(-) diff --git a/mmv1/products/redis/Cluster.yaml b/mmv1/products/redis/Cluster.yaml index d815eb7b9a0a..e4fdc0649c05 100644 --- a/mmv1/products/redis/Cluster.yaml +++ b/mmv1/products/redis/Cluster.yaml @@ -231,3 +231,9 @@ properties: description: | Required. Number of shards for the Redis cluster. required: true + - !ruby/object:Api::Type::KeyValuePairs + name: 'redisConfigs' + description: | + Configure Redis Cluster behavior using a subset of native Redis configuration parameters. + Please check Memorystore documentation for the list of supported parameters: + https://cloud.google.com/memorystore/docs/cluster/supported-instance-configurations diff --git a/mmv1/templates/terraform/examples/redis_cluster_ha.tf.erb b/mmv1/templates/terraform/examples/redis_cluster_ha.tf.erb index 24273a469e55..6f97550fe142 100644 --- a/mmv1/templates/terraform/examples/redis_cluster_ha.tf.erb +++ b/mmv1/templates/terraform/examples/redis_cluster_ha.tf.erb @@ -9,6 +9,9 @@ resource "google_redis_cluster" "<%= ctx[:primary_resource_id] %>" { node_type = "REDIS_SHARED_CORE_NANO" transit_encryption_mode = "TRANSIT_ENCRYPTION_MODE_DISABLED" authorization_mode = "AUTH_MODE_DISABLED" + redis_configs = { + maxmemory-policy = "volatile-ttl" + } depends_on = [ google_network_connectivity_service_connection_policy.default ] diff --git a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.erb b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.erb index 928eb49c857c..4397f6e5a5a7 100644 --- a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.erb @@ -4,6 +4,7 @@ package redis_test import ( "fmt" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -11,31 +12,31 @@ import ( ) func TestAccRedisCluster_createClusterWithNodeType(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 replica count 1 - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 1, /* shardCount = */ 3, true, /*nodeType = */ "REDIS_STANDARD_SMALL"), - }, - { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"psc_configs"}, - }, - { - // clean up the resource - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 0, /* shardCount = */ 3, false, /*nodeType = */ "REDIS_STANDARD_SMALL"), - }, - }, - }) + 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 replica count 1 + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true, nodeType: "REDIS_STANDARD_SMALL"}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // clean up the resource + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false, nodeType: "REDIS_STANDARD_SMALL"}), + }, + }, + }) } // Validate that replica count is updated for the cluster @@ -51,41 +52,41 @@ func TestAccRedisCluster_updateReplicaCount(t *testing.T) { Steps: []resource.TestStep{ { // create cluster with replica count 1 - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 1, /* shardCount = */ 3, true, /* nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true}), }, { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"psc_configs"}, }, { // update replica count to 2 - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 2, /* shardCount = */ 3, true, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 2, shardCount: 3, preventDestroy: true}), }, { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"psc_configs"}, }, { // clean up the resource - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 2, /* shardCount = */ 3, false, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: false}), }, { // update replica count to 0 - Config: createOrUpdateRedisCluster(name, /* replicaCount = */ 0, /* shardCount = */ 3, true, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: true}), }, { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"psc_configs"}, }, { // clean up the resource - Config: createOrUpdateRedisCluster(name /* replicaCount = */, 0 /* shardCount = */, 3, false, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, preventDestroy: false}), }, }, }) @@ -104,83 +105,151 @@ func TestAccRedisCluster_updateShardCount(t *testing.T) { Steps: []resource.TestStep{ { // create cluster with shard count 3 - Config: createOrUpdateRedisCluster(name /* replicaCount = */, 1 /* shardCount = */, 3, true, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 3, preventDestroy: true}), }, { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"psc_configs"}, - }, { // update shard count to 5 - Config: createOrUpdateRedisCluster(name /* replicaCount = */, 1 /* shardCount = */, 5, true, /*nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, preventDestroy: true}), }, { - ResourceName: "google_redis_cluster.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"psc_configs"}, }, { // clean up the resource - Config: createOrUpdateRedisCluster(name /* replicaCount = */, 1 /* shardCount = */, 5, false, /* nodeType = */ ""), + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 1, shardCount: 5, preventDestroy: false}), }, }, }) } -func createOrUpdateRedisCluster(name string, replicaCount int, shardCount int, preventDestroy bool, nodeType string) string { +// Validate that redisConfigs is updated for the cluster +func TestAccRedisCluster_updateRedisConfigs(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 + Config: createOrUpdateRedisCluster(&ClusterParams{ + name: name, + shardCount: 3, + redisConfigs: map[string]string{ + "maxmemory-policy": "volatile-ttl", + }}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // add a new redis config key-value pair and update existing redis config + Config: createOrUpdateRedisCluster(&ClusterParams{ + name: name, + shardCount: 3, + redisConfigs: map[string]string{ + "maxmemory-policy": "allkeys-lru", + "maxmemory-clients": "90%", + }}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // remove all redis configs + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, shardCount: 3}), + }, + + }, + }) +} + +type ClusterParams struct { + name string + replicaCount int + shardCount int + preventDestroy bool + nodeType string + redisConfigs map[string]string +} + +func createOrUpdateRedisCluster(params *ClusterParams) string { lifecycleBlock := "" - if preventDestroy { + 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)) + } + return fmt.Sprintf(` resource "google_redis_cluster" "test" { - provider = google-beta - name = "%s" + provider = google-beta + name = "%s" replica_count = %d shard_count = %d node_type = "%s" - region = "us-central1" + region = "us-central1" psc_configs { network = google_compute_network.producer_net.id } + redis_configs = { + %s + } depends_on = [ - google_network_connectivity_service_connection_policy.default - ] + google_network_connectivity_service_connection_policy.default + ] %s } resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta - name = "%s" - location = "us-central1" - service_class = "gcp-memorystore-redis" - description = "my basic service connection policy" - network = google_compute_network.producer_net.id - psc_config { - subnetworks = [google_compute_subnetwork.producer_subnet.id] - } + provider = google-beta + name = "%s" + location = "us-central1" + service_class = "gcp-memorystore-redis" + description = "my basic service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + } } resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta - name = "%s" - ip_cidr_range = "10.0.0.248/29" - region = "us-central1" - network = google_compute_network.producer_net.id + provider = google-beta + name = "%s" + ip_cidr_range = "10.0.0.248/29" + region = "us-central1" + network = google_compute_network.producer_net.id } resource "google_compute_network" "producer_net" { - provider = google-beta - name = "%s" - auto_create_subnetworks = false + provider = google-beta + name = "%s" + auto_create_subnetworks = false } -`, name, replicaCount, shardCount, nodeType, lifecycleBlock, name, name, name) +`, params.name, params.replicaCount, params.shardCount, params.nodeType, strBuilder.String(), lifecycleBlock, params.name, params.name, params.name) } + <% end -%>