Skip to content

Conversation

@Pearl1594
Copy link
Contributor

This PR attempts to deprecate the usage of "ports" with the introduction of "rule_number" support in the 0.6.0 release.
Caution has been taken to allow backward compatibility for delete operation. However creation of new config and update is disallowed if ports is used. Users will be prompted to migrate to use port parameter.

terraform {
  required_providers {
    cloudstack = {
      source = "hashicorp.com/dev/cloudstack"
    }
  }
}
provider "cloudstack" {
  api_url    = "http://xx.xx.xx.xx:8080/client/api"
  api_key    = "LIN6rqXuaJwMPfGYFh13qDwYz5VNNz1J2J6qIOWcd3oLQOq0WtD4CwRundBL6rzXToa3lQOC_vKjI3nkHtiD8Q"
  secret_key = "R6QPwRUz09TVXBjXNwZk7grTjcPtsFRphH6xhN1oPvnc12YUk296t4KHytg8zRLczDA0X5NsLVi4d8rfMMx3yg"
  timeout    = 1800  # 30 minutes for template registration
}

resource "cloudstack_vpc" "default" {
  name         = "test-vpc"
  cidr         = "10.0.0.0/16"
  vpc_offering = "Default VPC offering"
  zone         = "ref-trl-9522-k-Mol8-kiran-chavala"
}

output "vpc_id" {
   value= cloudstack_vpc.default.id
}


resource "cloudstack_network_acl" "default" {
  name   = "test-acl"
  vpc_id = cloudstack_vpc.default.id
}

output "acl_id" {
   value= cloudstack_network_acl.default.id   
}

resource "cloudstack_network_acl_rule" "default" {
  acl_id = cloudstack_network_acl.default.id

  rule {
    rule_number = 16
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port       = "80-81"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue" 
  }

  rule {
    rule_number  = 17
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "2222-2223"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue - 1" 
  }

  rule {
    rule_number  = 18
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "8080"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue - 2"
  }

  rule {
    rule_number  = 19
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "8081"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue - 3"
  }
}

@Pearl1594 Pearl1594 requested a review from kiranchavala October 8, 2025 21:36
Copy link
Collaborator

@kiranchavala kiranchavala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Tested with port and rule_number able to create and update

resource "cloudstack_network_acl_rule" "test" {
  acl_id = "b70ac793-4bf1-434d-a75d-baf7e959a1c8"


  rule {
    rule_number = 16
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port       = "81-83"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue-new-1" 
  }

  rule {
    rule_number  = 17
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "2222-2223"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue - 2dsg" 
  }

  rule {
    rule_number  = 18
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "8081"
    traffic_type = "ingress"
    description  = "testing terraform ACL issue - 2"
  }

  rule {
    rule_number  = 19
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port        = "8086"
    traffic_type = "Egress"
    description  = "testing terraform ACL issue - 3"
  }
}


terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # cloudstack_network_acl_rule.default will be created
  + resource "cloudstack_network_acl_rule" "default" {
      + acl_id      = "8ad13c5a-700f-467b-ad79-70fd942d3a09"
      + id          = (known after apply)
      + managed     = false
      + parallelism = 2

      + rule {
          + action       = "allow"
          + cidr_list    = [
              + "10.0.0.0/24",
            ]
          + description  = "testing terraform ACL issue"
          + icmp_code    = (known after apply)
          + icmp_type    = (known after apply)
          + port         = "80-81"
          + protocol     = "tcp"
          + rule_number  = 16
          + traffic_type = "ingress"
          + uuids        = (known after apply)
        }
      + rule {
          + action       = "allow"
          + cidr_list    = [
              + "10.0.0.0/24",
            ]
          + description  = "testing terraform ACL issue - 1"
          + icmp_code    = (known after apply)
          + icmp_type    = (known after apply)
          + port         = "2222-2223"
          + protocol     = "tcp"
          + rule_number  = 17
          + traffic_type = "ingress"
          + uuids        = (known after apply)
        }
      + rule {
          + action       = "allow"
          + cidr_list    = [
              + "10.0.0.0/24",
            ]
          + description  = "testing terraform ACL issue - 2"
          + icmp_code    = (known after apply)
          + icmp_type    = (known after apply)
          + port         = "8080"
          + protocol     = "tcp"
          + rule_number  = 18
          + traffic_type = "ingress"
          + uuids        = (known after apply)
        }
      + rule {
          + action       = "allow"
          + cidr_list    = [
              + "10.0.0.0/24",
            ]
          + description  = "testing terraform ACL issue - 3"
          + icmp_code    = (known after apply)
          + icmp_type    = (known after apply)
          + port         = "8081"
          + protocol     = "tcp"
          + rule_number  = 19
          + traffic_type = "ingress"
          + uuids        = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

cloudstack_network_acl_rule.default: Creating...
cloudstack_network_acl_rule.default: Creation complete after 3s [id=8ad13c5a-700f-467b-ad79-70fd942d3a09]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
╭─ ~/Desktop/cloudstack-India-demo/cloudstack-terraform-copy                                                                                                                ✔ ╱ 4s ╱ Azure subscription 1  ╱ 10:50:58 AM 
╰─ terraform apply
cloudstack_network_acl_rule.default: Refreshing state... [id=8ad13c5a-700f-467b-ad79-70fd942d3a09]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # cloudstack_network_acl_rule.default will be updated in-place
  ~ resource "cloudstack_network_acl_rule" "default" {
        id          = "8ad13c5a-700f-467b-ad79-70fd942d3a09"
        # (3 unchanged attributes hidden)

      ~ rule {
          ~ port         = "80-81" -> "80-82"
            # (10 unchanged attributes hidden)
        }
      ~ rule {
          ~ port         = "2222-2223" -> "2222-2225"
            # (10 unchanged attributes hidden)
        }
      ~ rule {
          ~ protocol     = "tcp" -> "udp"
            # (10 unchanged attributes hidden)
        }
      ~ rule {
          ~ description  = "testing terraform ACL issue - 3" -> "testing terraform ACL issue - 4"
            # (10 unchanged attributes hidden)
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

cloudstack_network_acl_rule.default: Modifying... [id=8ad13c5a-700f-467b-ad79-70fd942d3a09]
cloudstack_network_acl_rule.default: Modifications complete after 4s [id=8ad13c5a-700f-467b-ad79-70fd942d3a09]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

When ports is mentioned in the terraform config , warning and exception is thrown


Plan: 1 to add, 0 to change, 0 to destroy.
╷
│ Warning: Argument is deprecated
│ 
│   with cloudstack_network_acl_rule.default,
│   on main.tf line 18, in resource "cloudstack_network_acl_rule" "default":
│   18:     ports       =  ["80", "1000-2000"]
│ 
│ Use 'port' instead. The 'ports' field is deprecated and will be removed in a future version.
│ 
│ (and 5 more similar warnings elsewhere)
╵

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

cloudstack_network_acl_rule.default: Creating...
╷
│ Warning: Argument is deprecated
│ 
│   with cloudstack_network_acl_rule.default,
│   on main.tf line 18, in resource "cloudstack_network_acl_rule" "default":
│   18:     ports       =  ["80", "1000-2000"]
│ 
│ Use 'port' instead. The 'ports' field is deprecated and will be removed in a future version.
│ 
│ (and 2 more similar warnings elsewhere)
╵
╷
│ Error: 3 errors occurred:
│       * rule #1: The 'ports' field is deprecated. Use 'port' instead for new configurations.
│       * rule #2: The 'ports' field is deprecated. Use 'port' instead for new configurations.
│       * rule #3: The 'ports' field is deprecated. Use 'port' instead for new configurations.
│ 
│ 
│ 
│   with cloudstack_network_acl_rule.default,
│   on main.tf line 10, in resource "cloudstack_network_acl_rule" "default":
│   10: resource "cloudstack_network_acl_rule" "default" {

@kiranchavala
Copy link
Collaborator

@Pearl1594 can you update the documentation to use port

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clgtm generally

return err
}

// Create all rules that are configured
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CodeBleu , this is an example of what I meant earlier. The comment above can be the name of a method that contains the if-else block below. That would make it easier to read and maintain. Again, this is not due to this PR but changing it would make the code more readable.

@Pearl1594
Copy link
Contributor Author

I've addressed your comments @DaanHoogland . Thanks.

@kiranchavala kiranchavala merged commit e53f30c into main Oct 10, 2025
47 checks passed
@DaanHoogland DaanHoogland deleted the fix-acl-ports branch October 13, 2025 10:17
@DaanHoogland DaanHoogland modified the milestones: v0.7.0, v0.6.0 Oct 13, 2025
@CodeBleu
Copy link
Collaborator

CodeBleu commented Oct 14, 2025

@Pearl1594 I'm having issues with using rule numbers.

│ Error: 6 errors occurred:
│       * rule #1: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 1 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675
│       * rule #2: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 2 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675
│       * rule #3: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 3 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675
│       * rule #4: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 4 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675
│       * rule #5: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 5 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675
│       * rule #6: CloudStack API error 431 (CSExceptionErrorCode: 4350): ACL item with number 6 already exists in ACL: 43b2ba94-7bab-46e0-a1fd-5425cd77d675

I using managed as true and putting a rule_number on all rules.

My rules don't match, and even when I run plan again, it shows 1 change for the ACL with all of the rules listed again, even though they are in CS ( partially )

UPDATE
I had to delete all my rules, and change things to use port instead of ports and it finally applied and doing another plan comes back correct.

This is prob going to be an issue for users when they use the new provider and it detects these changes and doesn't apply them correctly initially and have to delete all their rules and re-apply

I tried to just change the description on one of the rules and it shows this:

   # cloudstack_network_acl_rule.test-acl-rules will be updated in-place
  ~ resource "cloudstack_network_acl_rule" "test-acl-rules" {
        id          = "43b2ba94-7bab-46e0-a1fd-5425cd77d675"
        # (3 unchanged attributes hidden)

      ~ rule {
          ~ description  = "VPN Network" -> "VPN Network Stuff"
            # (9 unchanged attributes hidden)
        }

        # (6 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

It applies, but it never updated my rule
image

If I create a new rule and don't give it a rule_number, then go back and change the description it works. There is something wrong with updating things when you create rules with rule_number specified apparently.


  # cloudstack_network_acl_rule.test-acl-rules will be updated in-place
  ~ resource "cloudstack_network_acl_rule" "test-acl-rules" {
        id          = "43b2ba94-7bab-46e0-a1fd-5425cd77d675"
        # (3 unchanged attributes hidden)

      + rule {
          + action       = "allow"
          + cidr_list    = [
              + "1.1.1.1/32",
            ]
          + description  = "Test rule"
          + port         = "11"
          + protocol     = "tcp"
          + traffic_type = "ingress"
          + uuids        = (known after apply)
        }

        # (7 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Then I change description ( notice not rule_number above was not specified )

OpenTofu will perform the following actions:

  # cloudstack_network_acl_rule.test-acl-rules will be updated in-place
  ~ resource "cloudstack_network_acl_rule" "test-acl-rules" {
        id          = "43b2ba94-7bab-46e0-a1fd-5425cd77d675"
        # (3 unchanged attributes hidden)

      ~ rule {
          ~ description  = "Test rule" -> "Test rule test"
            # (10 unchanged attributes hidden)
        }

        # (7 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

and after apply

image

@CodeBleu
Copy link
Collaborator

CodeBleu commented Oct 14, 2025

@Pearl1594 After further testing it appears that updating the Description on rule 1, does not work.

I deleted all my rules again and created them all with no rule_number specified. I then went to update rule 1 and TF shows correct in plan and apply shows change, but it does not update rule 1

I then tested on the next 2 or 3 rules after 1 and they all work and update in CS like they are supposed to.

@CodeBleu
Copy link
Collaborator

@Pearl1594 I decided to change a rule_number on one of the rules that was created with TF and not specifying a rule_number

The rule_number it gave the rule was 4. I changed my TF on that rule to actually add a rule_number
rule_number = 8, so it would put it after my last rule_number (which is 7 ) and the TF plan shows that it's trying to change rule_number 0 instead!! NOT GOOD

image

      ~ rule {
          ~ rule_number  = 0 -> 8
            # (9 unchanged attributes hidden)
        }

@Pearl1594
Copy link
Contributor Author

Let me check these @CodeBleu. Thanks for reporting.

@Pearl1594
Copy link
Contributor Author

@CodeBleu I was testing you observation, by first creating ACL rules using the previous version 0.5.0

resource "cloudstack_network_acl_rule" "default" {
  acl_id = cloudstack_network_acl.default.id

  rule {
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    ports        = ["80-81", "8080", "443", "2222-2224"]
    traffic_type = "ingress"
  }
}

After moving to the latest release, now 0.6.0-rc3, we first would have to delete the ports as you mentioned and then re-add the rules using port. This was done because we cannot use ports and rule_number together.
Once ports are deleted, re-add them following the new schema (i.e, using port)

resource "cloudstack_network_acl_rule" "default" {
  acl_id = cloudstack_network_acl.default.id

  rule {
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port         = "80-81"
    traffic_type = "ingress"
    rule_number  = 7
  }

  rule {
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port         = "8080"
    traffic_type = "ingress"
  }

  rule {
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port         = "443"
    traffic_type = "ingress"
    rule_number  = 5
  }

  rule {
    action       = "allow"
    cidr_list    = ["10.0.0.0/24"]
    protocol     = "tcp"
    port         = "2222-2224"
    traffic_type = "ingress"
  }
}


This resulted in the following order in ACS
80-81 -> rule_number: 1
8080 -> rule_number: 2
443 -> rule_number: 5
2222 - 2224 -> rule_number: 6

At this point, in the terraform.tfstate file the rule_numbers for all rules except 443 is 0 (here is where the issue lies, as the read function isn't storing the rule number in the state) however since 443 had the rule_number explicitly set in the config, it gets updated, which is why went I on to change the rule number of the ACL rule for port 80-81 (which is currently 1) to 7, and it identified the change as 0 -> 7 , which is what you observed as well.

And the resultant list of ACL rules on ACS looks like:

image

So yes, there seems to be an issue, but do you think it's a blocker? I believe if all acl rules have rule number set we can work around the issue observed.

@CodeBleu
Copy link
Collaborator

So yes, there seems to be an issue, but do you think it's a blocker? I believe if all acl rules have rule_number set we can work around the issue observed.

@Pearl1594

The fact that the TF will change the wrong rule_number seems like a big concern to me. I just feel like I should have been able to split up my ports to a port rules and add rule_number to them and it work. When I initially did this, it caused several issues until I had to delete all my rules and create them new. Then I wanted to update my rule_number on a rule to move it, and it was going to change the wrong thing. Then not being able to update the description ( didn't try other things) on rule_number 1 stinks. The combination of these issues just makes me feel like it needs more work is all 😞

Also, did you see my other issues ( rule_number 1 not updating issue)

@Pearl1594
Copy link
Contributor Author

I wasn't able to reproduce the issue where in the rule isn't updated though the plan indicates otherwise.
I have created a PR: #245 to handle the issue wrt it showing the wrong rule number being updated. However, though it shows updating rule number 0 to x where x is the value set by the user, it does update the correct rule in my observation.

It would be great if you could help verify if the PR addresses the rule number issue. Thanks

@CodeBleu
Copy link
Collaborator

I wasn't able to reproduce the issue where in the rule isn't updated though the plan indicates otherwise. I have created a PR: #245 to handle the issue wrt it showing the wrong rule number being updated. However, though it shows updating rule number 0 to x where x is the value set by the user, it does update the correct rule in my observation.

It would be great if you could help verify if the PR addresses the rule number issue. Thanks

I have tested and left my results on #245

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants