Copilot commented on code in PR #281:
URL: 
https://github.com/apache/cloudstack-terraform-provider/pull/281#discussion_r2936975512


##########
cloudstack/resource_cloudstack_network_acl_rule.go:
##########
@@ -232,6 +481,30 @@ func resourceCloudStackNetworkACLRuleCreate(d 
*schema.ResourceData, meta interfa
                        log.Printf("[ERROR] Failed to set rule attribute: %v", 
err)
                        return err
                }
+       } else if nrs := d.Get("ruleset").(*schema.Set); nrs.Len() > 0 {
+               // Handle 'ruleset' (TypeSet with mandatory rule_number)
+               rules := make([]interface{}, 0)
+
+               log.Printf("[DEBUG] Processing %d rules from 'ruleset' field", 
nrs.Len())
+
+               // Convert Set to list (no auto-numbering needed, rule_number 
is required)
+               rulesList := nrs.List()
+

Review Comment:
   `ruleset` create path skips `verifyNetworkACLRuleParams` entirely before 
calling `createNetworkACLRules`. Because `createNetworkACLRule` performs 
unchecked type assertions (e.g., `rule["icmp_type"].(int)`), invalid/missing 
fields can cause panics or much less actionable CloudStack API errors. Validate 
each `ruleset` element (same as the legacy `rule` path) before creation, and do 
the same validation for `newRules`/`newRuleset` in Update before calling 
`updateNetworkACLRules`/creating new rules.
   



##########
cloudstack/resource_cloudstack_network_acl_rule.go:
##########
@@ -369,26 +645,97 @@ func createNetworkACLRule(d *schema.ResourceData, meta 
interface{}, rule map[str
                        log.Printf("[ERROR] Failed to create ALL rule: %v", err)
                        return err
                }
-               uuids["all"] = r.(*cloudstack.CreateNetworkACLResponse).Id
-               rule["uuids"] = uuids
-               log.Printf("[DEBUG] Created ALL rule with ID=%s", 
r.(*cloudstack.CreateNetworkACLResponse).Id)
+               ruleID := r.(*cloudstack.CreateNetworkACLResponse).Id
+               setRuleUUID(rule, "all", ruleID)
+               log.Printf("[DEBUG] Created ALL rule with ID=%s", ruleID)
        }
 
        // If protocol is TCP or UDP, create the rule (with or without port)
        if rule["protocol"].(string) == "tcp" || rule["protocol"].(string) == 
"udp" {
-               // Check if deprecated ports field is used and reject it
-               if portsSet, hasPortsSet := rule["ports"].(*schema.Set); 
hasPortsSet && portsSet.Len() > 0 {
-                       log.Printf("[ERROR] Attempt to create rule with 
deprecated ports field")
-                       return fmt.Errorf("The 'ports' field is no longer 
supported for creating new rules. Please use the 'port' field with separate 
rules for each port/range.")
-               }
-
+               // Check if deprecated ports field is used (for backward 
compatibility)
+               portsSet, hasPortsSet := rule["ports"].(*schema.Set)
                portStr, hasPort := rule["port"].(string)
 
-               if hasPort && portStr != "" {
+               if hasPortsSet && portsSet.Len() > 0 {
+                       // Handle deprecated ports field for backward 
compatibility
+                       // Create a separate rule for each port in the set, 
each with a unique rule number
+                       log.Printf("[DEBUG] Using deprecated ports field for 
backward compatibility, creating %d rules", portsSet.Len())
+
+                       // Get the base rule number - this should always be set 
by assignRuleNumbers
+                       baseRuleNum := 0
+                       if ruleNum, ok := rule["rule_number"].(int); ok && 
ruleNum > 0 {
+                               baseRuleNum = ruleNum
+                       }
+
+                       portIndex := 0
+                       for _, port := range portsSet.List() {
+                               portValue := port.(string)
+

Review Comment:
   When expanding deprecated `ports` into multiple CloudStack rules, iteration 
uses `portsSet.List()` (TypeSet) which is not ordered. Because you derive 
`uniqueRuleNum := baseRuleNum + portIndex`, the assigned rule numbers (and 
therefore rule priorities) can change between runs even if the configured ports 
are the same. Sort the port strings before iterating so numbering is 
deterministic and stable.
   



##########
cloudstack/resource_cloudstack_network_acl_rule.go:
##########
@@ -300,17 +576,17 @@ func createNetworkACLRules(d *schema.ResourceData, meta 
interface{}, rules *[]in
 
 func createNetworkACLRule(d *schema.ResourceData, meta interface{}, rule 
map[string]interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
-       uuids := rule["uuids"].(map[string]interface{})
-       log.Printf("[DEBUG] Creating network ACL rule with protocol=%s", 
rule["protocol"].(string))
 
-       // Make sure all required parameters are there
-       if err := verifyNetworkACLRuleParams(d, rule); err != nil {
-               log.Printf("[ERROR] Failed to verify rule parameters: %v", err)
-               return err
-       }
+       protocol := rule["protocol"].(string)
+       action := rule["action"].(string)
+       trafficType := rule["traffic_type"].(string)
+
+       log.Printf("[DEBUG] Creating network ACL rule with protocol=%s, 
action=%s, traffic_type=%s", protocol, action, trafficType)
+
+       // Note: Parameter verification is done before assignRuleNumbers in 
resourceCloudStackNetworkACLRuleCreate
 
        // Create a new parameter struct

Review Comment:
   `createNetworkACLRule` assumes “parameter verification is done before 
assignRuleNumbers in Create”, but this function is also called from Update (for 
new rules) and from the `ruleset` Create path, where that verification is not 
guaranteed. Either re-introduce `verifyNetworkACLRuleParams` inside 
`createNetworkACLRule` (so all call sites are protected) or ensure every caller 
(Create/Update for both `rule` and `ruleset`) validates rules before invoking 
it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to