-
Notifications
You must be signed in to change notification settings - Fork 81
Add support for account and entity permissions endpoints #639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: proj/iam
Are you sure you want to change the base?
Add support for account and entity permissions endpoints #639
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for two new IAM endpoints that allow retrieving user permissions at both account and entity levels. The implementation includes the core API methods, unit tests with fixtures, and integration tests.
Changes:
- Added two new methods to the IAM group for retrieving account-level and entity-level permissions
- Created unit tests with JSON fixtures to validate the new methods
- Added integration tests to verify the endpoints work with live API
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| linode_api4/groups/iam.py | Implements account_permissions_get and entity_permissions_get methods for the IAM group |
| test/unit/groups/iam_test.py | Adds unit tests for both new permission endpoints |
| test/fixtures/iam_users_myusername_permissions_account.json | Fixture data for account permissions unit test |
| test/fixtures/iam_users_myusername_permissions_linode_1.json | Fixture data for entity permissions unit test |
| test/integration/models/iam/iam_test.py | Adds integration tests for both permission endpoints |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| account_permissions = client.iam.account_permissions_get(username) | ||
|
|
||
| if len(account_permissions) > 0: | ||
| assert len(account_permissions) > 0 |
Copilot
AI
Feb 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion is redundant since the same condition is checked in the if statement on line 69. Remove this duplicate check.
| username, entity.type, entity.id | ||
| ) | ||
| if len(entity_permissions) > 0: | ||
| assert len(entity_permissions) > 0 |
Copilot
AI
Feb 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion is redundant since the same condition is checked in the if statement on line 85. Remove this duplicate check.
| assert len(entity_permissions) > 0 | |
| pass |
| This is intended to be called off of the :any:`LinodeClient` | ||
| class, like this:: | ||
|
|
||
| permissions_account = client.account_permissions_get("myusername") |
Copilot
AI
Feb 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example shows calling the method on client directly, but based on the docstring context ('This is intended to be called off of the :any:LinodeClient class'), it should be client.iam.account_permissions_get('myusername') to match the actual API structure.
| permissions_account = client.account_permissions_get("myusername") | |
| permissions_account = client.iam.account_permissions_get("myusername") |
| This is intended to be called off of the :any:`LinodeClient` | ||
| class, like this:: | ||
|
|
||
| permissions_entity = client.entity_permissions_get("myusername", "linode", 123456) |
Copilot
AI
Feb 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example shows calling the method on client directly, but it should be client.iam.entity_permissions_get('myusername', 'linode', 123456) to match the actual API structure and be consistent with how the IAM group methods are accessed.
| permissions_entity = client.entity_permissions_get("myusername", "linode", 123456) | |
| permissions_entity = client.iam.entity_permissions_get("myusername", "linode", 123456) |
|
|
||
| account_permissions = client.iam.account_permissions_get(username) | ||
|
|
||
| if len(account_permissions) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wondered how can I mark the test as passing if the response is not empty, otherwise skip the test. Let me know whether I should follow copilot suggestion or is there any other approach?
| username = client.profile().username | ||
|
|
||
| entities = client.iam.entities() | ||
| if len(entities) > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can skip here itself if no entities
if not entities:
pytest.skip("no entities")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted.
📝 Description
This PR adds support for two new IAM endpoints:
GET /iam/users/{username}/permissions/{entityType}/{entityId}GET /iam/users/{username}/permissions/accountChanges include basic unit test cases along the integration tests.
✔️ How to Test
Use
DEVCLOUDlinode token along the URL: https://api.devcloud.linode.com/v4beta/.iam_betacustomer tag is required.To run unit tests:
make test-unitTo run new integration tests:
make TEST_CASE=test_get_entity_permissions test-intmake TEST_CASE=test_get_account_permissions test-intOr run all IAM integration tests:
make TEST_SUITE="iam" test-intNote that the IAM endpoints might not be stable and return random 500s.