@@ -2,6 +2,7 @@ package provider
22
33import (
44 "context"
5+ "sort"
56
67 "github.com/RedisLabs/rediscloud-go-api/redis"
78 "github.com/RedisLabs/rediscloud-go-api/service/databases"
@@ -198,79 +199,162 @@ func filterDefaultSourceIPs(apiSourceIPs []*string) []string {
198199}
199200
200201// addSourceIPsIfOverridden adds override_global_source_ips to region config if it differs from global.
201- func addSourceIPsIfOverridden (regionDbConfig map [string ]interface {}, d * schema.ResourceData , regionDb * databases.CrdbDatabase ) {
202+ func addSourceIPsIfOverridden (ctx context. Context , regionDbConfig map [string ]interface {}, d * schema.ResourceData , regionDb * databases.CrdbDatabase , region string ) {
202203 sourceIPs := filterDefaultSourceIPs (regionDb .Security .SourceIPs )
204+
205+ tflog .Debug (ctx , "Read: addSourceIPsIfOverridden" , map [string ]interface {}{
206+ "region" : region ,
207+ "apiSourceIPsCount" : len (regionDb .Security .SourceIPs ),
208+ "filteredIPsCount" : len (sourceIPs ),
209+ "filteredIPs" : sourceIPs ,
210+ })
211+
203212 if len (sourceIPs ) == 0 {
213+ tflog .Debug (ctx , "Read: Skipping source IPs (filtered to empty)" , map [string ]interface {}{"region" : region })
204214 return
205215 }
206216
207217 globalSourceIPsPtrs := utils .SetToStringSlice (d .Get ("global_source_ips" ).(* schema.Set ))
208218 globalSourceIPs := redis .StringSliceValue (globalSourceIPsPtrs ... )
209219
210- if ! stringSlicesEqual (sourceIPs , globalSourceIPs ) {
220+ shouldAdd := ! stringSlicesEqual (sourceIPs , globalSourceIPs )
221+ tflog .Debug (ctx , "Read: Source IPs comparison" , map [string ]interface {}{
222+ "region" : region ,
223+ "regionIPs" : sourceIPs ,
224+ "globalIPs" : globalSourceIPs ,
225+ "shouldAdd" : shouldAdd ,
226+ })
227+
228+ if shouldAdd {
211229 regionDbConfig ["override_global_source_ips" ] = sourceIPs
212230 }
213231}
214232
215233// addDataPersistenceIfOverridden adds override_global_data_persistence to region config if it differs from global.
216234func addDataPersistenceIfOverridden (
235+ ctx context.Context ,
217236 regionDbConfig map [string ]interface {},
218237 db * databases.ActiveActiveDatabase ,
219238 regionDb * databases.CrdbDatabase ,
239+ region string ,
220240) {
221241 if regionDb .DataPersistence != nil && db .GlobalDataPersistence != nil {
222- if redis .StringValue (regionDb .DataPersistence ) != redis .StringValue (db .GlobalDataPersistence ) {
242+ regionValue := redis .StringValue (regionDb .DataPersistence )
243+ globalValue := redis .StringValue (db .GlobalDataPersistence )
244+ shouldAdd := regionValue != globalValue
245+
246+ tflog .Debug (ctx , "Read: Data persistence comparison" , map [string ]interface {}{
247+ "region" : region ,
248+ "regionValue" : regionValue ,
249+ "globalValue" : globalValue ,
250+ "shouldAdd" : shouldAdd ,
251+ })
252+
253+ if shouldAdd {
223254 regionDbConfig ["override_global_data_persistence" ] = regionDb .DataPersistence
224255 }
256+ } else {
257+ tflog .Debug (ctx , "Read: Skipping data persistence (nil values)" , map [string ]interface {}{
258+ "region" : region ,
259+ "regionIsNil" : regionDb .DataPersistence == nil ,
260+ "globalIsNil" : db .GlobalDataPersistence == nil ,
261+ })
225262 }
226263}
227264
228265// addPasswordIfOverridden adds override_global_password to region config if it differs from global.
229266func addPasswordIfOverridden (
267+ ctx context.Context ,
230268 regionDbConfig map [string ]interface {},
231269 db * databases.ActiveActiveDatabase ,
232270 regionDb * databases.CrdbDatabase ,
271+ region string ,
233272) {
234273 if regionDb .Security .Password != nil && db .GlobalPassword != nil {
235- if * regionDb .Security .Password != redis .StringValue (db .GlobalPassword ) {
236- regionDbConfig ["override_global_password" ] = redis .StringValue (regionDb .Security .Password )
274+ regionValue := * regionDb .Security .Password
275+ globalValue := redis .StringValue (db .GlobalPassword )
276+ shouldAdd := regionValue != globalValue
277+
278+ tflog .Debug (ctx , "Read: Password comparison" , map [string ]interface {}{
279+ "region" : region ,
280+ "regionValue" : "[REDACTED]" ,
281+ "globalValue" : "[REDACTED]" ,
282+ "valuesDiffer" : shouldAdd ,
283+ "shouldAdd" : shouldAdd ,
284+ })
285+
286+ if shouldAdd {
287+ regionDbConfig ["override_global_password" ] = regionValue
237288 }
289+ } else {
290+ tflog .Debug (ctx , "Read: Skipping password (nil values)" , map [string ]interface {}{
291+ "region" : region ,
292+ "regionIsNil" : regionDb .Security .Password == nil ,
293+ "globalIsNil" : db .GlobalPassword == nil ,
294+ })
238295 }
239296}
240297
241298// addAlertsIfOverridden adds override_global_alert to region config if count differs from global.
242299// Note: Active-Active API doesn't return global alerts separately, so we compare counts.
243300func addAlertsIfOverridden (
301+ ctx context.Context ,
244302 regionDbConfig map [string ]interface {},
245303 d * schema.ResourceData ,
246304 regionDb * databases.CrdbDatabase ,
305+ region string ,
247306) {
248307 globalAlerts := d .Get ("global_alert" ).(* schema.Set ).List ()
249308 regionAlerts := pro .FlattenAlerts (regionDb .Alerts )
309+ shouldAdd := len (globalAlerts ) != len (regionAlerts )
310+
311+ tflog .Debug (ctx , "Read: Alerts comparison" , map [string ]interface {}{
312+ "region" : region ,
313+ "globalAlertsCount" : len (globalAlerts ),
314+ "globalAlerts" : globalAlerts ,
315+ "regionAlertsCount" : len (regionAlerts ),
316+ "regionAlerts" : regionAlerts ,
317+ "shouldAdd" : shouldAdd ,
318+ })
250319
251- if len ( globalAlerts ) != len ( regionAlerts ) {
320+ if shouldAdd {
252321 regionDbConfig ["override_global_alert" ] = regionAlerts
253322 }
254323}
255324
256325// addRemoteBackupIfConfigured adds remote_backup to region config if it exists in both API and state.
257326func addRemoteBackupIfConfigured (
327+ ctx context.Context ,
258328 regionDbConfig map [string ]interface {},
259329 regionDb * databases.CrdbDatabase ,
260330 stateOverrideRegion map [string ]interface {},
331+ region string ,
261332) {
333+ tflog .Debug (ctx , "Read: Checking remote backup" , map [string ]interface {}{
334+ "region" : region ,
335+ "apiHasBackup" : regionDb .Backup != nil ,
336+ })
337+
262338 if regionDb .Backup == nil {
339+ tflog .Debug (ctx , "Read: Skipping remote backup (nil in API)" , map [string ]interface {}{"region" : region })
263340 return
264341 }
265342
266343 stateRemoteBackup := stateOverrideRegion ["remote_backup" ]
267344 if stateRemoteBackup == nil {
345+ tflog .Debug (ctx , "Read: Skipping remote backup (nil in state)" , map [string ]interface {}{"region" : region })
268346 return
269347 }
270348
271349 stateRemoteBackupList := stateRemoteBackup .([]interface {})
350+ tflog .Debug (ctx , "Read: Remote backup state list" , map [string ]interface {}{
351+ "region" : region ,
352+ "listCount" : len (stateRemoteBackupList ),
353+ })
354+
272355 if len (stateRemoteBackupList ) > 0 {
273356 regionDbConfig ["remote_backup" ] = pro .FlattenBackupPlan (regionDb .Backup , stateRemoteBackupList , "" )
357+ tflog .Debug (ctx , "Read: Added remote_backup to region config" , map [string ]interface {}{"region" : region })
274358 }
275359}
276360
@@ -323,30 +407,47 @@ func logRegionConfigBuilt(ctx context.Context, region string, regionDbConfig map
323407// buildRegionConfigFromAPIAndState orchestrates building region config from API and state.
324408// Each override field is handled by a dedicated helper function for clarity and maintainability.
325409func buildRegionConfigFromAPIAndState (ctx context.Context , d * schema.ResourceData , db * databases.ActiveActiveDatabase , region string , regionDb * databases.CrdbDatabase , stateOverrideRegion map [string ]interface {}) map [string ]interface {} {
410+ tflog .Debug (ctx , "Read: Starting buildRegionConfigFromAPIAndState" , map [string ]interface {}{
411+ "region" : region ,
412+ })
413+
326414 regionDbConfig := map [string ]interface {}{
327415 "name" : region ,
328416 }
329417
330418 // Handle each override field using dedicated helper functions
331- addSourceIPsIfOverridden (regionDbConfig , d , regionDb )
332- addDataPersistenceIfOverridden (regionDbConfig , db , regionDb )
333- addPasswordIfOverridden (regionDbConfig , db , regionDb )
334- addAlertsIfOverridden (regionDbConfig , d , regionDb )
335- addRemoteBackupIfConfigured (regionDbConfig , regionDb , stateOverrideRegion )
419+ addSourceIPsIfOverridden (ctx , regionDbConfig , d , regionDb , region )
420+ addDataPersistenceIfOverridden (ctx , regionDbConfig , db , regionDb , region )
421+ addPasswordIfOverridden (ctx , regionDbConfig , db , regionDb , region )
422+ addAlertsIfOverridden (ctx , regionDbConfig , d , regionDb , region )
423+ addRemoteBackupIfConfigured (ctx , regionDbConfig , regionDb , stateOverrideRegion , region )
336424 addEnableDefaultUserIfNeeded (ctx , regionDbConfig , d , db , region , regionDb )
337425
338426 logRegionConfigBuilt (ctx , region , regionDbConfig )
339427
340428 return regionDbConfig
341429}
342430
343- // stringSlicesEqual compares two string slices for equality (order matters)
431+ // stringSlicesEqual compares two string slices for equality (order-insensitive).
432+ // This is used for comparing source IP lists where order doesn't matter.
344433func stringSlicesEqual (a , b []string ) bool {
345434 if len (a ) != len (b ) {
346435 return false
347436 }
348- for i := range a {
349- if a [i ] != b [i ] {
437+
438+ // Make copies to avoid modifying the original slices
439+ aCopy := make ([]string , len (a ))
440+ bCopy := make ([]string , len (b ))
441+ copy (aCopy , a )
442+ copy (bCopy , b )
443+
444+ // Sort both copies
445+ sort .Strings (aCopy )
446+ sort .Strings (bCopy )
447+
448+ // Compare sorted slices
449+ for i := range aCopy {
450+ if aCopy [i ] != bCopy [i ] {
350451 return false
351452 }
352453 }
0 commit comments