@@ -272,6 +272,7 @@ func resourceRedisCloudActiveActiveDatabase() *schema.Resource {
272272 Description : "When 'true', enables connecting to the database with the 'default' user. If not specified, the region inherits the value from global_enable_default_user." ,
273273 Type : schema .TypeBool ,
274274 Optional : true ,
275+ Computed : true ,
275276 DiffSuppressFunc : func (k , old , new string , d * schema.ResourceData ) bool {
276277 // Smart diff suppression: only suppress when truly inheriting from global
277278 // Check both: value matches global AND field not explicitly set in config
@@ -692,10 +693,45 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
692693
693694 regionDbConfig ["remote_backup" ] = pro .FlattenBackupPlan (regionDb .Backup , getStateRemoteBackup (d , region ), "" )
694695
695- // Always include enable_default_user in state (even when inheriting from global)
696- // DiffSuppressFunc will prevent drift when value matches global
696+ // Conditionally include enable_default_user in state
697+ // Only include if: (1) explicitly set in config, OR (2) differs from global (API override)
698+ // DiffSuppressFunc provides additional safety net for edge cases
697699 if regionDb .Security .EnableDefaultUser != nil {
698- regionDbConfig ["enable_default_user" ] = redis .BoolValue (regionDb .Security .EnableDefaultUser )
700+ globalValue := d .Get ("global_enable_default_user" ).(bool )
701+ regionValue := redis .BoolValue (regionDb .Security .EnableDefaultUser )
702+
703+ shouldInclude := false
704+
705+ rawConfig := d .GetRawConfig ()
706+ if ! rawConfig .IsNull () && rawConfig .IsKnown () {
707+ // Apply/Update mode: GetRawConfig available - check actual HCL config
708+ explicitInConfig := isFieldInConfigForRegion (d , region , "enable_default_user" )
709+
710+ if explicitInConfig {
711+ // User explicitly set it in config → always include
712+ shouldInclude = true
713+ } else if regionValue != globalValue {
714+ // Not in config but differs from global → API override exists, include to track it
715+ shouldInclude = true
716+ }
717+ // else: not in config and matches global → inheriting, omit from state
718+ } else {
719+ // Refresh mode: GetRawConfig is null - check previous state via GetRawState
720+ fieldWasInState := isFieldInStateForRegion (d , region , "enable_default_user" )
721+
722+ if fieldWasInState {
723+ // Was explicitly tracked before → continue tracking
724+ shouldInclude = true
725+ } else if regionValue != globalValue {
726+ // New API override detected → start tracking
727+ shouldInclude = true
728+ }
729+ // else: wasn't tracked and matches global → keep omitted
730+ }
731+
732+ if shouldInclude {
733+ regionDbConfig ["enable_default_user" ] = regionValue
734+ }
699735 }
700736
701737 regionDbConfigs = append (regionDbConfigs , regionDbConfig )
@@ -714,8 +750,21 @@ func resourceRedisCloudActiveActiveDatabaseRead(ctx context.Context, d *schema.R
714750 if err := d .Set ("private_endpoint" , privateEndpointConfig ); err != nil {
715751 return diag .FromErr (err )
716752 }
717- if err := d .Set ("global_modules" , flattenModulesToNames (db .Modules )); err != nil {
718- return diag .FromErr (err )
753+ // For Redis 8.0+, modules are bundled by default and returned by the API
754+ // Only set modules in state if they were explicitly defined in the config
755+ redisVersion := redis .StringValue (db .RedisVersion )
756+ if shouldSuppressModuleDiffsForRedis8 (redisVersion ) {
757+ // Only set modules if they were explicitly configured by the user
758+ if _ , ok := d .GetOk ("global_modules" ); ok {
759+ if err := d .Set ("global_modules" , flattenModulesToNames (db .Modules )); err != nil {
760+ return diag .FromErr (err )
761+ }
762+ }
763+ } else {
764+ // For Redis < 8.0, always set modules from API response
765+ if err := d .Set ("global_modules" , flattenModulesToNames (db .Modules )); err != nil {
766+ return diag .FromErr (err )
767+ }
719768 }
720769
721770 if err := d .Set ("redis_version" , redis .StringValue (db .RedisVersion )); err != nil {
@@ -1102,3 +1151,66 @@ func isFieldInConfigForRegion(d *schema.ResourceData, regionName string, fieldNa
11021151 return false
11031152}
11041153
1154+ // isFieldInStateForRegion checks if a field is present in the actual persisted state
1155+ // for a specific region's override_region block. Uses GetRawState() to bypass materialization.
1156+ // Returns true only if the field exists in the actual state file.
1157+ func isFieldInStateForRegion (d * schema.ResourceData , regionName string , fieldName string ) bool {
1158+ rawState := d .GetRawState ()
1159+ if rawState .IsNull () || ! rawState .IsKnown () {
1160+ return false
1161+ }
1162+
1163+ if ! rawState .Type ().HasAttribute ("override_region" ) {
1164+ return false
1165+ }
1166+
1167+ overrideRegions := rawState .GetAttr ("override_region" )
1168+ if overrideRegions .IsNull () || ! overrideRegions .IsKnown () {
1169+ return false
1170+ }
1171+
1172+ // Iterate through regions to find matching name
1173+ iter := overrideRegions .ElementIterator ()
1174+ for iter .Next () {
1175+ _ , regionVal := iter .Element ()
1176+
1177+ if regionVal .IsNull () || ! regionVal .IsKnown () {
1178+ continue
1179+ }
1180+
1181+ if ! regionVal .Type ().HasAttribute ("name" ) {
1182+ continue
1183+ }
1184+
1185+ nameAttr := regionVal .GetAttr ("name" )
1186+ if nameAttr .IsNull () || ! nameAttr .IsKnown () {
1187+ continue
1188+ }
1189+
1190+ // Check if the name matches
1191+ if nameAttr .AsString () == regionName {
1192+ // Found the region, check if field exists
1193+ if ! regionVal .Type ().HasAttribute (fieldName ) {
1194+ return false
1195+ }
1196+ fieldAttr := regionVal .GetAttr (fieldName )
1197+ return ! fieldAttr .IsNull ()
1198+ }
1199+ }
1200+
1201+ return false
1202+ }
1203+
1204+ // shouldSuppressModuleDiffsForRedis8 checks if the Redis version is 8.0 or higher.
1205+ // For Redis 8+, modules are bundled by default, so we suppress drift for modules
1206+ // that weren't explicitly configured by the user.
1207+ func shouldSuppressModuleDiffsForRedis8 (version string ) bool {
1208+ if len (version ) == 0 {
1209+ return false
1210+ }
1211+ majorVersionStr := strings .Split (version , "." )[0 ]
1212+ if majorVersion , err := strconv .Atoi (majorVersionStr ); err == nil {
1213+ return majorVersion >= 8
1214+ }
1215+ return false
1216+ }
0 commit comments