Skip to content

Conversation

@Keshavrajsinghal
Copy link
Contributor

@Keshavrajsinghal Keshavrajsinghal commented Oct 2, 2025

Description

The Read() method in permissions/resource.go was fetching all permissions for a subject from the API and storing them in Terraform state, causing unmanaged (UI-created / API created) permissions to be deleted when removing the Terraform resource. We now build a map of managed permissions from the existing state and filter API responses to only include those permissions that Terraform originally created.

During import operations however, the state is initially empty, which would cause the managed permissions map to be empty and filter out all permissions from the API response. To handle this, we refactored the API fetching logic into a reusable fetchPermissionsForSubject() helper method and updated ImportState() to populate permissions before Read() is automatically called, ensuring the managed permissions map is correctly initialized with the imported baseline.

Tests

Added two new acceptance tests: TestAccPermissions_ManagedDeletion verifies that removing a Terraform-managed permission resource doesn't delete unmanaged permissions created via the UI or API, and TestAccPermissions_ReadOnlyManaged confirms that the Read() method only tracks managed permissions in state while leaving unmanaged ones intact. Both tests use direct API calls to create unmanaged permissions and verify they persist after Terraform operations.

Note: These tests have been commented out because they rely on direct API calls that do not get recorded. As a result, they fail CD pipelines as they try to bypass the recorder and hit the RETOOL_HOST which is a dummy host set to recorded.retool.dev. They pass with real hosts as tested locally.

@EhudB
Copy link
Contributor

EhudB commented Oct 10, 2025

@Keshavrajsinghal This is a suggestion i haven't fully tested out, but i think that if you add another provider to the acctest.go file, you could use it to send API request without affecting the state of the main provider, thus being able to add changes to the retool instance and also being able to record and replay them.
For reading, i think you will have to implement a data_source for permissions in order to allow the recording to both validate the data returned from retool and record it

@nguyenmp nguyenmp requested a review from simplyluke October 14, 2025 21:35
@simplyluke
Copy link
Contributor

I merged this with main and modified the tests. The tests are less comprehensive than your original but will work with replay. I also tested this with a universal access permission group on a local instance (see the terraform output below) and this seems to be working well. I'm going to accept, but @Keshavrajsinghal can you also review the changes I made prior to merging?

❯ terraform apply
retool_group.admin_group: Preparing import... [id=5]
retool_group.admin_group: Refreshing state... [id=5]

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:

  # retool_folder.example_app_folder will be created
  + resource "retool_folder" "example_app_folder" {
      + folder_type      = "app"
      + id               = (known after apply)
      + is_system_folder = (known after apply)
      + legacy_id        = (known after apply)
      + name             = "Terraform Example App Folder 2"
      + parent_folder_id = "ROOT"
    }

  # retool_group.admin_group will be imported
    resource "retool_group" "admin_group" {
        account_details_access         = false
        audit_log_access               = false
        id                             = "5"
        legacy_id                      = "5"
        name                           = "app_admin_group"
        theme_access                   = false
        universal_app_access           = "own"
        universal_query_library_access = "none"
        universal_resource_access      = "none"
        universal_workflow_access      = "none"
        unpublished_release_access     = false
        usage_analytics_access         = false
        user_list_access               = false
    }

  # retool_group.test_group will be created
  + resource "retool_group" "test_group" {
      + account_details_access         = true
      + audit_log_access               = true
      + id                             = (known after apply)
      + legacy_id                      = (known after apply)
      + name                           = "Test Group"
      + theme_access                   = false
      + universal_app_access           = "use"
      + universal_query_library_access = "none"
      + universal_resource_access      = "none"
      + universal_workflow_access      = "none"
      + unpublished_release_access     = false
      + usage_analytics_access         = true
      + user_list_access               = false
    }

  # retool_permissions.test_permissions will be created
  + resource "retool_permissions" "test_permissions" {
      + permissions = [
          + {
              + access_level = "own"
              + object       = {
                  + id   = (known after apply)
                  + type = "folder"
                }
            },
        ]
      + subject     = {
          + id   = (known after apply)
          + type = "group"
        }
    }

Plan: 1 to import, 3 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

retool_group.admin_group: Importing... [id=5]
retool_group.admin_group: Import complete [id=5]
retool_folder.example_app_folder: Creating...
retool_group.test_group: Creating...
retool_group.test_group: Creation complete after 1s [id=134]
retool_folder.example_app_folder: Creation complete after 1s [id=app_193]
retool_permissions.test_permissions: Creating...
retool_permissions.test_permissions: Creation complete after 0s

Apply complete! Resources: 1 imported, 3 added, 0 changed, 0 destroyed.
❯ terraform plan
retool_folder.example_app_folder: Refreshing state... [id=app_193]
retool_group.admin_group: Refreshing state... [id=5]
retool_group.test_group: Refreshing state... [id=134]
retool_permissions.test_permissions: Refreshing state...

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your
configuration and found no differences, so no changes are needed.
❯

Copy link
Contributor Author

@Keshavrajsinghal Keshavrajsinghal left a comment

Choose a reason for hiding this comment

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

LGTM!

@simplyluke simplyluke merged commit 859066b into main Nov 15, 2025
3 checks passed
@simplyluke simplyluke deleted the add-local-mapping-to-read branch November 15, 2025 00:43
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