11package provider
22
33import (
4+ "context"
45 "fmt"
6+ "strconv"
7+ "strings"
58 "testing"
69
10+ "github.com/RedisLabs/rediscloud-go-api/redis"
11+ "github.com/RedisLabs/terraform-provider-rediscloud/provider/client"
712 "github.com/RedisLabs/terraform-provider-rediscloud/provider/utils"
813 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
914 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
15+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1016)
1117
1218// TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser tests the enable_default_user field
1319// for global and regional override behavior, specifically testing for drift issues when:
14- // - Regions inherit from global (field NOT in override_region)
15- // - Regions explicitly override global (field IS in override_region)
16- // - User explicitly sets same value as global (field IS in override_region, tests explicit vs inherited)
20+ // - Regions inherit from global (field NOT in override_region) - Steps 1, 5
21+ // - Regions explicitly override global (field IS in override_region) - Steps 2, 3
22+ // - User explicitly sets same value as global (field IS in override_region, tests explicit vs inherited) - Steps 4, 6
23+ //
24+ // Tests all 6 combinations:
25+ // Step 1: global=true, both inherit
26+ // Step 2: global=true, one region=false, one inherit
27+ // Step 3: global=false, one region=true, one inherit
28+ // Step 4: global=true, region1=true (matches), region2=false
29+ // Step 5: global=false, both inherit
30+ // Step 6: global=false, region1=false (matches), one inherit
1731func TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser (t * testing.T ) {
1832 subscriptionName := acctest .RandomWithPrefix (testResourcePrefix ) + "-subscription"
1933 databaseName := acctest .RandomWithPrefix (testResourcePrefix ) + "-database"
@@ -47,6 +61,12 @@ func TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser(t *testing.
4761 // Neither region should have enable_default_user in state (inheriting from global)
4862 resource .TestCheckNoResourceAttr (databaseResourceName , "override_region.0.enable_default_user" ),
4963 resource .TestCheckNoResourceAttr (databaseResourceName , "override_region.1.enable_default_user" ),
64+
65+ // API check: Both regions should have true (inherited from global)
66+ testCheckEnableDefaultUserInAPI (databaseResourceName , true , map [string ]* bool {
67+ "us-east-1" : nil , // nil means inherits from global
68+ "us-east-2" : nil ,
69+ }),
5070 ),
5171 },
5272 // Step 2: global=true, us-east-1 explicit false (field SHOULD appear in override_region)
@@ -67,9 +87,20 @@ func TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser(t *testing.
6787 // Two regions
6888 resource .TestCheckResourceAttr (databaseResourceName , "override_region.#" , "2" ),
6989
70- // us-east-1 has explicit false - need to find which index it is
71- // We check both indices and one should have enable_default_user=false
72- // Note: TypeSet ordering is non-deterministic, so we check both indices
90+ // us-east-1 has explicit false (differs from global=true)
91+ // us-east-2 inherits (no explicit field)
92+ // Use TestCheckTypeSet to verify specific TypeSet element fields
93+ resource .TestCheckTypeSetElemNestedAttrs (databaseResourceName , "override_region.*" , map [string ]string {
94+ "name" : "us-east-1" ,
95+ "enable_default_user" : "false" ,
96+ }),
97+ // us-east-2 should NOT have enable_default_user field in this step
98+
99+ // API check: us-east-1=false (explicit), us-east-2=true (inherited)
100+ testCheckEnableDefaultUserInAPI (databaseResourceName , true , map [string ]* bool {
101+ "us-east-1" : redis .Bool (false ), // Explicit override
102+ "us-east-2" : nil , // Inherits from global
103+ }),
73104 ),
74105 },
75106 // Step 3: global=false, us-east-1 explicit true (field SHOULD appear in override_region)
@@ -90,7 +121,18 @@ func TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser(t *testing.
90121 // Two regions
91122 resource .TestCheckResourceAttr (databaseResourceName , "override_region.#" , "2" ),
92123
93- // us-east-1 has explicit true - will appear in one of the indices
124+ // us-east-1 has explicit true (differs from global=false)
125+ resource .TestCheckTypeSetElemNestedAttrs (databaseResourceName , "override_region.*" , map [string ]string {
126+ "name" : "us-east-1" ,
127+ "enable_default_user" : "true" ,
128+ }),
129+ // us-east-2 inherits (no explicit field)
130+
131+ // API check: us-east-1=true (explicit), us-east-2=false (inherited)
132+ testCheckEnableDefaultUserInAPI (databaseResourceName , false , map [string ]* bool {
133+ "us-east-1" : redis .Bool (true ), // Explicit override
134+ "us-east-2" : nil , // Inherits from global
135+ }),
94136 ),
95137 },
96138 // Step 4: global=true, both regions explicit (us-east-1=true, us-east-2=false)
@@ -112,13 +154,165 @@ func TestAccResourceRedisCloudActiveActiveDatabase_enableDefaultUser(t *testing.
112154 // Two regions
113155 resource .TestCheckResourceAttr (databaseResourceName , "override_region.#" , "2" ),
114156
115- // Both regions have explicit enable_default_user
157+ // Both regions have explicit enable_default_user - both should be in state
116158 // us-east-1 has true (matches global but explicit)
159+ resource .TestCheckTypeSetElemNestedAttrs (databaseResourceName , "override_region.*" , map [string ]string {
160+ "name" : "us-east-1" ,
161+ "enable_default_user" : "true" ,
162+ }),
117163 // us-east-2 has false (differs from global)
118- // Due to TypeSet non-deterministic ordering, we can't check specific indices
119- // But the key point is both should have the field in state
164+ resource .TestCheckTypeSetElemNestedAttrs (databaseResourceName , "override_region.*" , map [string ]string {
165+ "name" : "us-east-2" ,
166+ "enable_default_user" : "false" ,
167+ }),
168+
169+ // API check: us-east-1=true (explicit), us-east-2=false (explicit)
170+ testCheckEnableDefaultUserInAPI (databaseResourceName , true , map [string ]* bool {
171+ "us-east-1" : redis .Bool (true ), // Explicit (matches global)
172+ "us-east-2" : redis .Bool (false ), // Explicit (differs from global)
173+ }),
174+ ),
175+ },
176+ // Step 5: global=false, both regions inherit (NO enable_default_user in override_region)
177+ // Mirror of Step 1 but with global=false
178+ {
179+ PreConfig : func () {
180+ t .Logf ("Starting Step 5: global=false, both regions inherit" )
181+ },
182+ Config : fmt .Sprintf (
183+ utils .GetTestConfig (t , "./activeactive/testdata/enable_default_user_global_false_inherit.tf" ),
184+ subscriptionName ,
185+ databaseName ,
186+ databasePassword ,
187+ ),
188+ Check : resource .ComposeAggregateTestCheckFunc (
189+ // Global setting
190+ resource .TestCheckResourceAttr (databaseResourceName , "global_enable_default_user" , "false" ),
191+
192+ // Both regions should exist
193+ resource .TestCheckResourceAttr (databaseResourceName , "override_region.#" , "2" ),
194+
195+ // Neither region should have enable_default_user in state (inheriting from global)
196+ resource .TestCheckNoResourceAttr (databaseResourceName , "override_region.0.enable_default_user" ),
197+ resource .TestCheckNoResourceAttr (databaseResourceName , "override_region.1.enable_default_user" ),
198+
199+ // API check: Both regions should have false (inherited from global)
200+ testCheckEnableDefaultUserInAPI (databaseResourceName , false , map [string ]* bool {
201+ "us-east-1" : nil , // Inherits from global
202+ "us-east-2" : nil ,
203+ }),
204+ ),
205+ },
206+ // Step 6: global=false, us-east-1 explicit false (field SHOULD appear in override_region)
207+ // Tests explicit false matching global false (vs inheriting)
208+ {
209+ PreConfig : func () {
210+ t .Logf ("Starting Step 6: global=false, us-east-1 explicit false (matches global)" )
211+ },
212+ Config : fmt .Sprintf (
213+ utils .GetTestConfig (t , "./activeactive/testdata/enable_default_user_global_false_region_false.tf" ),
214+ subscriptionName ,
215+ databaseName ,
216+ databasePassword ,
217+ ),
218+ Check : resource .ComposeAggregateTestCheckFunc (
219+ // Global setting
220+ resource .TestCheckResourceAttr (databaseResourceName , "global_enable_default_user" , "false" ),
221+
222+ // Two regions
223+ resource .TestCheckResourceAttr (databaseResourceName , "override_region.#" , "2" ),
224+
225+ // us-east-1 has explicit false (matches global but is EXPLICIT)
226+ resource .TestCheckTypeSetElemNestedAttrs (databaseResourceName , "override_region.*" , map [string ]string {
227+ "name" : "us-east-1" ,
228+ "enable_default_user" : "false" ,
229+ }),
230+ // us-east-2 inherits (no explicit field)
231+
232+ // API check: us-east-1=false (explicit, matches global), us-east-2=false (inherited)
233+ testCheckEnableDefaultUserInAPI (databaseResourceName , false , map [string ]* bool {
234+ "us-east-1" : redis .Bool (false ), // Explicit (matches global)
235+ "us-east-2" : nil , // Inherits from global
236+ }),
120237 ),
121238 },
122239 },
123240 })
124241}
242+
243+ // testCheckEnableDefaultUserInAPI verifies the enable_default_user values in the actual Redis Cloud API
244+ // expected: map[regionName]expectedValue (nil means should match global)
245+ func testCheckEnableDefaultUserInAPI (resourceName string , expectedGlobal bool , expectedRegions map [string ]* bool ) resource.TestCheckFunc {
246+ return func (s * terraform.State ) error {
247+ rs , ok := s .RootModule ().Resources [resourceName ]
248+ if ! ok {
249+ return fmt .Errorf ("resource not found: %s" , resourceName )
250+ }
251+
252+ // Parse subscription_id and db_id from resource
253+ subIdStr := rs .Primary .Attributes ["subscription_id" ]
254+ dbIdStr := rs .Primary .Attributes ["db_id" ]
255+
256+ subId , err := strconv .Atoi (subIdStr )
257+ if err != nil {
258+ return fmt .Errorf ("failed to parse subscription_id: %v" , err )
259+ }
260+
261+ dbId , err := strconv .Atoi (dbIdStr )
262+ if err != nil {
263+ return fmt .Errorf ("failed to parse db_id: %v" , err )
264+ }
265+
266+ // Get API client
267+ apiClient , err := client .GetClient ()
268+ if err != nil {
269+ return fmt .Errorf ("failed to get API client: %v" , err )
270+ }
271+
272+ // Fetch database from API
273+ ctx := context .Background ()
274+ db , err := apiClient .Client .Database .GetActiveActive (ctx , subId , dbId )
275+ if err != nil {
276+ return fmt .Errorf ("failed to get database from API: %v" , err )
277+ }
278+
279+ // Check global enable_default_user
280+ if db .GlobalEnableDefaultUser == nil {
281+ return fmt .Errorf ("API returned nil for GlobalEnableDefaultUser" )
282+ }
283+ actualGlobal := redis .BoolValue (db .GlobalEnableDefaultUser )
284+ if actualGlobal != expectedGlobal {
285+ return fmt .Errorf ("API global_enable_default_user: expected %v, got %v" , expectedGlobal , actualGlobal )
286+ }
287+
288+ // Check regional enable_default_user values
289+ for _ , regionDb := range db .CrdbDatabases {
290+ regionName := redis .StringValue (regionDb .Region )
291+
292+ if regionDb .Security == nil || regionDb .Security .EnableDefaultUser == nil {
293+ return fmt .Errorf ("API returned nil for region %s EnableDefaultUser" , regionName )
294+ }
295+
296+ actualRegionValue := redis .BoolValue (regionDb .Security .EnableDefaultUser )
297+
298+ // Get expected value for this region
299+ expectedValue , hasExplicitOverride := expectedRegions [regionName ]
300+
301+ var expectedRegionValue bool
302+ if hasExplicitOverride && expectedValue != nil {
303+ // Region has explicit override
304+ expectedRegionValue = * expectedValue
305+ } else {
306+ // Region inherits from global
307+ expectedRegionValue = expectedGlobal
308+ }
309+
310+ if actualRegionValue != expectedRegionValue {
311+ return fmt .Errorf ("API region %s enable_default_user: expected %v, got %v" ,
312+ regionName , expectedRegionValue , actualRegionValue )
313+ }
314+ }
315+
316+ return nil
317+ }
318+ }
0 commit comments