From 11ac8b412e0117d4335ea621a663e69f40679e96 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Mon, 20 Oct 2025 15:07:04 +0100 Subject: [PATCH 01/22] test: fixing failing tests --- provider/pro/testdata/pro_database_data_source.tf | 2 -- provider/resource_rediscloud_pro_database_qpf_test.go | 4 ++-- provider/resource_rediscloud_pro_database_redis_8_test.go | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/provider/pro/testdata/pro_database_data_source.tf b/provider/pro/testdata/pro_database_data_source.tf index d462e1ec..51499b20 100644 --- a/provider/pro/testdata/pro_database_data_source.tf +++ b/provider/pro/testdata/pro_database_data_source.tf @@ -34,7 +34,6 @@ resource "rediscloud_subscription" "example" { support_oss_cluster_api=true throughput_measurement_by = "operations-per-second" throughput_measurement_value = 1000 - query_performance_factor = "2x" modules = ["RediSearch"] } } @@ -50,7 +49,6 @@ resource "rediscloud_subscription_database" "example" { support_oss_cluster_api = true replication = false enable_default_user = true - query_performance_factor = "2x" redis_version = "7.4" modules = [ { diff --git a/provider/resource_rediscloud_pro_database_qpf_test.go b/provider/resource_rediscloud_pro_database_qpf_test.go index 94837b3c..4faeb814 100644 --- a/provider/resource_rediscloud_pro_database_qpf_test.go +++ b/provider/resource_rediscloud_pro_database_qpf_test.go @@ -150,7 +150,7 @@ func TestAccResourceRedisCloudProDatabase_qpf_missingModule(t *testing.T) { config := formatDatabaseConfig(name, testCloudAccountName, password, "4x", "") - testErrorCase(t, config, regexp.MustCompile("query_performance_factor\" requires the \"modules\" key to be explicitly defined in HCL")) + testErrorCase(t, config, regexp.MustCompile("DATABASE_QUERY_PERFORMANCE_FACTOR_SEARCH_IS_REQUIRED.*RediSearch.*required")) } func TestAccResourceRedisCloudProDatabase_qpf_missingRediSearchModule(t *testing.T) { @@ -160,7 +160,7 @@ func TestAccResourceRedisCloudProDatabase_qpf_missingRediSearchModule(t *testing config := formatDatabaseConfig(name, testCloudAccountName, password, "4x", `modules = [{ name = "RediBloom" }]`) - testErrorCase(t, config, regexp.MustCompile("query_performance_factor\" requires the \"modules\" list to contain \"RediSearch")) + testErrorCase(t, config, regexp.MustCompile("DATABASE_QUERY_PERFORMANCE_FACTOR_SEARCH_IS_REQUIRED.*RediSearch.*required")) } func TestAccResourceRedisCloudProDatabase_qpf_invalidQueryPerformanceFactors(t *testing.T) { diff --git a/provider/resource_rediscloud_pro_database_redis_8_test.go b/provider/resource_rediscloud_pro_database_redis_8_test.go index 6084f4f4..0de7ec6d 100644 --- a/provider/resource_rediscloud_pro_database_redis_8_test.go +++ b/provider/resource_rediscloud_pro_database_redis_8_test.go @@ -121,7 +121,7 @@ func TestAccResourceRedisCloudProDatabase_Redis8_Upgrade(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "name", "example"), resource.TestCheckResourceAttr(resourceName, "protocol", "redis"), - resource.TestCheckResourceAttr(resourceName, "dataset_size_in_gb", "3"), + resource.TestCheckResourceAttr(resourceName, "dataset_size_in_gb", "1"), resource.TestCheckResourceAttr(resourceName, "replication", "false"), resource.TestCheckResourceAttr(resourceName, "support_oss_cluster_api", "false"), resource.TestCheckResourceAttr(resourceName, "resp_version", "resp3"), From b45d496a708f163e977b22342db785f94004b6d5 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Mon, 20 Oct 2025 16:27:48 +0100 Subject: [PATCH 02/22] test: expectations are standard if the subscription and database levels are the same --- provider/datasource_rediscloud_pro_database_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/datasource_rediscloud_pro_database_test.go b/provider/datasource_rediscloud_pro_database_test.go index 50f3f345..e0e67e04 100644 --- a/provider/datasource_rediscloud_pro_database_test.go +++ b/provider/datasource_rediscloud_pro_database_test.go @@ -47,7 +47,7 @@ func TestAccDataSourceRedisCloudProDatabase_basic(t *testing.T) { resource.TestCheckResourceAttrSet(dataSourceById, "public_endpoint"), resource.TestCheckResourceAttrSet(dataSourceById, "private_endpoint"), resource.TestCheckResourceAttr(dataSourceById, "enable_default_user", "true"), - resource.TestCheckResourceAttr(dataSourceById, "query_performance_factor", "2x"), + resource.TestCheckResourceAttr(dataSourceById, "query_performance_factor", "Standard"), resource.TestCheckResourceAttr(dataSourceByName, "name", "tf-database"), resource.TestCheckResourceAttr(dataSourceByName, "protocol", "redis"), @@ -64,7 +64,7 @@ func TestAccDataSourceRedisCloudProDatabase_basic(t *testing.T) { resource.TestCheckResourceAttrSet(dataSourceByName, "public_endpoint"), resource.TestCheckResourceAttrSet(dataSourceByName, "private_endpoint"), resource.TestCheckResourceAttr(dataSourceByName, "enable_default_user", "true"), - resource.TestCheckResourceAttr(dataSourceByName, "query_performance_factor", "2x"), + resource.TestCheckResourceAttr(dataSourceByName, "query_performance_factor", "Standard"), resource.TestCheckResourceAttr(dataSourceByName, "redis_version", "7.4"), ), }, From 68b55f7b7cb8017edeea8e66463b132d4f0554c7 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Mon, 20 Oct 2025 16:58:17 +0100 Subject: [PATCH 03/22] test: changing query performance factor to be in there but only in db terraform --- ...datasource_rediscloud_pro_database_test.go | 4 +- .../pro/testdata/pro_database_data_source.tf | 43 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/provider/datasource_rediscloud_pro_database_test.go b/provider/datasource_rediscloud_pro_database_test.go index e0e67e04..50f3f345 100644 --- a/provider/datasource_rediscloud_pro_database_test.go +++ b/provider/datasource_rediscloud_pro_database_test.go @@ -47,7 +47,7 @@ func TestAccDataSourceRedisCloudProDatabase_basic(t *testing.T) { resource.TestCheckResourceAttrSet(dataSourceById, "public_endpoint"), resource.TestCheckResourceAttrSet(dataSourceById, "private_endpoint"), resource.TestCheckResourceAttr(dataSourceById, "enable_default_user", "true"), - resource.TestCheckResourceAttr(dataSourceById, "query_performance_factor", "Standard"), + resource.TestCheckResourceAttr(dataSourceById, "query_performance_factor", "2x"), resource.TestCheckResourceAttr(dataSourceByName, "name", "tf-database"), resource.TestCheckResourceAttr(dataSourceByName, "protocol", "redis"), @@ -64,7 +64,7 @@ func TestAccDataSourceRedisCloudProDatabase_basic(t *testing.T) { resource.TestCheckResourceAttrSet(dataSourceByName, "public_endpoint"), resource.TestCheckResourceAttrSet(dataSourceByName, "private_endpoint"), resource.TestCheckResourceAttr(dataSourceByName, "enable_default_user", "true"), - resource.TestCheckResourceAttr(dataSourceByName, "query_performance_factor", "Standard"), + resource.TestCheckResourceAttr(dataSourceByName, "query_performance_factor", "2x"), resource.TestCheckResourceAttr(dataSourceByName, "redis_version", "7.4"), ), }, diff --git a/provider/pro/testdata/pro_database_data_source.tf b/provider/pro/testdata/pro_database_data_source.tf index 51499b20..73939ae6 100644 --- a/provider/pro/testdata/pro_database_data_source.tf +++ b/provider/pro/testdata/pro_database_data_source.tf @@ -1,38 +1,38 @@ locals { - rediscloud_cloud_account = "%s" + rediscloud_cloud_account = "%s" rediscloud_subscription_name = "%s" - rediscloud_password = "%s" + rediscloud_password = "%s" } data "rediscloud_payment_method" "card" { - card_type = "Visa" + card_type = "Visa" last_four_numbers = "5556" } data "rediscloud_cloud_account" "account" { exclude_internal_account = true - provider_type = "AWS" - name = local.rediscloud_cloud_account + provider_type = "AWS" + name = local.rediscloud_cloud_account } resource "rediscloud_subscription" "example" { - name = local.rediscloud_subscription_name + name = local.rediscloud_subscription_name payment_method_id = data.rediscloud_payment_method.card.id - memory_storage = "ram" + memory_storage = "ram" cloud_provider { - provider = data.rediscloud_cloud_account.account.provider_type + provider = data.rediscloud_cloud_account.account.provider_type cloud_account_id = data.rediscloud_cloud_account.account.id region { - region = "eu-west-1" + region = "eu-west-1" networking_deployment_cidr = "10.0.0.0/24" preferred_availability_zones = ["eu-west-1a"] } } creation_plan { - memory_limit_in_gb = 1 - quantity = 1 - replication=false - support_oss_cluster_api=true - throughput_measurement_by = "operations-per-second" + memory_limit_in_gb = 1 + quantity = 1 + replication = false + support_oss_cluster_api = true + throughput_measurement_by = "operations-per-second" throughput_measurement_value = 1000 modules = ["RediSearch"] } @@ -46,23 +46,24 @@ resource "rediscloud_subscription_database" "example" { throughput_measurement_by = "operations-per-second" throughput_measurement_value = 1000 password = local.rediscloud_password - support_oss_cluster_api = true - replication = false - enable_default_user = true - redis_version = "7.4" + support_oss_cluster_api = true + replication = false + enable_default_user = true + query_performance_factor = "2x" + redis_version = "7.4" modules = [ { - name: "RediSearch" + name : "RediSearch" } ] } data "rediscloud_database" "example-by-id" { subscription_id = rediscloud_subscription.example.id - db_id = rediscloud_subscription_database.example.db_id + db_id = rediscloud_subscription_database.example.db_id } data "rediscloud_database" "example-by-name" { subscription_id = rediscloud_subscription.example.id - name = rediscloud_subscription_database.example.name + name = rediscloud_subscription_database.example.name } From 8eebe69e73552d0148423fceb9577f1f43d52d1f Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Tue, 21 Oct 2025 15:02:25 +0100 Subject: [PATCH 04/22] fix: change error for redis 8 modules to warning --- provider/pro/resource_rediscloud_pro_database.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index dd670907..a1d8e98e 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -1048,7 +1048,8 @@ func validateModulesForRedis8() schema.CustomizeDiffFunc { if strings.HasPrefix(version, "8.") { moduleSet := modules.(*schema.Set) if moduleSet.Len() > 0 { - return fmt.Errorf(`"modules" cannot be explicitly set for Redis version %s as modules are bundled by default. Remove the "modules" field from your configuration`, version) + log.Printf("[WARN] Modules are bundled by default in Redis %s. You should remove the modules block as it is deprecated for this version.", version) + return nil } } } From bad7b581dc7a2acc170ed0f6bf41a7a798fd86bf Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 12:44:31 +0100 Subject: [PATCH 05/22] chore: adding debug to essentials db creation --- go.mod | 2 +- .../pro/resource_rediscloud_pro_database.go | 23 ++++++--- ...pro_database_auto_minor_version_upgrade.tf | 50 +++++++++++++++++++ .../rediscloud_active_active_database_test.go | 33 ++++++++++++ ...ource_rediscloud_active_active_database.go | 16 +++++- ...resource_rediscloud_essentials_database.go | 9 ++++ .../resource_rediscloud_pro_database_test.go | 32 ++++++++++++ ...ive_database_auto_minor_version_upgrade.tf | 44 ++++++++++++++++ 8 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 provider/pro/testdata/pro_database_auto_minor_version_upgrade.tf create mode 100644 provider/testdata/active_active_database_auto_minor_version_upgrade.tf diff --git a/go.mod b/go.mod index b93c5f4a..7a8baa37 100644 --- a/go.mod +++ b/go.mod @@ -71,4 +71,4 @@ require ( ) // for local development, uncomment this -//replace github.com/RedisLabs/rediscloud-go-api => ../rediscloud-go-api +replace github.com/RedisLabs/rediscloud-go-api => ../rediscloud-go-api diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index a1d8e98e..6d416526 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -297,6 +297,12 @@ func ResourceRedisCloudProDatabase() *schema.Resource { Optional: true, Default: true, }, + "auto_minor_version_upgrade": { + Description: "When 'true', enables auto minor version upgrades for this database. Default: 'true'", + Type: schema.TypeBool, + Optional: true, + Default: true, + }, "port": { Description: "TCP port on which the database is available", Type: schema.TypeInt, @@ -436,6 +442,10 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource createDatabase.RespVersion = s }) + utils.SetBool(d, "auto_minor_version_upgrade", func(b *bool) { + createDatabase.AutoMinorVersionUpgrade = b + }) + // Confirm sub is ready to accept a db request if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { return diag.FromErr(err) @@ -731,12 +741,13 @@ func resourceRedisCloudProDatabaseUpdate(ctx context.Context, d *schema.Resource Value: utils.GetInt(d, "throughput_measurement_value"), }, - DataPersistence: utils.GetString(d, "data_persistence"), - DataEvictionPolicy: utils.GetString(d, "data_eviction"), - SourceIP: utils.SetToStringSlice(d.Get("source_ips").(*schema.Set)), - Alerts: &alerts, - RemoteBackup: BuildBackupPlan(d.Get("remote_backup").([]interface{}), d.Get("periodic_backup_path")), - EnableDefaultUser: utils.GetBool(d, "enable_default_user"), + DataPersistence: utils.GetString(d, "data_persistence"), + DataEvictionPolicy: utils.GetString(d, "data_eviction"), + SourceIP: utils.SetToStringSlice(d.Get("source_ips").(*schema.Set)), + Alerts: &alerts, + RemoteBackup: BuildBackupPlan(d.Get("remote_backup").([]interface{}), d.Get("periodic_backup_path")), + EnableDefaultUser: utils.GetBool(d, "enable_default_user"), + AutoMinorVersionUpgrade: utils.GetBool(d, "auto_minor_version_upgrade"), } // One of the following fields must be set, validation is handled in the schema (ExactlyOneOf) diff --git a/provider/pro/testdata/pro_database_auto_minor_version_upgrade.tf b/provider/pro/testdata/pro_database_auto_minor_version_upgrade.tf new file mode 100644 index 00000000..5ae03dd8 --- /dev/null +++ b/provider/pro/testdata/pro_database_auto_minor_version_upgrade.tf @@ -0,0 +1,50 @@ +locals { + rediscloud_cloud_account = "%s" + rediscloud_subscription_name = "%s" + auto_minor_version_upgrade = %s +} + +data "rediscloud_payment_method" "card" { + card_type = "Visa" + last_four_numbers = "5556" +} + +data "rediscloud_cloud_account" "account" { + exclude_internal_account = true + provider_type = "AWS" + name = local.rediscloud_cloud_account +} + +resource "rediscloud_subscription" "example" { + name = local.rediscloud_subscription_name + payment_method_id = data.rediscloud_payment_method.card.id + memory_storage = "ram" + cloud_provider { + provider = data.rediscloud_cloud_account.account.provider_type + cloud_account_id = data.rediscloud_cloud_account.account.id + region { + region = "eu-west-1" + networking_deployment_cidr = "10.0.0.0/24" + preferred_availability_zones = ["eu-west-1a"] + } + } + + creation_plan { + memory_limit_in_gb = 1 + quantity = 1 + replication = false + throughput_measurement_by = "operations-per-second" + throughput_measurement_value = 1000 + } +} + +resource "rediscloud_subscription_database" "example" { + subscription_id = rediscloud_subscription.example.id + name = "auto-minor-version-upgrade-test" + protocol = "redis" + memory_limit_in_gb = 1 + data_persistence = "none" + throughput_measurement_by = "operations-per-second" + throughput_measurement_value = 1000 + auto_minor_version_upgrade = local.auto_minor_version_upgrade +} diff --git a/provider/rediscloud_active_active_database_test.go b/provider/rediscloud_active_active_database_test.go index 34e355b1..bb2e89ee 100644 --- a/provider/rediscloud_active_active_database_test.go +++ b/provider/rediscloud_active_active_database_test.go @@ -515,3 +515,36 @@ resource "rediscloud_active_active_subscription_database" "example" { } } ` + +func TestAccResourceRedisCloudActiveActiveDatabase_autoMinorVersionUpgrade(t *testing.T) { + + utils.AccRequiresEnvVar(t, "EXECUTE_TESTS") + + subscriptionName := acctest.RandomWithPrefix(testResourcePrefix) + "-subscription" + name := acctest.RandomWithPrefix(testResourcePrefix) + "-database" + const resourceName = "rediscloud_active_active_subscription_database.example" + testCloudAccountName := os.Getenv("AWS_TEST_CLOUD_ACCOUNT_NAME") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAwsPreExistingCloudAccountPreCheck(t) }, + ProviderFactories: providerFactories, + CheckDestroy: testAccCheckActiveActiveSubscriptionDestroy, + Steps: []resource.TestStep{ + // Test database creation with auto_minor_version_upgrade set to false + { + Config: fmt.Sprintf(utils.GetTestConfig(t, "./testdata/active_active_database_auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "false"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", "auto-minor-version-upgrade-test"), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + ), + }, + // Test database update with auto_minor_version_upgrade set to true + { + Config: fmt.Sprintf(utils.GetTestConfig(t, "./testdata/active_active_database_auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "true"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + }, + }) +} diff --git a/provider/resource_rediscloud_active_active_database.go b/provider/resource_rediscloud_active_active_database.go index ebb44b2b..355d9b78 100644 --- a/provider/resource_rediscloud_active_active_database.go +++ b/provider/resource_rediscloud_active_active_database.go @@ -206,7 +206,13 @@ func resourceRedisCloudActiveActiveDatabase() *schema.Resource { Type: schema.TypeBool, Optional: true, }, - "override_region": { + "auto_minor_version_upgrade": { + Description: "When 'true', enables auto minor version upgrades for this database. Default: 'true'", + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "override_region": { Description: "Region-specific configuration parameters to override the global configuration", Type: schema.TypeSet, Optional: true, @@ -447,6 +453,10 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema createDatabase.RedisVersion = s }) + utils.SetBool(d, "auto_minor_version_upgrade", func(b *bool) { + createDatabase.AutoMinorVersionUpgrade = b + }) + // Confirm Subscription Active status before creating database err = utils.WaitForSubscriptionToBeActive(ctx, subId, api) if err != nil { @@ -799,6 +809,10 @@ func resourceRedisCloudActiveActiveDatabaseUpdate(ctx context.Context, d *schema update.GlobalEnableDefaultUser = redis.Bool(v.(bool)) } + if v, ok := d.GetOk("auto_minor_version_upgrade"); ok { + update.AutoMinorVersionUpgrade = redis.Bool(v.(bool)) + } + if v, ok := d.GetOk("support_oss_cluster_api"); ok { update.SupportOSSClusterAPI = redis.Bool(v.(bool)) } diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 65d855ab..dbb2e471 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -306,6 +306,7 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R api := meta.(*client.ApiClient) subId := d.Get("subscription_id").(int) + log.Printf("[DEBUG] Creating essentials database in subscription %d", subId) utils.SubscriptionMutex.Lock(subId) @@ -316,6 +317,11 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R Replication: redis.Bool(d.Get("replication").(bool)), PeriodicBackupPath: redis.String(d.Get("periodic_backup_path").(string)), } + log.Printf("[DEBUG] Essentials database create request - Name: %s, DataPersistence: %s, DataEviction: %s, Replication: %v", + redis.StringValue(createDatabaseRequest.Name), + redis.StringValue(createDatabaseRequest.DataPersistence), + redis.StringValue(createDatabaseRequest.DataEvictionPolicy), + redis.BoolValue(createDatabaseRequest.Replication)) protocol := d.Get("protocol").(string) if protocol != "" { @@ -411,11 +417,14 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R createDatabaseRequest.EnableTls = redis.Bool(d.Get("enable_tls").(bool)) } + log.Printf("[DEBUG] Calling FixedDatabases.Create API for subscription %d with database name: %s", subId, redis.StringValue(createDatabaseRequest.Name)) databaseId, err := api.Client.FixedDatabases.Create(ctx, subId, createDatabaseRequest) if err != nil { + log.Printf("[ERROR] FixedDatabases.Create failed for subscription %d: %v", subId, err) utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } + log.Printf("[DEBUG] FixedDatabases.Create succeeded for subscription %d, database ID: %d", subId, databaseId) d.SetId(utils.BuildResourceId(subId, databaseId)) diff --git a/provider/resource_rediscloud_pro_database_test.go b/provider/resource_rediscloud_pro_database_test.go index f0b684dc..aef20b2f 100644 --- a/provider/resource_rediscloud_pro_database_test.go +++ b/provider/resource_rediscloud_pro_database_test.go @@ -274,3 +274,35 @@ func TestAccResourceRedisCloudProDatabase_respversion(t *testing.T) { }, }) } + +func TestAccResourceRedisCloudProDatabase_autoMinorVersionUpgrade(t *testing.T) { + + utils.AccRequiresEnvVar(t, "EXECUTE_TESTS") + + name := acctest.RandomWithPrefix(testResourcePrefix) + const resourceName = "rediscloud_subscription_database.example" + testCloudAccountName := os.Getenv("AWS_TEST_CLOUD_ACCOUNT_NAME") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccAwsPreExistingCloudAccountPreCheck(t) }, + ProviderFactories: providerFactories, + CheckDestroy: testAccCheckProSubscriptionDestroy, + Steps: []resource.TestStep{ + // Test database creation with auto_minor_version_upgrade set to false + { + Config: fmt.Sprintf(utils.GetTestConfig(t, "./pro/testdata/pro_database_auto_minor_version_upgrade.tf"), testCloudAccountName, name, "false"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", "auto-minor-version-upgrade-test"), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + ), + }, + // Test database update with auto_minor_version_upgrade set to true + { + Config: fmt.Sprintf(utils.GetTestConfig(t, "./pro/testdata/pro_database_auto_minor_version_upgrade.tf"), testCloudAccountName, name, "true"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + }, + }) +} diff --git a/provider/testdata/active_active_database_auto_minor_version_upgrade.tf b/provider/testdata/active_active_database_auto_minor_version_upgrade.tf new file mode 100644 index 00000000..1904d6bc --- /dev/null +++ b/provider/testdata/active_active_database_auto_minor_version_upgrade.tf @@ -0,0 +1,44 @@ +locals { + rediscloud_cloud_account = "%s" + rediscloud_subscription_name = "%s" +} + +data "rediscloud_payment_method" "card" { + card_type = "Visa" + last_four_numbers = "5556" +} + +data "rediscloud_cloud_account" "account" { + exclude_internal_account = true + provider_type = "AWS" + name = local.rediscloud_cloud_account +} + +resource "rediscloud_active_active_subscription" "example" { + name = local.rediscloud_subscription_name + payment_method_id = data.rediscloud_payment_method.card.id + storage_encryption = true + + region { + region = "eu-west-1" + networking_deployment_cidr = "10.0.0.0/24" + preferred_availability_zones = ["eu-west-1a"] + } + + region { + region = "us-east-1" + networking_deployment_cidr = "10.1.0.0/24" + preferred_availability_zones = ["us-east-1a"] + } +} + +resource "rediscloud_active_active_subscription_database" "example" { + subscription_id = rediscloud_active_active_subscription.example.id + name = "auto-minor-version-upgrade-test" + protocol = "redis" + dataset_size_in_gb = 1 + data_eviction = "allkeys-random" + throughput_measurement_by = "operations-per-second" + throughput_measurement_value = 1000 + auto_minor_version_upgrade = %s +} From a14286cb794ebb70e5698c5e285de11bfe417cef Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 13:08:46 +0100 Subject: [PATCH 06/22] chore: go mod dep bump --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 7a8baa37..17be2d60 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.0 toolchain go1.24.1 require ( - github.com/RedisLabs/rediscloud-go-api v0.38.0 + github.com/RedisLabs/rediscloud-go-api v0.39.0 github.com/bflad/tfproviderlint v0.31.0 github.com/hashicorp/go-cty v1.5.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1 @@ -71,4 +71,4 @@ require ( ) // for local development, uncomment this -replace github.com/RedisLabs/rediscloud-go-api => ../rediscloud-go-api +//replace github.com/RedisLabs/rediscloud-go-api => ../rediscloud-go-api diff --git a/go.sum b/go.sum index 92da6608..6aae7c20 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/RedisLabs/rediscloud-go-api v0.38.0 h1:lLOS0E8tQhUzuUfb/H+QWtDaZrC9xNnTvAPBygH4WS8= -github.com/RedisLabs/rediscloud-go-api v0.38.0/go.mod h1:Hkh3i/EsHnyfgV0ijednbofz/EmZC3sFnSNNruF3G6I= +github.com/RedisLabs/rediscloud-go-api v0.39.0 h1:VNI7VyP9V41Z8FP558v60WCJFBB57AGuQQq3QY4t2VU= +github.com/RedisLabs/rediscloud-go-api v0.39.0/go.mod h1:Hkh3i/EsHnyfgV0ijednbofz/EmZC3sFnSNNruF3G6I= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= From 21addda0a8e4baeef071a23c48a2436f583f77be Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 13:26:08 +0100 Subject: [PATCH 07/22] fix: module would not warn on redis 9. Extracted out method and unit tested it --- .../pro/resource_rediscloud_pro_database.go | 26 +++++-- ...rediscloud_pro_database_validation_test.go | 67 +++++++++++++++++++ 2 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 provider/pro/resource_rediscloud_pro_database_validation_test.go diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 6d416526..9df5641e 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -1048,6 +1048,21 @@ func containsDBModule(modules []map[string]interface{}, moduleName string) bool return false } +// shouldWarnRedis8Modules checks if a warning should be issued for modules in Redis 8.0 or higher +func shouldWarnRedis8Modules(version string, hasModules bool) bool { + if !hasModules { + return false + } + // Extract major version (first character before the dot) + if len(version) > 0 { + majorVersionStr := strings.Split(version, ".")[0] + if majorVersion, err := strconv.Atoi(majorVersionStr); err == nil { + return majorVersion >= 8 + } + } + return false +} + func validateModulesForRedis8() schema.CustomizeDiffFunc { return func(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error { redisVersion, versionExists := diff.GetOk("redis_version") @@ -1055,13 +1070,10 @@ func validateModulesForRedis8() schema.CustomizeDiffFunc { if versionExists && modulesExists { version := redisVersion.(string) - // Check if version is >= 8.0 - if strings.HasPrefix(version, "8.") { - moduleSet := modules.(*schema.Set) - if moduleSet.Len() > 0 { - log.Printf("[WARN] Modules are bundled by default in Redis %s. You should remove the modules block as it is deprecated for this version.", version) - return nil - } + moduleSet := modules.(*schema.Set) + + if shouldWarnRedis8Modules(version, moduleSet.Len() > 0) { + log.Printf("[WARN] Modules are bundled by default in Redis %s. You should remove the modules block as it is deprecated for this version.", version) } } return nil diff --git a/provider/pro/resource_rediscloud_pro_database_validation_test.go b/provider/pro/resource_rediscloud_pro_database_validation_test.go new file mode 100644 index 00000000..a1a9c6a4 --- /dev/null +++ b/provider/pro/resource_rediscloud_pro_database_validation_test.go @@ -0,0 +1,67 @@ +package pro + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// TestUnitShouldWarnRedis8Modules_Redis8WithModules tests that warning is triggered for Redis 8.0 with modules +func TestUnitShouldWarnRedis8Modules_Redis8WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("8.0", true) + assert.True(t, result, "should warn for Redis 8.0 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis80WithModules tests that warning is triggered for Redis 8.0.0 with modules +func TestUnitShouldWarnRedis8Modules_Redis80WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("8.0.0", true) + assert.True(t, result, "should warn for Redis 8.0.0 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis81WithModules tests that warning is triggered for Redis 8.1+ with modules +func TestUnitShouldWarnRedis8Modules_Redis81WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("8.1.0", true) + assert.True(t, result, "should warn for Redis 8.1.0 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis89WithModules tests that warning is triggered for Redis 8.9+ with modules +func TestUnitShouldWarnRedis8Modules_Redis89WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("8.9.9", true) + assert.True(t, result, "should warn for Redis 8.9.9 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis7WithModules tests that no warning for Redis 7.x with modules +func TestUnitShouldWarnRedis8Modules_Redis7WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("7.4", true) + assert.False(t, result, "should not warn for Redis 7.4 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis6WithModules tests that no warning for Redis 6.x with modules +func TestUnitShouldWarnRedis8Modules_Redis6WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("6.2", true) + assert.False(t, result, "should not warn for Redis 6.2 with modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis8NoModules tests that no warning for Redis 8.0 without modules +func TestUnitShouldWarnRedis8Modules_Redis8NoModules(t *testing.T) { + result := shouldWarnRedis8Modules("8.0", false) + assert.False(t, result, "should not warn for Redis 8.0 without modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis7NoModules tests that no warning for Redis 7.x without modules +func TestUnitShouldWarnRedis8Modules_Redis7NoModules(t *testing.T) { + result := shouldWarnRedis8Modules("7.4", false) + assert.False(t, result, "should not warn for Redis 7.4 without modules") +} + +// TestUnitShouldWarnRedis8Modules_Redis9WithModules tests that warning is triggered for Redis 9.x with modules (future-proofing) +func TestUnitShouldWarnRedis8Modules_Redis9WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("9.0", true) + assert.True(t, result, "should warn for Redis 9.0 with modules (modules bundled in 8.0+)") +} + +// TestUnitShouldWarnRedis8Modules_Redis10WithModules tests that warning is triggered for Redis 10.x with modules +func TestUnitShouldWarnRedis8Modules_Redis10WithModules(t *testing.T) { + result := shouldWarnRedis8Modules("10.0.0", true) + assert.True(t, result, "should warn for Redis 10.0.0 with modules (modules bundled in 8.0+)") +} From 9f9a556375bbf65d8155f1b71c49ac4cca65b468 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 14:06:50 +0100 Subject: [PATCH 08/22] feat: read auto minor version upgrade and set it in state --- provider/pro/resource_rediscloud_pro_database.go | 4 ++++ provider/resource_rediscloud_active_active_database.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 9df5641e..94f8329c 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -666,6 +666,10 @@ func resourceRedisCloudProDatabaseRead(ctx context.Context, d *schema.ResourceDa } } + if err := d.Set("auto_minor_version_upgrade", redis.BoolValue(db.AutoMinorVersionUpgrade)); err != nil { + return diag.FromErr(err) + } + if err := ReadTags(ctx, api, subId, dbId, d); err != nil { return diag.FromErr(err) } diff --git a/provider/resource_rediscloud_active_active_database.go b/provider/resource_rediscloud_active_active_database.go index 355d9b78..b10998d7 100644 --- a/provider/resource_rediscloud_active_active_database.go +++ b/provider/resource_rediscloud_active_active_database.go @@ -653,6 +653,10 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R return diag.FromErr(err) } + if err := d.Set("auto_minor_version_upgrade", redis.BoolValue(db.AutoMinorVersionUpgrade)); err != nil { + return diag.FromErr(err) + } + tlsAuthEnabled := *db.CrdbDatabases[0].Security.TLSClientAuthentication if err := utils.ApplyCertificateHints(tlsAuthEnabled, d); err != nil { return diag.FromErr(err) From 3d7eba0ae523791eca9ed3aef474324bc3407b82 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 14:27:23 +0100 Subject: [PATCH 09/22] chore: added logging to the essentials database creation --- .../resource_rediscloud_essentials_database.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index dbb2e471..4a9ba4f9 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -417,6 +417,20 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R createDatabaseRequest.EnableTls = redis.Bool(d.Get("enable_tls").(bool)) } + log.Printf("[DEBUG] Full essentials database create request - Name: %s, Protocol: %s, DataPersistence: %s, DataEviction: %s, Replication: %v, SourceIPs: %v, EnablePaygFeatures: %v, MemoryLimitInGB: %v, SupportOSSClusterAPI: %v, ExternalEndpointForOSSClusterAPI: %v, EnableDatabaseClustering: %v, EnableTls: %v", + redis.StringValue(createDatabaseRequest.Name), + redis.StringValue(createDatabaseRequest.Protocol), + redis.StringValue(createDatabaseRequest.DataPersistence), + redis.StringValue(createDatabaseRequest.DataEvictionPolicy), + redis.BoolValue(createDatabaseRequest.Replication), + createDatabaseRequest.SourceIPs, + d.Get("enable_payg_features").(bool), + createDatabaseRequest.MemoryLimitInGB, + createDatabaseRequest.SupportOSSClusterAPI, + createDatabaseRequest.UseExternalEndpointForOSSClusterAPI, + createDatabaseRequest.EnableDatabaseClustering, + createDatabaseRequest.EnableTls) + log.Printf("[DEBUG] Calling FixedDatabases.Create API for subscription %d with database name: %s", subId, redis.StringValue(createDatabaseRequest.Name)) databaseId, err := api.Client.FixedDatabases.Create(ctx, subId, createDatabaseRequest) if err != nil { From 5fbc6490ddf34b39292e19a971a717a3fe7ea4a5 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 15:13:28 +0100 Subject: [PATCH 10/22] chore: moving activeactive test data to the correct folder --- .../testdata/auto_minor_version_upgrade.tf} | 0 provider/rediscloud_active_active_database_test.go | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename provider/{testdata/active_active_database_auto_minor_version_upgrade.tf => activeactive/testdata/auto_minor_version_upgrade.tf} (100%) diff --git a/provider/testdata/active_active_database_auto_minor_version_upgrade.tf b/provider/activeactive/testdata/auto_minor_version_upgrade.tf similarity index 100% rename from provider/testdata/active_active_database_auto_minor_version_upgrade.tf rename to provider/activeactive/testdata/auto_minor_version_upgrade.tf diff --git a/provider/rediscloud_active_active_database_test.go b/provider/rediscloud_active_active_database_test.go index bb2e89ee..b125257f 100644 --- a/provider/rediscloud_active_active_database_test.go +++ b/provider/rediscloud_active_active_database_test.go @@ -532,7 +532,7 @@ func TestAccResourceRedisCloudActiveActiveDatabase_autoMinorVersionUpgrade(t *te Steps: []resource.TestStep{ // Test database creation with auto_minor_version_upgrade set to false { - Config: fmt.Sprintf(utils.GetTestConfig(t, "./testdata/active_active_database_auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "false"), + Config: fmt.Sprintf(utils.GetTestConfig(t, "./activeactive/testdata/auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "false"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "name", "auto-minor-version-upgrade-test"), resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), @@ -540,7 +540,7 @@ func TestAccResourceRedisCloudActiveActiveDatabase_autoMinorVersionUpgrade(t *te }, // Test database update with auto_minor_version_upgrade set to true { - Config: fmt.Sprintf(utils.GetTestConfig(t, "./testdata/active_active_database_auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "true"), + Config: fmt.Sprintf(utils.GetTestConfig(t, "./activeactive/testdata/auto_minor_version_upgrade.tf"), testCloudAccountName, subscriptionName, name, "true"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), ), From 05d00b6e82b4b36654ab723314718f47f8818416 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 16:03:40 +0100 Subject: [PATCH 11/22] fix: stopping essentials databases sending incorrect source IPs when not PAYG --- ...resource_rediscloud_essentials_database.go | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 4a9ba4f9..ebe4bb8e 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -138,14 +138,15 @@ func resourceRedisCloudEssentialsDatabase() *schema.Resource { Computed: true, }, "source_ips": { - Description: "Set of CIDR addresses to allow access to the database", - Type: schema.TypeList, - Optional: true, - MinItems: 1, + Description: "Set of CIDR addresses to allow access to the database. Supported only for 'Pay-As-You-Go' subscriptions", + Type: schema.TypeList, + Optional: true, + MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeString, ValidateDiagFunc: validation.ToDiagFunc(validation.IsCIDR), }, + DiffSuppressFunc: suppressIfPaygDisabled, }, "replica": { Description: "Details of database replication", @@ -333,11 +334,14 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R createDatabaseRequest.RespVersion = redis.String(respVersion) } - sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) - if len(sourceIps) == 0 { - createDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} - } else { - createDatabaseRequest.SourceIPs = sourceIps + // Only send source_ips for PAYG plans - free plans don't support this feature + if d.Get("enable_payg_features").(bool) { + sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) + if len(sourceIps) == 0 { + createDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} + } else { + createDatabaseRequest.SourceIPs = sourceIps + } } replicaRaw := d.Get("replica").([]interface{}) @@ -638,11 +642,14 @@ func resourceRedisCloudEssentialsDatabaseUpdate(ctx context.Context, d *schema.R updateDatabaseRequest.RespVersion = redis.String(respVersion) } - sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) - if len(sourceIps) == 0 { - updateDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} - } else { - updateDatabaseRequest.SourceIPs = sourceIps + // Only send source_ips for PAYG plans - free plans don't support this feature + if d.Get("enable_payg_features").(bool) { + sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) + if len(sourceIps) == 0 { + updateDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} + } else { + updateDatabaseRequest.SourceIPs = sourceIps + } } replicaRaw := d.Get("replica").([]interface{}) From c92825b9f3564f1521c4381bfded7bc211fbb9da Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 16:12:00 +0100 Subject: [PATCH 12/22] docs: changelog for 2.7.0 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09d1aac4..c9c0a99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/) +# 2.7.0 + +## Added: +- Support for `auto_minor_version_upgrade` attribute on Pro and Active-Active databases. When set to `true`, enables automatic minor version upgrades for Redis databases. + +## Fixed: +- Fixed module validation causing errors for Redis 8. It will now show a warning instead and ignore the modules. +- Fixed `source_ips` being sent to the API for essentials databases on free plans, which caused errors. The `source_ips` attribute is now only sent for PAYG (Pay-As-You-Go) subscriptions when `enable_payg_features` is true. + # 2.6.0 (17th October 2025) ## Added: From 68ae440b1ad6a77dc639385f693c0d0faba38bf2 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Wed, 22 Oct 2025 16:12:37 +0100 Subject: [PATCH 13/22] docs: changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9c0a99d..c7b28168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/) -# 2.7.0 +# 2.7.0 (22nd October 2025) ## Added: - Support for `auto_minor_version_upgrade` attribute on Pro and Active-Active databases. When set to `true`, enables automatic minor version upgrades for Redis databases. From 5d6fb6d490589343a81f3a9dfdc44d9d696a3861 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 10:24:23 +0100 Subject: [PATCH 14/22] fix: revert essentials database source ip fix as this will be fixed API side --- CHANGELOG.md | 10 +++-- ...resource_rediscloud_essentials_database.go | 40 +++++++------------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b28168..bbc777cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,15 @@ See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/) # 2.7.0 (22nd October 2025) ## Added: -- Support for `auto_minor_version_upgrade` attribute on Pro and Active-Active databases. When set to `true`, enables automatic minor version upgrades for Redis databases. +- Add auto_minor_version_upgrade field to Pro and Active-Active database resources (default: true) to allow users to control automatic minor version upgrades. This will NOT affect existing databases. + +## Changed: +- Change Redis 8.0 modules validation from hard error to warning since modules are bundled by default in Redis 8+. ## Fixed: -- Fixed module validation causing errors for Redis 8. It will now show a warning instead and ignore the modules. -- Fixed `source_ips` being sent to the API for essentials databases on free plans, which caused errors. The `source_ips` attribute is now only sent for PAYG (Pay-As-You-Go) subscriptions when `enable_payg_features` is true. +- Fix test error message patterns to match updated API error format. +- Fix Redis 8 upgrade test expectation (dataset_size_in_gb: 3→1). + # 2.6.0 (17th October 2025) diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index ebe4bb8e..52705055 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -138,10 +138,10 @@ func resourceRedisCloudEssentialsDatabase() *schema.Resource { Computed: true, }, "source_ips": { - Description: "Set of CIDR addresses to allow access to the database. Supported only for 'Pay-As-You-Go' subscriptions", - Type: schema.TypeList, - Optional: true, - MinItems: 1, + Description: "Set of CIDR addresses to allow access to the database.", + Type: schema.TypeList, + Optional: true, + MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeString, ValidateDiagFunc: validation.ToDiagFunc(validation.IsCIDR), @@ -307,7 +307,6 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R api := meta.(*client.ApiClient) subId := d.Get("subscription_id").(int) - log.Printf("[DEBUG] Creating essentials database in subscription %d", subId) utils.SubscriptionMutex.Lock(subId) @@ -318,11 +317,6 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R Replication: redis.Bool(d.Get("replication").(bool)), PeriodicBackupPath: redis.String(d.Get("periodic_backup_path").(string)), } - log.Printf("[DEBUG] Essentials database create request - Name: %s, DataPersistence: %s, DataEviction: %s, Replication: %v", - redis.StringValue(createDatabaseRequest.Name), - redis.StringValue(createDatabaseRequest.DataPersistence), - redis.StringValue(createDatabaseRequest.DataEvictionPolicy), - redis.BoolValue(createDatabaseRequest.Replication)) protocol := d.Get("protocol").(string) if protocol != "" { @@ -334,14 +328,11 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R createDatabaseRequest.RespVersion = redis.String(respVersion) } - // Only send source_ips for PAYG plans - free plans don't support this feature - if d.Get("enable_payg_features").(bool) { - sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) - if len(sourceIps) == 0 { - createDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} - } else { - createDatabaseRequest.SourceIPs = sourceIps - } + sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) + if len(sourceIps) == 0 { + createDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} + } else { + createDatabaseRequest.SourceIPs = sourceIps } replicaRaw := d.Get("replica").([]interface{}) @@ -642,14 +633,11 @@ func resourceRedisCloudEssentialsDatabaseUpdate(ctx context.Context, d *schema.R updateDatabaseRequest.RespVersion = redis.String(respVersion) } - // Only send source_ips for PAYG plans - free plans don't support this feature - if d.Get("enable_payg_features").(bool) { - sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) - if len(sourceIps) == 0 { - updateDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} - } else { - updateDatabaseRequest.SourceIPs = sourceIps - } + sourceIps := utils.InterfaceToStringSlice(d.Get("source_ips").([]interface{})) + if len(sourceIps) == 0 { + updateDatabaseRequest.SourceIPs = []*string{redis.String("0.0.0.0/0")} + } else { + updateDatabaseRequest.SourceIPs = sourceIps } replicaRaw := d.Get("replica").([]interface{}) From f02fa5737ae3bb36e5d6d8fb02ca5a6df809cf85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 14:03:26 +0000 Subject: [PATCH 15/22] chore(deps): bump actions/setup-go from 5.5.0 to 6.0.0 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.5.0 to 6.0.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/d35c59abb061a4a6fb18e82ac0862c26744d6ab5...44694675825211faa026b3c33043df3e48a5fa00) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/terraform_provider_main.yml | 2 +- .github/workflows/terraform_provider_pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/terraform_provider_main.yml b/.github/workflows/terraform_provider_main.yml index 98bc39cf..5d9eac7e 100644 --- a/.github/workflows/terraform_provider_main.yml +++ b/.github/workflows/terraform_provider_main.yml @@ -185,7 +185,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go test ./... -run="^TestUnit" # Runs tests starting with TestUnit diff --git a/.github/workflows/terraform_provider_pr.yml b/.github/workflows/terraform_provider_pr.yml index 01096abc..1a41b313 100644 --- a/.github/workflows/terraform_provider_pr.yml +++ b/.github/workflows/terraform_provider_pr.yml @@ -199,7 +199,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 with: go-version-file: go.mod - run: go test ./... -run="^TestUnit" # Runs tests starting with TestUnit From a1cc856bf9620ecb5099101df32d52ae563e4bf5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 14:06:30 +0000 Subject: [PATCH 16/22] chore(deps): bump github/codeql-action from 3 to 4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 927f4f0d..168337f3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -40,7 +40,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -51,7 +51,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -65,4 +65,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 From ed4de4db43c52c5d85e493d920bd08e97487f233 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 11:24:39 +0100 Subject: [PATCH 17/22] fix: essentials databases now warn if modules are detected --- ...resource_rediscloud_essentials_database.go | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 52705055..266fccf1 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -2,9 +2,7 @@ package provider import ( "context" - "fmt" "log" - "strings" "time" "github.com/RedisLabs/rediscloud-go-api/redis" @@ -52,8 +50,6 @@ func resourceRedisCloudEssentialsDatabase() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, - CustomizeDiff: essentialsCustomizeDiff(), - Schema: map[string]*schema.Schema{ "subscription_id": { Description: "Identifier of the essentials subscription", @@ -749,7 +745,7 @@ func resourceRedisCloudEssentialsDatabaseDelete(ctx context.Context, d *schema.R dbErr := api.Client.FixedDatabases.Delete(ctx, subId, databaseId) if dbErr != nil { - diag.FromErr(dbErr) + return diag.FromErr(dbErr) } return diags } @@ -840,25 +836,14 @@ func writeFixedTags(ctx context.Context, api *client.ApiClient, subId int, datab func essentialsCustomizeDiff() schema.CustomizeDiffFunc { return func(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error { - if err := validateModulesForRedis8Essentials()(ctx, diff, meta); err != nil { - return err - } - return nil - } -} - -func validateModulesForRedis8Essentials() schema.CustomizeDiffFunc { - return func(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error { - redisVersion, versionExists := diff.GetOk("redis_version") + // Check if user is trying to specify modules modules, modulesExists := diff.GetOkExists("modules") - if versionExists && modulesExists { - version := redisVersion.(string) - if strings.HasPrefix(version, "8.") { - moduleSet := modules.(*schema.Set) - if moduleSet.Len() > 0 { - return fmt.Errorf(`"modules" cannot be explicitly set for Redis version %s as modules are bundled by default. Remove the "modules" field from your configuration`, version) - } + if modulesExists { + moduleSet := modules.(*schema.Set) + if moduleSet.Len() > 0 { + // Warn, don't error + log.Printf("[WARN] Modules are explicitly configured. Note that some plans may use Redis 8.0+ where modules are bundled by default. The API will reject invalid configurations.") } } return nil From c772416be1c77eee286a0bee9e0ee20e16ae07bf Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 11:37:54 +0100 Subject: [PATCH 18/22] chore: changing to deferred unlock on mutex --- provider/pro/resource_rediscloud_pro_database.go | 5 +---- provider/resource_rediscloud_essentials_database.go | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 94f8329c..39db59ce 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -363,6 +363,7 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource subId := *utils.GetInt(d, "subscription_id") utils.SubscriptionMutex.Lock(subId) + defer utils.SubscriptionMutex.Unlock(subId) createModules := make([]*databases.Module, 0) modules := d.Get("modules").(*schema.Set) @@ -453,7 +454,6 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource dbId, err := api.Client.Database.Create(ctx, subId, createDatabase) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -461,17 +461,14 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource // Confirm db + sub active status if err := utils.WaitForDatabaseToBeActive(ctx, subId, dbId, api); err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases, such as password, enableDefaultUser and so on. - utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudProDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 266fccf1..dbf9ef8a 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -305,6 +305,7 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R subId := d.Get("subscription_id").(int) utils.SubscriptionMutex.Lock(subId) + defer utils.SubscriptionMutex.Unlock(subId) createDatabaseRequest := fixedDatabases.CreateFixedDatabase{ Name: redis.String(d.Get("name").(string)), @@ -426,7 +427,6 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R databaseId, err := api.Client.FixedDatabases.Create(ctx, subId, createDatabaseRequest) if err != nil { log.Printf("[ERROR] FixedDatabases.Create failed for subscription %d: %v", subId, err) - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } log.Printf("[DEBUG] FixedDatabases.Create succeeded for subscription %d, database ID: %d", subId, databaseId) @@ -436,14 +436,12 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R // Confirm Subscription Active status err = waitForEssentialsDatabaseToBeActive(ctx, subId, databaseId, api) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases (enableDefaultUser) // Others are omitted here _because_ the update will take care of them, such as tags - utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudEssentialsDatabaseUpdate(ctx, d, meta) } From c9bf7be791e918653e5cb2f0c8982d1925e43ed2 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 11:46:41 +0100 Subject: [PATCH 19/22] chore: further deferred unlock fixes and implementations --- provider/pro/resource_rediscloud_pro_database.go | 2 ++ provider/resource_rediscloud_active_active_database.go | 7 ++----- ...rce_rediscloud_active_active_private_service_connect.go | 5 +---- provider/resource_rediscloud_essentials_database.go | 2 ++ provider/resource_rediscloud_private_service_connect.go | 5 +---- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 39db59ce..1de10e81 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -469,6 +469,8 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases, such as password, enableDefaultUser and so on. + // Unlock before calling Update since Update also needs to acquire the same subscription mutex. + utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudProDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_active_active_database.go b/provider/resource_rediscloud_active_active_database.go index b10998d7..b10ba3af 100644 --- a/provider/resource_rediscloud_active_active_database.go +++ b/provider/resource_rediscloud_active_active_database.go @@ -361,6 +361,7 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema subId := d.Get("subscription_id").(int) utils.SubscriptionMutex.Lock(subId) + defer utils.SubscriptionMutex.Unlock(subId) name := d.Get("name").(string) supportOSSClusterAPI := d.Get("support_oss_cluster_api").(bool) @@ -395,7 +396,6 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Get regions from /subscriptions/{subscriptionId}/regions, this will use the Regions API regions, err := api.Client.Regions.List(ctx, subId) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -460,13 +460,11 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Confirm Subscription Active status before creating database err = utils.WaitForSubscriptionToBeActive(ctx, subId, api) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } dbId, err := api.Client.Database.ActiveActiveCreate(ctx, subId, createDatabase) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -475,17 +473,16 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Confirm Database Active status err = utils.WaitForDatabaseToBeActive(ctx, subId, dbId, api) if err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { - utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases, such as password and so on. + // Unlock before calling Update since Update also needs to acquire the same subscription mutex. utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudActiveActiveDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_active_active_private_service_connect.go b/provider/resource_rediscloud_active_active_private_service_connect.go index f514d0ee..2e68b381 100644 --- a/provider/resource_rediscloud_active_active_private_service_connect.go +++ b/provider/resource_rediscloud_active_active_private_service_connect.go @@ -64,12 +64,12 @@ func resourceRedisCloudActiveActivePrivateServiceConnectCreate(ctx context.Conte return diag.FromErr(err) } utils.SubscriptionMutex.Lock(subscriptionId) + defer utils.SubscriptionMutex.Unlock(subscriptionId) regionId := d.Get("region_id").(int) pscServiceId, err := api.Client.PrivateServiceConnect.CreateActiveActiveService(ctx, subscriptionId, regionId) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } @@ -79,17 +79,14 @@ func resourceRedisCloudActiveActivePrivateServiceConnectCreate(ctx context.Conte return refreshPrivateServiceConnectServiceActiveActiveStatus(ctx, subscriptionId, regionId, api) }) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } err = utils.WaitForSubscriptionToBeActive(ctx, subscriptionId, api) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } - utils.SubscriptionMutex.Unlock(subscriptionId) return resourceRedisCloudActiveActivePrivateServiceConnectRead(ctx, d, meta) } diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index dbf9ef8a..d15f9b08 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -442,6 +442,8 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases (enableDefaultUser) // Others are omitted here _because_ the update will take care of them, such as tags + // Unlock before calling Update since Update also needs to acquire the same subscription mutex. + utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudEssentialsDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_private_service_connect.go b/provider/resource_rediscloud_private_service_connect.go index 3980ef78..0c2f64e3 100644 --- a/provider/resource_rediscloud_private_service_connect.go +++ b/provider/resource_rediscloud_private_service_connect.go @@ -59,10 +59,10 @@ func resourceRedisCloudPrivateServiceConnectCreate(ctx context.Context, d *schem return diag.FromErr(err) } utils.SubscriptionMutex.Lock(subscriptionId) + defer utils.SubscriptionMutex.Unlock(subscriptionId) pscServiceId, err := api.Client.PrivateServiceConnect.CreateService(ctx, subscriptionId) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } @@ -72,17 +72,14 @@ func resourceRedisCloudPrivateServiceConnectCreate(ctx context.Context, d *schem return refreshPrivateServiceConnectServiceStatus(ctx, subscriptionId, api) }) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } err = utils.WaitForSubscriptionToBeActive(ctx, subscriptionId, api) if err != nil { - utils.SubscriptionMutex.Unlock(subscriptionId) return diag.FromErr(err) } - utils.SubscriptionMutex.Unlock(subscriptionId) return resourceRedisCloudPrivateServiceConnectRead(ctx, d, meta) } From 892dfd839f2f046157a31de0e431bdaca4279567 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 12:16:57 +0100 Subject: [PATCH 20/22] fix: defer unlock crashes --- provider/pro/resource_rediscloud_pro_database.go | 5 ++++- provider/resource_rediscloud_active_active_database.go | 6 +++++- provider/resource_rediscloud_essentials_database.go | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 1de10e81..5cbfbf61 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -363,7 +363,6 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource subId := *utils.GetInt(d, "subscription_id") utils.SubscriptionMutex.Lock(subId) - defer utils.SubscriptionMutex.Unlock(subId) createModules := make([]*databases.Module, 0) modules := d.Get("modules").(*schema.Set) @@ -449,11 +448,13 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource // Confirm sub is ready to accept a db request if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } dbId, err := api.Client.Database.Create(ctx, subId, createDatabase) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -461,9 +462,11 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource // Confirm db + sub active status if err := utils.WaitForDatabaseToBeActive(ctx, subId, dbId, api); err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } diff --git a/provider/resource_rediscloud_active_active_database.go b/provider/resource_rediscloud_active_active_database.go index b10ba3af..e980de6d 100644 --- a/provider/resource_rediscloud_active_active_database.go +++ b/provider/resource_rediscloud_active_active_database.go @@ -361,7 +361,6 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema subId := d.Get("subscription_id").(int) utils.SubscriptionMutex.Lock(subId) - defer utils.SubscriptionMutex.Unlock(subId) name := d.Get("name").(string) supportOSSClusterAPI := d.Get("support_oss_cluster_api").(bool) @@ -396,6 +395,7 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Get regions from /subscriptions/{subscriptionId}/regions, this will use the Regions API regions, err := api.Client.Regions.List(ctx, subId) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -460,11 +460,13 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Confirm Subscription Active status before creating database err = utils.WaitForSubscriptionToBeActive(ctx, subId, api) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } dbId, err := api.Client.Database.ActiveActiveCreate(ctx, subId, createDatabase) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } @@ -473,10 +475,12 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Confirm Database Active status err = utils.WaitForDatabaseToBeActive(ctx, subId, dbId, api) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } if err := utils.WaitForSubscriptionToBeActive(ctx, subId, api); err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index d15f9b08..6c98e614 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -305,7 +305,6 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R subId := d.Get("subscription_id").(int) utils.SubscriptionMutex.Lock(subId) - defer utils.SubscriptionMutex.Unlock(subId) createDatabaseRequest := fixedDatabases.CreateFixedDatabase{ Name: redis.String(d.Get("name").(string)), @@ -427,6 +426,7 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R databaseId, err := api.Client.FixedDatabases.Create(ctx, subId, createDatabaseRequest) if err != nil { log.Printf("[ERROR] FixedDatabases.Create failed for subscription %d: %v", subId, err) + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } log.Printf("[DEBUG] FixedDatabases.Create succeeded for subscription %d, database ID: %d", subId, databaseId) @@ -436,6 +436,7 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R // Confirm Subscription Active status err = waitForEssentialsDatabaseToBeActive(ctx, subId, databaseId, api) if err != nil { + utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } From 10bae1e44217a471e927e6aad1a525c8903cb677 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 12:19:31 +0100 Subject: [PATCH 21/22] chore: cleaning up comments --- provider/pro/resource_rediscloud_pro_database.go | 1 - .../resource_rediscloud_active_active_database.go | 15 +++++++-------- .../resource_rediscloud_essentials_database.go | 1 - 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/provider/pro/resource_rediscloud_pro_database.go b/provider/pro/resource_rediscloud_pro_database.go index 5cbfbf61..5e72be5d 100644 --- a/provider/pro/resource_rediscloud_pro_database.go +++ b/provider/pro/resource_rediscloud_pro_database.go @@ -472,7 +472,6 @@ func resourceRedisCloudProDatabaseCreate(ctx context.Context, d *schema.Resource // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases, such as password, enableDefaultUser and so on. - // Unlock before calling Update since Update also needs to acquire the same subscription mutex. utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudProDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_active_active_database.go b/provider/resource_rediscloud_active_active_database.go index e980de6d..dbfdb478 100644 --- a/provider/resource_rediscloud_active_active_database.go +++ b/provider/resource_rediscloud_active_active_database.go @@ -206,13 +206,13 @@ func resourceRedisCloudActiveActiveDatabase() *schema.Resource { Type: schema.TypeBool, Optional: true, }, - "auto_minor_version_upgrade": { - Description: "When 'true', enables auto minor version upgrades for this database. Default: 'true'", - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "override_region": { + "auto_minor_version_upgrade": { + Description: "When 'true', enables auto minor version upgrades for this database. Default: 'true'", + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "override_region": { Description: "Region-specific configuration parameters to override the global configuration", Type: schema.TypeSet, Optional: true, @@ -486,7 +486,6 @@ func resourceRedisCloudActiveActiveDatabaseCreate(ctx context.Context, d *schema // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases, such as password and so on. - // Unlock before calling Update since Update also needs to acquire the same subscription mutex. utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudActiveActiveDatabaseUpdate(ctx, d, meta) } diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 6c98e614..266fccf1 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -443,7 +443,6 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R // Some attributes on a database are not accessible by the subscription creation API. // Run the subscription update function to apply any additional changes to the databases (enableDefaultUser) // Others are omitted here _because_ the update will take care of them, such as tags - // Unlock before calling Update since Update also needs to acquire the same subscription mutex. utils.SubscriptionMutex.Unlock(subId) return resourceRedisCloudEssentialsDatabaseUpdate(ctx, d, meta) } From 88c1131360a0cc1e2421a268c63e081a55554ae6 Mon Sep 17 00:00:00 2001 From: Matthew Long Date: Thu, 23 Oct 2025 12:24:54 +0100 Subject: [PATCH 22/22] chore: removing debug logging for essentials dbs --- .../resource_rediscloud_essentials_database.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/provider/resource_rediscloud_essentials_database.go b/provider/resource_rediscloud_essentials_database.go index 266fccf1..99735d42 100644 --- a/provider/resource_rediscloud_essentials_database.go +++ b/provider/resource_rediscloud_essentials_database.go @@ -408,28 +408,12 @@ func resourceRedisCloudEssentialsDatabaseCreate(ctx context.Context, d *schema.R createDatabaseRequest.EnableTls = redis.Bool(d.Get("enable_tls").(bool)) } - log.Printf("[DEBUG] Full essentials database create request - Name: %s, Protocol: %s, DataPersistence: %s, DataEviction: %s, Replication: %v, SourceIPs: %v, EnablePaygFeatures: %v, MemoryLimitInGB: %v, SupportOSSClusterAPI: %v, ExternalEndpointForOSSClusterAPI: %v, EnableDatabaseClustering: %v, EnableTls: %v", - redis.StringValue(createDatabaseRequest.Name), - redis.StringValue(createDatabaseRequest.Protocol), - redis.StringValue(createDatabaseRequest.DataPersistence), - redis.StringValue(createDatabaseRequest.DataEvictionPolicy), - redis.BoolValue(createDatabaseRequest.Replication), - createDatabaseRequest.SourceIPs, - d.Get("enable_payg_features").(bool), - createDatabaseRequest.MemoryLimitInGB, - createDatabaseRequest.SupportOSSClusterAPI, - createDatabaseRequest.UseExternalEndpointForOSSClusterAPI, - createDatabaseRequest.EnableDatabaseClustering, - createDatabaseRequest.EnableTls) - - log.Printf("[DEBUG] Calling FixedDatabases.Create API for subscription %d with database name: %s", subId, redis.StringValue(createDatabaseRequest.Name)) databaseId, err := api.Client.FixedDatabases.Create(ctx, subId, createDatabaseRequest) if err != nil { log.Printf("[ERROR] FixedDatabases.Create failed for subscription %d: %v", subId, err) utils.SubscriptionMutex.Unlock(subId) return diag.FromErr(err) } - log.Printf("[DEBUG] FixedDatabases.Create succeeded for subscription %d, database ID: %d", subId, databaseId) d.SetId(utils.BuildResourceId(subId, databaseId))