This is an automated email from the ASF dual-hosted git repository.

sureshanaparti pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git


The following commit(s) were added to refs/heads/main by this push:
     new edf76e1  Feature: Add dest_cidr_list support to egress firewall (#298)
edf76e1 is described below

commit edf76e19d9bd09f8a3515e5e60a9122101dae70e
Author: Elias Flötzinger <[email protected]>
AuthorDate: Mon Aug 17 13:12:32 2026 +0200

    Feature: Add dest_cidr_list support to egress firewall (#298)
    
    * chore: add .worktrees to .gitignore
    
    * feat: add dest_cidr_list support to cloudstack_egress_firewall
    
    Adds the destcidrlist parameter to egress firewall rules, allowing
    users to restrict the destination of egress traffic. The field is
    optional and maps to the CloudStack API's destcidrlist parameter.
    
    Fixes #296
    
    * refactor: simplify egress firewall read with cidrSetFromList helper
    
    Restructure resourceCloudStackEgressFirewallRead to use a switch on the
    protocol and extract the repeated CIDR set-building into a single
    cidrSetFromList helper.
    
    The helper returns an empty set for an empty list, restoring the guard
    against empty Destcidrlist consistently across all branches.
    
    Verified with the egress firewall acceptance tests against the
    cloudstack simulator.
    
    * docs: add dest_cidr_list example and 'all' protocol to egress firewall
---
 .gitignore                                        |   2 +
 cloudstack/resource_cloudstack_egress_firewall.go | 134 ++++++++++++----------
 website/docs/r/egress_firewall.html.markdown      |  13 ++-
 3 files changed, 81 insertions(+), 68 deletions(-)

diff --git a/.gitignore b/.gitignore
index b6b0f36..2c88f78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,5 @@ website/vendor
 !command/test-fixtures/**/.terraform/
 .terraform.lock.hcl
 provider.tf
+.worktrees/
+.env
diff --git a/cloudstack/resource_cloudstack_egress_firewall.go 
b/cloudstack/resource_cloudstack_egress_firewall.go
index e2a83e4..beec0bd 100644
--- a/cloudstack/resource_cloudstack_egress_firewall.go
+++ b/cloudstack/resource_cloudstack_egress_firewall.go
@@ -70,6 +70,13 @@ func resourceCloudStackEgressFirewall() *schema.Resource {
                                                        Set:      
schema.HashString,
                                                },
 
+                                               "dest_cidr_list": {
+                                                       Type:     
schema.TypeSet,
+                                                       Optional: true,
+                                                       Elem:     
&schema.Schema{Type: schema.TypeString},
+                                                       Set:      
schema.HashString,
+                                               },
+
                                                "protocol": {
                                                        Type:     
schema.TypeString,
                                                        Required: true,
@@ -194,6 +201,15 @@ func createEgressFirewallRule(d *schema.ResourceData, meta 
interface{}, rule map
                p.SetCidrlist(cidrList)
        }
 
+       // Set the destination CIDR list
+       if rs, ok := rule["dest_cidr_list"].(*schema.Set); ok && rs.Len() > 0 {
+               var destCidrList []string
+               for _, cidr := range 
rule["dest_cidr_list"].(*schema.Set).List() {
+                       destCidrList = append(destCidrList, cidr.(string))
+               }
+               p.SetDestcidrlist(destCidrList)
+       }
+
        // If the protocol is ICMP set the needed ICMP parameters
        if rule["protocol"].(string) == "icmp" {
                p.SetIcmptype(rule["icmp_type"].(int))
@@ -264,6 +280,19 @@ func createEgressFirewallRule(d *schema.ResourceData, meta 
interface{}, rule map
        return nil
 }
 
+// cidrSetFromList builds a schema.Set of CIDRs from a comma-separated list,
+// returning an empty set when the list is empty.
+func cidrSetFromList(list string) *schema.Set {
+       set := &schema.Set{F: schema.HashString}
+       if list == "" {
+               return set
+       }
+       for _, cidr := range strings.Split(list, ",") {
+               set.Add(cidr)
+       }
+       return set
+}
+
 func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta 
interface{}) error {
        cs := meta.(*cloudstack.CloudStackClient)
 
@@ -297,7 +326,10 @@ func resourceCloudStackEgressFirewallRead(d 
*schema.ResourceData, meta interface
                        rule := rule.(map[string]interface{})
                        uuids := rule["uuids"].(map[string]interface{})
 
-                       if rule["protocol"].(string) == "icmp" {
+                       protocol := strings.ToLower(rule["protocol"].(string))
+
+                       switch protocol {
+                       case "icmp":
                                id, ok := uuids["icmp"]
                                if !ok {
                                        continue
@@ -313,64 +345,14 @@ func resourceCloudStackEgressFirewallRead(d 
*schema.ResourceData, meta interface
                                // Delete the known rule so only unknown rules 
remain in the ruleMap
                                delete(ruleMap, id.(string))
 
-                               // Create a set with all CIDR's
-                               cidrs := &schema.Set{F: schema.HashString}
-                               for _, cidr := range strings.Split(r.Cidrlist, 
",") {
-                                       cidrs.Add(cidr)
-                               }
-
                                // Update the values
                                rule["protocol"] = r.Protocol
                                rule["icmp_type"] = r.Icmptype
                                rule["icmp_code"] = r.Icmpcode
-                               rule["cidr_list"] = cidrs
+                               rule["cidr_list"] = cidrSetFromList(r.Cidrlist)
+                               rule["dest_cidr_list"] = 
cidrSetFromList(r.Destcidrlist)
                                rules.Add(rule)
-                       }
-
-                       // If protocol is not ICMP, loop through all ports
-                       if rule["protocol"].(string) != "icmp" && 
strings.ToLower(rule["protocol"].(string)) != "all" {
-                               if ps := rule["ports"].(*schema.Set); ps.Len() 
> 0 {
-
-                                       // Create an empty schema.Set to hold 
all ports
-                                       ports := &schema.Set{F: 
schema.HashString}
-
-                                       // Loop through all ports and retrieve 
their info
-                                       for _, port := range ps.List() {
-                                               id, ok := uuids[port.(string)]
-                                               if !ok {
-                                                       continue
-                                               }
-
-                                               // Get the rule
-                                               r, ok := ruleMap[id.(string)]
-                                               if !ok {
-                                                       delete(uuids, 
port.(string))
-                                                       continue
-                                               }
-
-                                               // Delete the known rule so 
only unknown rules remain in the ruleMap
-                                               delete(ruleMap, id.(string))
-
-                                               // Create a set with all CIDR's
-                                               cidrs := &schema.Set{F: 
schema.HashString}
-                                               for _, cidr := range 
strings.Split(r.Cidrlist, ",") {
-                                                       cidrs.Add(cidr)
-                                               }
-
-                                               // Update the values
-                                               rule["protocol"] = r.Protocol
-                                               rule["cidr_list"] = cidrs
-                                               ports.Add(port)
-                                       }
-
-                                       // If there is at least one port found, 
add this rule to the rules set
-                                       if ports.Len() > 0 {
-                                               rule["ports"] = ports
-                                               rules.Add(rule)
-                                       }
-                               }
-                       }
-                       if strings.ToLower(rule["protocol"].(string)) == "all" {
+                       case "all":
                                id, ok := uuids["all"]
                                if !ok {
                                        continue
@@ -386,18 +368,44 @@ func resourceCloudStackEgressFirewallRead(d 
*schema.ResourceData, meta interface
                                // Delete the known rule so only unknown rules 
remain in the ruleMap
                                delete(ruleMap, id.(string))
 
-                               // Create a set with all CIDR's
-                               if _, ok := rule["cidr_list"]; ok {
-                                       cidrs := &schema.Set{F: 
schema.HashString}
-                                       for _, cidr := range 
strings.Split(r.Cidrlist, ",") {
-                                               cidrs.Add(cidr)
-                                       }
-                                       rule["cidr_list"] = cidrs
-                               }
-
                                // Update the values
                                rule["protocol"] = r.Protocol
+                               rule["cidr_list"] = cidrSetFromList(r.Cidrlist)
+                               rule["dest_cidr_list"] = 
cidrSetFromList(r.Destcidrlist)
                                rules.Add(rule)
+                       default:
+                               // Create an empty schema.Set to hold all ports
+                               ports := &schema.Set{F: schema.HashString}
+
+                               // Loop through all ports and retrieve their 
info
+                               for _, port := range 
rule["ports"].(*schema.Set).List() {
+                                       id, ok := uuids[port.(string)]
+                                       if !ok {
+                                               continue
+                                       }
+
+                                       // Get the rule
+                                       r, ok := ruleMap[id.(string)]
+                                       if !ok {
+                                               delete(uuids, port.(string))
+                                               continue
+                                       }
+
+                                       // Delete the known rule so only 
unknown rules remain in the ruleMap
+                                       delete(ruleMap, id.(string))
+
+                                       // Update the values
+                                       rule["protocol"] = r.Protocol
+                                       rule["cidr_list"] = 
cidrSetFromList(r.Cidrlist)
+                                       rule["dest_cidr_list"] = 
cidrSetFromList(r.Destcidrlist)
+                                       ports.Add(port)
+                               }
+
+                               // If there is at least one port found, add 
this rule to the rules set
+                               if ports.Len() > 0 {
+                                       rule["ports"] = ports
+                                       rules.Add(rule)
+                               }
                        }
                }
        }
diff --git a/website/docs/r/egress_firewall.html.markdown 
b/website/docs/r/egress_firewall.html.markdown
index 10badd1..dde7406 100644
--- a/website/docs/r/egress_firewall.html.markdown
+++ b/website/docs/r/egress_firewall.html.markdown
@@ -17,9 +17,10 @@ resource "cloudstack_egress_firewall" "default" {
   network_id = "6eb22f91-7454-4107-89f4-36afcdf33021"
 
   rule {
-    cidr_list = ["10.0.0.0/8"]
-    protocol  = "tcp"
-    ports     = ["80", "1000-2000"]
+    cidr_list      = ["10.0.0.0/8"]
+    dest_cidr_list = ["192.168.0.0/16"]
+    protocol       = "tcp"
+    ports          = ["80", "1000-2000"]
   }
 }
 ```
@@ -43,10 +44,12 @@ The following arguments are supported:
 
 The `rule` block supports:
 
-* `cidr_list` - (Required) A CIDR list to allow access to the given ports.
+* `cidr_list` - (Optional) A CIDR list to allow access to the given ports.
+
+* `dest_cidr_list` - (Optional) A CIDR list to restrict the destination of 
egress traffic.
 
 * `protocol` - (Required) The name of the protocol to allow. Valid options are:
-    `tcp`, `udp` and `icmp`.
+    `tcp`, `udp`, `icmp` and `all`.
 
 * `icmp_type` - (Optional) The ICMP type to allow. This can only be specified 
if
     the protocol is ICMP.

Reply via email to