Skip to content

Fix role_permission description edits and authoritative drift detection - #350

Merged
sureshanaparti merged 1 commit into
mainfrom
fixup-cloudstack-role-permission
Sep 15, 2026
Merged

sureshanaparti merged 1 commit into
mainfrom
fixup-cloudstack-role-permission

Conversation

@vishesh92

Copy link
Copy Markdown
Member

No description provided.

Copilot AI lite review requested due to automatic review settings September 15, 2026 07:14
@vishesh92 vishesh92 changed the title Fixup cloudstack role permission Fix role_permission description edits and authoritative drift detection Sep 15, 2026
@vishesh92
vishesh92 force-pushed the fixup-cloudstack-role-permission branch from 1903f15 to c17fdbc Compare September 15, 2026 07:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Fix ID-based deletion behavior and move the drift assertion to the correct test step.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Updates CloudStack role-permission reconciliation for description edits, authoritative drift detection, and duplicate-rule validation.

Changes:

  • Reconcile permission description changes.
  • Detect unmanaged permissions in authoritative mode.
  • Add regression and acceptance coverage.
File summaries
File Summary
cloudstack/resource_cloudstack_role_permission.go Updates reconciliation, drift detection, deletion, and validation logic.
cloudstack/resource_cloudstack_role_permission_test.go Adds coverage for description edits, drift detection, and duplicate rules.
Review details

Suppressed comments (2)

