@@ -369,6 +369,99 @@ func createNetworkACLRule(d *schema.ResourceData, meta interface{}, rule map[str
369369 return nil
370370}
371371
372+ func processTCPUDPRule (rule map [string ]interface {}, ruleMap map [string ]* cloudstack.NetworkACL , uuids map [string ]interface {}, rules * []interface {}) {
373+ // Check for deprecated ports field first (for backward compatibility)
374+ ps , hasPortsSet := rule ["ports" ].(* schema.Set )
375+ portStr , hasPort := rule ["port" ].(string )
376+
377+ if hasPortsSet && ps .Len () > 0 {
378+ log .Printf ("[DEBUG] Processing %d ports for TCP/UDP rule (deprecated field)" , ps .Len ())
379+
380+ var ports []interface {}
381+ for _ , port := range ps .List () {
382+ if processPortForRule (port .(string ), rule , ruleMap , uuids ) {
383+ ports = append (ports , port )
384+ log .Printf ("[DEBUG] Added port %s to TCP/UDP rule" , port .(string ))
385+ }
386+ }
387+
388+ if len (ports ) > 0 {
389+ rule ["ports" ] = schema .NewSet (schema .HashString , ports )
390+ * rules = append (* rules , rule )
391+ log .Printf ("[DEBUG] Added TCP/UDP rule with deprecated ports to state: %+v" , rule )
392+ }
393+
394+ } else if hasPort && portStr != "" {
395+ log .Printf ("[DEBUG] Processing single port for TCP/UDP rule: %s" , portStr )
396+
397+ if processPortForRule (portStr , rule , ruleMap , uuids ) {
398+ rule ["port" ] = portStr
399+ * rules = append (* rules , rule )
400+ log .Printf ("[DEBUG] Added TCP/UDP rule with single port to state: %+v" , rule )
401+ }
402+
403+ } else {
404+ log .Printf ("[DEBUG] Processing TCP/UDP rule with no port specified" )
405+
406+ id , ok := uuids ["all_ports" ]
407+ if ! ok {
408+ log .Printf ("[DEBUG] No UUID for all_ports, skipping rule" )
409+ return
410+ }
411+
412+ r , ok := ruleMap [id .(string )]
413+ if ! ok {
414+ log .Printf ("[DEBUG] TCP/UDP rule for all_ports with ID %s not found, removing UUID" , id .(string ))
415+ delete (uuids , "all_ports" )
416+ return
417+ }
418+
419+ delete (ruleMap , id .(string ))
420+
421+ var cidrs []interface {}
422+ for _ , cidr := range strings .Split (r .Cidrlist , "," ) {
423+ cidrs = append (cidrs , cidr )
424+ }
425+
426+ rule ["action" ] = strings .ToLower (r .Action )
427+ rule ["protocol" ] = r .Protocol
428+ rule ["traffic_type" ] = strings .ToLower (r .Traffictype )
429+ rule ["cidr_list" ] = cidrs
430+ * rules = append (* rules , rule )
431+ log .Printf ("[DEBUG] Added TCP/UDP rule with no port to state: %+v" , rule )
432+ }
433+ }
434+
435+ func processPortForRule (portStr string , rule map [string ]interface {}, ruleMap map [string ]* cloudstack.NetworkACL , uuids map [string ]interface {}) bool {
436+ id , ok := uuids [portStr ]
437+ if ! ok {
438+ log .Printf ("[DEBUG] No UUID for port %s, skipping" , portStr )
439+ return false
440+ }
441+
442+ r , ok := ruleMap [id .(string )]
443+ if ! ok {
444+ log .Printf ("[DEBUG] TCP/UDP rule for port %s with ID %s not found, removing UUID" , portStr , id .(string ))
445+ delete (uuids , portStr )
446+ return false
447+ }
448+
449+ // Delete the known rule so only unknown rules remain in the ruleMap
450+ delete (ruleMap , id .(string ))
451+
452+ var cidrs []interface {}
453+ for _ , cidr := range strings .Split (r .Cidrlist , "," ) {
454+ cidrs = append (cidrs , cidr )
455+ }
456+
457+ rule ["action" ] = strings .ToLower (r .Action )
458+ rule ["protocol" ] = r .Protocol
459+ rule ["traffic_type" ] = strings .ToLower (r .Traffictype )
460+ rule ["cidr_list" ] = cidrs
461+
462+ return true
463+ }
464+
372465func resourceCloudStackNetworkACLRuleRead (d * schema.ResourceData , meta interface {}) error {
373466 cs := meta .(* cloudstack.CloudStackClient )
374467 log .Printf ("[DEBUG] Entering resourceCloudStackNetworkACLRuleRead with acl_id=%s" , d .Id ())
@@ -501,111 +594,8 @@ func resourceCloudStackNetworkACLRuleRead(d *schema.ResourceData, meta interface
501594 }
502595
503596 if rule ["protocol" ].(string ) == "tcp" || rule ["protocol" ].(string ) == "udp" {
504- // Check for deprecated ports field first (for backward compatibility)
505- ps , hasPortsSet := rule ["ports" ].(* schema.Set )
506- portStr , hasPort := rule ["port" ].(string )
507-
508- if hasPortsSet && ps .Len () > 0 {
509- // Handle deprecated ports field (multiple ports)
510- log .Printf ("[DEBUG] Processing %d ports for TCP/UDP rule (deprecated field)" , ps .Len ())
511-
512- var ports []interface {}
513- for _ , port := range ps .List () {
514- id , ok := uuids [port .(string )]
515- if ! ok {
516- log .Printf ("[DEBUG] No UUID for port %s, skipping" , port .(string ))
517- continue
518- }
519-
520- r , ok := ruleMap [id .(string )]
521- if ! ok {
522- log .Printf ("[DEBUG] TCP/UDP rule for port %s with ID %s not found, removing UUID" , port .(string ), id .(string ))
523- delete (uuids , port .(string ))
524- continue
525- }
526-
527- // Delete the known rule so only unknown rules remain in the ruleMap
528- delete (ruleMap , id .(string ))
529-
530- var cidrs []interface {}
531- for _ , cidr := range strings .Split (r .Cidrlist , "," ) {
532- cidrs = append (cidrs , cidr )
533- }
534-
535- rule ["action" ] = strings .ToLower (r .Action )
536- rule ["protocol" ] = r .Protocol
537- rule ["traffic_type" ] = strings .ToLower (r .Traffictype )
538- rule ["cidr_list" ] = cidrs
539- ports = append (ports , port )
540- log .Printf ("[DEBUG] Added port %s to TCP/UDP rule" , port .(string ))
541- }
542-
543- rule ["ports" ] = schema .NewSet (schema .HashString , ports )
544- rules = append (rules , rule )
545- log .Printf ("[DEBUG] Added TCP/UDP rule with deprecated ports to state: %+v" , rule )
546-
547- } else if hasPort && portStr != "" {
548- log .Printf ("[DEBUG] Processing single port for TCP/UDP rule: %s" , portStr )
549-
550- id , ok := uuids [portStr ]
551- if ! ok {
552- log .Printf ("[DEBUG] No UUID for port %s, skipping rule" , portStr )
553- continue
554- }
555-
556- r , ok := ruleMap [id .(string )]
557- if ! ok {
558- log .Printf ("[DEBUG] TCP/UDP rule for port %s with ID %s not found, removing UUID" , portStr , id .(string ))
559- delete (uuids , portStr )
560- continue
561- }
562-
563- // Delete the known rule so only unknown rules remain in the ruleMap
564- delete (ruleMap , id .(string ))
565-
566- var cidrs []interface {}
567- for _ , cidr := range strings .Split (r .Cidrlist , "," ) {
568- cidrs = append (cidrs , cidr )
569- }
570-
571- rule ["action" ] = strings .ToLower (r .Action )
572- rule ["protocol" ] = r .Protocol
573- rule ["traffic_type" ] = strings .ToLower (r .Traffictype )
574- rule ["cidr_list" ] = cidrs
575- rule ["port" ] = portStr
576- rules = append (rules , rule )
577- log .Printf ("[DEBUG] Added TCP/UDP rule with single port to state: %+v" , rule )
578-
579- } else {
580- log .Printf ("[DEBUG] Processing TCP/UDP rule with no port specified" )
581-
582- id , ok := uuids ["all_ports" ]
583- if ! ok {
584- log .Printf ("[DEBUG] No UUID for all_ports, skipping rule" )
585- continue
586- }
587-
588- r , ok := ruleMap [id .(string )]
589- if ! ok {
590- log .Printf ("[DEBUG] TCP/UDP rule for all_ports with ID %s not found, removing UUID" , id .(string ))
591- delete (uuids , "all_ports" )
592- continue
593- }
594-
595- delete (ruleMap , id .(string ))
596-
597- var cidrs []interface {}
598- for _ , cidr := range strings .Split (r .Cidrlist , "," ) {
599- cidrs = append (cidrs , cidr )
600- }
601-
602- rule ["action" ] = strings .ToLower (r .Action )
603- rule ["protocol" ] = r .Protocol
604- rule ["traffic_type" ] = strings .ToLower (r .Traffictype )
605- rule ["cidr_list" ] = cidrs
606- rules = append (rules , rule )
607- log .Printf ("[DEBUG] Added TCP/UDP rule with no port to state: %+v" , rule )
608- }
597+ uuids := rule ["uuids" ].(map [string ]interface {})
598+ processTCPUDPRule (rule , ruleMap , uuids , & rules )
609599 }
610600 }
611601 }
0 commit comments