Skip to content

Commit 44b9652

Browse files
committed
fix: global fields drift issue
1 parent 068f24e commit 44b9652

File tree

1 file changed

+112
-23
lines changed

1 file changed

+112
-23
lines changed

provider/resource_rediscloud_active_active_database.go

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/RedisLabs/terraform-provider-rediscloud/provider/client"
1313
"github.com/RedisLabs/terraform-provider-rediscloud/provider/pro"
1414
"github.com/RedisLabs/terraform-provider-rediscloud/provider/utils"
15+
"github.com/hashicorp/terraform-plugin-log/tflog"
1516
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1617
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
1718
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -267,7 +268,6 @@ func resourceRedisCloudActiveActiveDatabase() *schema.Resource {
267268
Description: "When 'true', enables connecting to the database with the 'default' user. If not set, the global setting will be used.",
268269
Type: schema.TypeBool,
269270
Optional: true,
270-
Default: true,
271271
},
272272
"remote_backup": {
273273
Description: "An object that specifies the backup options for the database in this region",
@@ -526,10 +526,11 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
526526
return diag.FromErr(err)
527527
}
528528

529-
// Read global_data_persistence from API response
530-
if db.GlobalDataPersistence != nil {
531-
if err := d.Set("global_data_persistence", redis.StringValue(db.GlobalDataPersistence)); err != nil {
532-
return diag.FromErr(err)
529+
if _, ok := d.GetOk("global_data_persistence"); ok {
530+
if db.GlobalDataPersistence != nil {
531+
if err := d.Set("global_data_persistence", redis.StringValue(db.GlobalDataPersistence)); err != nil {
532+
return diag.FromErr(err)
533+
}
533534
}
534535
}
535536

@@ -570,6 +571,11 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
570571
var regionDbConfigs []map[string]interface{}
571572
publicEndpointConfig := make(map[string]interface{})
572573
privateEndpointConfig := make(map[string]interface{})
574+
575+
tflog.Debug(ctx, "Read: Starting to process regions from API", map[string]interface{}{
576+
"regionCount": len(db.CrdbDatabases),
577+
})
578+
573579
for _, regionDb := range db.CrdbDatabases {
574580
region := redis.StringValue(regionDb.Region)
575581
// Set the endpoints for the region
@@ -578,8 +584,17 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
578584
// Check if the region is in the state as an override
579585
stateOverrideRegion := getStateOverrideRegion(d, region)
580586
if stateOverrideRegion == nil {
587+
tflog.Debug(ctx, "Read: Skipping region (not in state override_region)", map[string]interface{}{
588+
"region": region,
589+
})
581590
continue
582591
}
592+
593+
tflog.Debug(ctx, "Read: Processing region from state", map[string]interface{}{
594+
"region": region,
595+
"stateHasEnableDefaultUser": stateOverrideRegion["enable_default_user"] != nil,
596+
})
597+
583598
regionDbConfig := map[string]interface{}{
584599
"name": region,
585600
}
@@ -611,6 +626,7 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
611626
sourceIPs = redis.StringSliceValue(regionDb.Security.SourceIPs...)
612627
}
613628

629+
// Only set override fields if they were in the old state (user configured them)
614630
if stateSourceIPs := getStateOverrideRegion(d, region)["override_global_source_ips"]; stateSourceIPs != nil {
615631
if len(stateSourceIPs.(*schema.Set).List()) > 0 {
616632
regionDbConfig["override_global_source_ips"] = sourceIPs
@@ -638,14 +654,44 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
638654

639655
regionDbConfig["remote_backup"] = pro.FlattenBackupPlan(regionDb.Backup, getStateRemoteBackup(d, region), "")
640656

641-
// Only set enable_default_user if it was explicitly configured in the override_region
642-
if stateEnableDefaultUser := getStateOverrideRegion(d, region)["enable_default_user"]; stateEnableDefaultUser != nil {
643-
regionDbConfig["enable_default_user"] = redis.BoolValue(regionDb.Security.EnableDefaultUser)
657+
// Only set enable_default_user if it differs from global (was overridden)
658+
// This prevents drift when region inherits from global (not explicitly set in config)
659+
globalEnableDefaultUser := d.Get("global_enable_default_user").(bool)
660+
regionEnableDefaultUser := redis.BoolValue(regionDb.Security.EnableDefaultUser)
661+
662+
tflog.Debug(ctx, "Read: Checking enable_default_user for region", map[string]interface{}{
663+
"region": region,
664+
"globalValue": globalEnableDefaultUser,
665+
"regionValue": regionEnableDefaultUser,
666+
"isDifferent": regionEnableDefaultUser != globalEnableDefaultUser,
667+
})
668+
669+
if regionEnableDefaultUser != globalEnableDefaultUser {
670+
// Region value differs from global, meaning it was explicitly overridden
671+
tflog.Debug(ctx, "Read: Setting enable_default_user in state (differs from global)", map[string]interface{}{
672+
"region": region,
673+
"value": regionEnableDefaultUser,
674+
})
675+
regionDbConfig["enable_default_user"] = regionEnableDefaultUser
676+
} else {
677+
tflog.Debug(ctx, "Read: NOT setting enable_default_user in state (matches global)", map[string]interface{}{
678+
"region": region,
679+
})
644680
}
645681

682+
tflog.Debug(ctx, "Read: Completed region config", map[string]interface{}{
683+
"region": region,
684+
"hasEnableDefaultUser": regionDbConfig["enable_default_user"] != nil,
685+
"enableDefaultUserValue": regionDbConfig["enable_default_user"],
686+
})
687+
646688
regionDbConfigs = append(regionDbConfigs, regionDbConfig)
647689
}
648690

691+
tflog.Debug(ctx, "Read: Completed processing all regions", map[string]interface{}{
692+
"totalRegionsProcessed": len(regionDbConfigs),
693+
})
694+
649695
// Only set override_region if it is defined in the config
650696
if len(d.Get("override_region").(*schema.Set).List()) > 0 {
651697
if err := d.Set("override_region", regionDbConfigs); err != nil {
@@ -667,15 +713,23 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
667713
return diag.FromErr(err)
668714
}
669715

670-
if err := d.Set("auto_minor_version_upgrade", redis.BoolValue(db.AutoMinorVersionUpgrade)); err != nil {
671-
return diag.FromErr(err)
716+
if _, ok := d.GetOk("auto_minor_version_upgrade"); ok {
717+
if err := d.Set("auto_minor_version_upgrade", redis.BoolValue(db.AutoMinorVersionUpgrade)); err != nil {
718+
return diag.FromErr(err)
719+
}
672720
}
673721

674722
// Read global_enable_default_user from API response
675723
if db.GlobalEnableDefaultUser != nil {
676-
if err := d.Set("global_enable_default_user", redis.BoolValue(db.GlobalEnableDefaultUser)); err != nil {
724+
globalValue := redis.BoolValue(db.GlobalEnableDefaultUser)
725+
tflog.Debug(ctx, "Read: Setting global_enable_default_user from API", map[string]interface{}{
726+
"value": globalValue,
727+
})
728+
if err := d.Set("global_enable_default_user", globalValue); err != nil {
677729
return diag.FromErr(err)
678730
}
731+
} else {
732+
tflog.Debug(ctx, "Read: global_enable_default_user is nil in API response", map[string]interface{}{})
679733
}
680734

681735
tlsAuthEnabled := *db.CrdbDatabases[0].Security.TLSClientAuthentication
@@ -750,6 +804,11 @@ func resourceRedisCloudActiveActiveDatabaseUpdate(ctx context.Context, d *schema
750804

751805
// Make a list of region-specific configurations
752806
var regions []*databases.LocalRegionProperties
807+
808+
tflog.Debug(ctx, "Update: Starting to build region configurations", map[string]interface{}{
809+
"regionCount": len(d.Get("override_region").(*schema.Set).List()),
810+
})
811+
753812
for _, region := range d.Get("override_region").(*schema.Set).List() {
754813
dbRegion := region.(map[string]interface{})
755814

@@ -773,9 +832,23 @@ func resourceRedisCloudActiveActiveDatabaseUpdate(ctx context.Context, d *schema
773832
enableDefaultUser := dbRegion["enable_default_user"].(bool)
774833
wasExplicitlySet := isEnableDefaultUserExplicitlySetInConfig(d, regionName)
775834

835+
tflog.Debug(ctx, "Checking enable_default_user for region", map[string]interface{}{
836+
"region": regionName,
837+
"value": enableDefaultUser,
838+
"wasExplicitlySet": wasExplicitlySet,
839+
})
840+
776841
if wasExplicitlySet {
777842
// Field was explicitly set in Terraform config, send the value
843+
tflog.Debug(ctx, "Sending enable_default_user to API", map[string]interface{}{
844+
"region": regionName,
845+
"value": enableDefaultUser,
846+
})
778847
regionProps.EnableDefaultUser = redis.Bool(enableDefaultUser)
848+
} else {
849+
tflog.Debug(ctx, "Not sending enable_default_user (inherit from global)", map[string]interface{}{
850+
"region": regionName,
851+
})
779852
}
780853
// If not explicitly set, don't send - let it inherit from global
781854

@@ -807,9 +880,19 @@ func resourceRedisCloudActiveActiveDatabaseUpdate(ctx context.Context, d *schema
807880

808881
regionProps.RemoteBackup = pro.BuildBackupPlan(dbRegion["remote_backup"], nil)
809882

883+
tflog.Debug(ctx, "Update: Completed building region properties", map[string]interface{}{
884+
"region": regionName,
885+
"hasEnableDefaultUser": regionProps.EnableDefaultUser != nil,
886+
"enableDefaultUserValue": regionProps.EnableDefaultUser,
887+
})
888+
810889
regions = append(regions, regionProps)
811890
}
812891

892+
tflog.Debug(ctx, "Update: Completed building all region configurations", map[string]interface{}{
893+
"totalRegions": len(regions),
894+
})
895+
813896
// Populate the database update request with the required fields
814897
update := databases.UpdateActiveActiveDatabase{
815898
GlobalAlerts: &updateAlerts,
@@ -982,18 +1065,16 @@ func flattenModulesToNames(modules []*databases.Module) []string {
9821065
return moduleNames
9831066
}
9841067

985-
// isEnableDefaultUserExplicitlySetInConfig checks if enable_default_user was explicitly
986-
// set in the Terraform configuration for a specific region in the override_region block.
1068+
// isOverrideFieldExplicitlySetInConfig checks if a field was explicitly set in the
1069+
// Terraform configuration for a specific region in the override_region block.
9871070
//
988-
// This is needed because TypeBool doesn't distinguish between "not set" and "false".
1071+
// This is needed to distinguish between "not set" and "set to default/empty value".
9891072
// We use GetRawConfig() to check if the field exists in the original HCL configuration.
990-
func isEnableDefaultUserExplicitlySetInConfig(d *schema.ResourceData, regionName string) bool {
1073+
func isOverrideFieldExplicitlySetInConfig(d *schema.ResourceData, regionName string, fieldName string) bool {
9911074
rawConfig := d.GetRawConfig()
9921075

993-
// If raw config is null (e.g., in test environment), fall back to conservative behavior
1076+
// If raw config is null (e.g., during Read operations), fall back to conservative behavior
9941077
if rawConfig.IsNull() {
995-
// In this case, we can't determine if it was explicitly set
996-
// Default to not sending it to avoid overriding global settings unintentionally
9971078
return false
9981079
}
9991080

@@ -1017,11 +1098,11 @@ func isEnableDefaultUserExplicitlySetInConfig(d *schema.ResourceData, regionName
10171098
if regionVal.Type().HasAttribute("name") {
10181099
nameAttr := regionVal.GetAttr("name")
10191100
if !nameAttr.IsNull() && nameAttr.AsString() == regionName {
1020-
// Found the matching region, check if enable_default_user exists
1021-
if regionVal.Type().HasAttribute("enable_default_user") {
1022-
eduAttr := regionVal.GetAttr("enable_default_user")
1101+
// Found the matching region, check if field exists
1102+
if regionVal.Type().HasAttribute(fieldName) {
1103+
fieldAttr := regionVal.GetAttr(fieldName)
10231104
// If the attribute exists and is not null, it was explicitly set
1024-
return !eduAttr.IsNull()
1105+
return !fieldAttr.IsNull()
10251106
}
10261107
// Field doesn't exist in config for this region
10271108
return false
@@ -1030,6 +1111,14 @@ func isEnableDefaultUserExplicitlySetInConfig(d *schema.ResourceData, regionName
10301111
}
10311112
}
10321113

1033-
// Region not found or enable_default_user not set
1114+
// Region not found or field not set
10341115
return false
10351116
}
1117+
1118+
// isEnableDefaultUserExplicitlySetInConfig checks if enable_default_user was explicitly
1119+
// set in the Terraform configuration for a specific region in the override_region block.
1120+
//
1121+
// This is a convenience wrapper around isOverrideFieldExplicitlySetInConfig.
1122+
func isEnableDefaultUserExplicitlySetInConfig(d *schema.ResourceData, regionName string) bool {
1123+
return isOverrideFieldExplicitlySetInConfig(d, regionName, "enable_default_user")
1124+
}

0 commit comments

Comments
 (0)