@@ -58,7 +58,7 @@ func (r *customAllocationRulesResource) Schema(_ context.Context, _ resource.Sch
5858 Required : true ,
5959 },
6060 "override_ui_defined_resources" : schema.BoolAttribute {
61- Description : "Whether to override UI-defined rules. When set to true, any rules created via the UI that are not defined in Terraform will be deleted and perform reorder based on the rules from the terraform. Default is false" ,
61+ Description : "Whether to override UI-defined rules. When set to true, any rules created via the UI that are not defined in Terraform will be deleted and Terraform will be used as the source of truth for rules and their ordering. When set to false, any rules created via the UI that are at the end of order will be kept but will be warned, otherwise an error will be thrown in terraform plan phase . Default is false" ,
6262 Optional : true ,
6363 },
6464 // Resource ID
@@ -87,11 +87,11 @@ func (r *customAllocationRulesResource) Read(ctx context.Context, request resour
8787 return
8888 }
8989
90- // Get the managed rule IDs from the current state
91- var managedRuleIDs [] string
90+ // Create a map for quick lookup of managed IDs
91+ managedIDsSet := make ( map [ string ] bool )
9292 for _ , tfID := range state .RuleIDs .Elements () {
9393 ruleID := tfID .(types.String ).ValueString ()
94- managedRuleIDs = append ( managedRuleIDs , ruleID )
94+ managedIDsSet [ ruleID ] = true
9595 }
9696
9797 // Check override setting to determine how to build state
@@ -112,17 +112,11 @@ func (r *customAllocationRulesResource) Read(ctx context.Context, request resour
112112 rules = * respData
113113 }
114114
115- // Create a map for quick lookup of managed IDs
116- managedIDsSet := make (map [string ]bool )
117- for _ , id := range managedRuleIDs {
118- managedIDsSet [id ] = true
119- }
120-
121115 // Get rules with positions
122- // During import (managedRuleIDs is empty): get ALL rules
123- // When override=false: only managed rules
116+ // During import (managedIDsSet is empty): get ALL rules
117+ // When override=false: only managed rules
124118 // When override=true: ALL rules (so Terraform can detect difference and trigger Update to delete unmanaged)
125- isImport := len (managedRuleIDs ) == 0
119+ isImport := len (managedIDsSet ) == 0
126120 rulePositions := getRulesWithPositions (rules , managedIDsSet , ! override && ! isImport )
127121
128122 // Verify all managed rules still exist
@@ -133,14 +127,14 @@ func (r *customAllocationRulesResource) Read(ctx context.Context, request resour
133127 }
134128 }
135129
136- if managedCount != len (managedRuleIDs ) {
130+ if managedCount != len (managedIDsSet ) {
137131 // Some managed rules were deleted
138132 missingIDs := []string {}
139133 foundIDs := make (map [string ]bool )
140134 for _ , rp := range rulePositions {
141135 foundIDs [rp .ID ] = true
142136 }
143- for _ , id := range managedRuleIDs {
137+ for id := range managedIDsSet {
144138 if ! foundIDs [id ] {
145139 missingIDs = append (missingIDs , id )
146140 }
@@ -214,17 +208,11 @@ func (r *customAllocationRulesResource) ModifyPlan(ctx context.Context, request
214208 existingRules = * respData
215209 }
216210
217- // Convert the Terraform list to strings
218- var desiredRuleIDs []string
219- for _ , tfID := range plan .RuleIDs .Elements () {
220- ruleID := tfID .(types.String ).ValueString ()
221- desiredRuleIDs = append (desiredRuleIDs , ruleID )
222- }
223-
224211 // Create a map of desired IDs for checking unmanaged rules
225212 desiredIDsSet := make (map [string ]bool )
226- for _ , id := range desiredRuleIDs {
227- desiredIDsSet [id ] = true
213+ for _ , tfID := range plan .RuleIDs .Elements () {
214+ ruleID := tfID .(types.String ).ValueString ()
215+ desiredIDsSet [ruleID ] = true
228216 }
229217
230218 // Get all rules with positions sorted
@@ -341,7 +329,7 @@ func extractRuleFields(rule datadogV2.ArbitraryRuleResponseData) (id string, nam
341329 }
342330 }
343331
344- // If normal fields failed, try UnparsedObject
332+ // If normal fields failed, try UnparsedObject
345333 // This happens when the API returns fields the generated client doesn't know about
346334 if rule .UnparsedObject != nil {
347335 // Extract ID
@@ -426,20 +414,14 @@ func findUnmanagedRules(allRules []ruleWithPosition, managedIDsSet map[string]bo
426414 }
427415
428416 // Check if all unmanaged are at the end
417+ // Since allRules is sorted by position, if unmanaged rules are all at the end,
418+ // they should form a contiguous block. We only need to check if the first unmanaged
419+ // rule starts at the expected position.
429420 allAtEnd := false
430421 if len (unmanagedRules ) > 0 {
431422 firstUnmanagedPos := unmanagedPositions [0 ]
432423 expectedStartPos := len (allRules ) - len (unmanagedRules )
433-
434424 allAtEnd = firstUnmanagedPos == expectedStartPos
435- if allAtEnd {
436- for i , pos := range unmanagedPositions {
437- if pos != expectedStartPos + i {
438- allAtEnd = false
439- break
440- }
441- }
442- }
443425 }
444426
445427 return unmanagedRuleInfo {
@@ -497,23 +479,6 @@ func (r *customAllocationRulesResource) updateOrderWithDeletion(state *customAll
497479 }
498480 }
499481
500- // Check if we extracted fewer IDs than total rules (API client deserialization bug)
501- if len (existingIDList ) < len (existingRules ) {
502- diag .AddError (
503- "Unable to extract IDs from all rules" ,
504- fmt .Sprintf ("The API returned %d rules, but we could only extract IDs from %d of them. " +
505- "This is likely due to a deserialization issue in the API client library. " +
506- "To work around this issue, please:\n " +
507- "1. Go to the Datadog UI and manually delete any problematic rules\n " +
508- "2. Or set override_ui_defined_resources=false to preserve unmanaged rules\n " +
509- "3. Then try again\n \n " +
510- "Successfully extracted IDs: %v\n " +
511- "Total rules from API: %d" ,
512- len (existingRules ), len (existingIDList ), existingIDList , len (existingRules )),
513- )
514- return
515- }
516-
517482 // Validate desired rules exist
518483 for _ , ruleID := range desiredOrder {
519484 if ! existingIDs [ruleID ] {
0 commit comments