cloudstack/resource_cloudstack_role_permission.go:338

  • When an authoritative resource is refreshed, the new Read path writes unmanaged permissions into state with their real IDs. If authoritative is then changed to false, oldPermissions includes those external IDs and this branch treats them as previously managed, deleting them even though non-authoritative mode is supposed to preserve out-of-band permissions. Keep unmanaged state entries distinguishable from managed entries (or otherwise track the prior managed set) before using oldManagedIDs here.
		for oldID := range oldManagedIDs {
			if managedIDSet[oldID] || deleted[oldID] {
				continue
			}
			if rolePermissionsByID[oldID] == nil {
				continue
			}
			if err := deleteCloudStackRolePermission(cs, oldID); err != nil {
				return err

cloudstack/resource_cloudstack_role_permission_test.go:738

  • This assertion is on the initial step, whose create plan is necessarily non-empty; the external permission is added only by Check, after that initial plan. It therefore does not assert that an unchanged configuration produces a non-empty plan from authoritative drift. Move ExpectNonEmptyPlan: true to the second same-config step (and remove it here) so this regression test fails if Read does not surface the externally added permission.
				ExpectNonEmptyPlan: true,
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cloudstack/resource_cloudstack_role_permission.go
@vishesh92
vishesh92 force-pushed the fixup-cloudstack-role-permission branch from c17fdbc to 31664fb Compare September 15, 2026 07:43
@sudo87
sudo87 requested a lite review from Copilot September 15, 2026 08:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment on lines +52 to +54
CustomizeDiff: func(_ context.Context, d *schema.ResourceDiff, _ interface{}) error {
return validateUniqueRolePermissionRules(rolePermissionSpecs(d.Get("permission").([]interface{})))
},
Comment on lines +242 to +249
// Not authoritative: remove only the permissions this resource manages and
// leave anything added outside Terraform in place.
desiredPermissions := rolePermissionSpecs(d.Get("permission").([]interface{}))
for _, rp := range matchCloudStackRolePermissions(rolePermissions, desiredPermissions) {
if rp == nil {
continue
}
used[ruleID] = true
if err := deleteCloudStackRolePermission(cs, ruleID); err != nil {
if err := deleteCloudStackRolePermission(cs, rp.Id); err != nil {
@sureshanaparti

Copy link
Copy Markdown
Contributor

Hi @bddvlpr Can you check/review this PR.

@vishesh92
vishesh92 force-pushed the fixup-cloudstack-role-permission branch from 31664fb to 5a41b76 Compare September 15, 2026 10:16

@sureshanaparti sureshanaparti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clgtm

@kiranchavala kiranchavala left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM tested manually


resource "cloudstack_role" "test" {
  name = "tf-pr350-role"
  type = "User"
}

resource "cloudstack_role_permission" "test" {
  role_id       = cloudstack_role.test.id
  authoritative = true

  permission {
    rule        = "listVirtualMachines"
    permission  = "allow"
    description = "original"
  }
  permission {
    rule        = "listZones"
    permission  = "allow"
    description = "zones"
  }
}
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_role.test will be created
  + resource "cloudstack_role" "test" {
      + description = (known after apply)
      + id          = (known after apply)
      + is_public   = true
      + name        = "tf-pr350-role"
      + type        = "User"
    }

  # cloudstack_role_permission.test will be created
  + resource "cloudstack_role_permission" "test" {
      + authoritative = true
      + id            = (known after apply)
      + role_id       = (known after apply)

      + permission {
          + description = "original"
          + id          = (known after apply)
          + permission  = "allow"
          + rule        = "listVirtualMachines"
        }
      + permission {
          + description = "zones"
          + id          = (known after apply)
          + permission  = "allow"
          + rule        = "listZones"
        }
    }

Plan: 2 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_role.test: Creating...
cloudstack_role.test: Creation complete after 1s [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Creating...
cloudstack_role_permission.test: Creation complete after 2s [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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

Update the description to updated

description = "original-updated"

terraform apply
cloudstack_role.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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_role_permission.test will be updated in-place
  ~ resource "cloudstack_role_permission" "test" {
        id            = "062367a5-8ee9-4534-b87c-128d40d112c7"
        # (2 unchanged attributes hidden)

      ~ permission {
          ~ description = "original" -> "original-updated"
            id          = "75e5a99a-46b0-4c97-bd10-1dcb488bb465"
            # (2 unchanged attributes hidden)
        }

        # (1 unchanged block 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_role_permission.test: Modifying... [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Modifications complete after 2s [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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

authoritative drift

  1. With the above applied, add a permission out of band:
    cmk create rolepermission roleid= rule=listVolumes permission=allow description=external
[root@ref-trl-12298-k-Mr8-suresh-anaparti-mgmt1 ~]#    cmk create rolepermission roleid=062367a5-8ee9-4534-b87c-128d40d112c7 rule=listVolumes permission=allow description=external
Loaded in-built API cache. Failed to read API cache, please run 'sync'.
{
  "rolepermission": {
    "description": "external",
    "id": "0a5feff0-4535-4458-b642-f2243f33f093",
    "permission": "allow",
    "roleid": "062367a5-8ee9-4534-b87c-128d40d112c7",
    "rule": "listVolumes"
  }
}
  1. terraform plan
cloudstack_role.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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_role_permission.test will be updated in-place
  ~ resource "cloudstack_role_permission" "test" {
        id            = "062367a5-8ee9-4534-b87c-128d40d112c7"
        # (2 unchanged attributes hidden)

      - permission {
          - description = "external" -> null
            id          = null
          - permission  = "allow" -> null
          - rule        = "listVolumes" -> null
        }

        # (2 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
  1. Terraform apply
terraform apply 
cloudstack_role.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Refreshing state... [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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_role_permission.test will be updated in-place
  ~ resource "cloudstack_role_permission" "test" {
        id            = "062367a5-8ee9-4534-b87c-128d40d112c7"
        # (2 unchanged attributes hidden)

      - permission {
          - description = "external" -> null
            id          = null
          - permission  = "allow" -> null
          - rule        = "listVolumes" -> null
        }

        # (2 unchanged blocks 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_role_permission.test: Modifying... [id=062367a5-8ee9-4534-b87c-128d40d112c7]
cloudstack_role_permission.test: Modifications complete after 1s [id=062367a5-8ee9-4534-b87c-128d40d112c7]

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

@sureshanaparti sureshanaparti added this to the v0.7.0 milestone Sep 15, 2026
@sureshanaparti
sureshanaparti merged commit 7a9e48b into main Sep 15, 2026
31 checks passed
@sureshanaparti
sureshanaparti deleted the fixup-cloudstack-role-permission branch September 15, 2026 12:33
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