Skip to content

Commit 1d31b10

Browse files
IO Ready and new IAM Endpoints (#864)
## πŸ“ Description Adds `io_ready` field to Volumes and 2 new endpoints for IAM ## βœ”οΈ How to Test ``` make test-unit ```
1 parent 52611e3 commit 1d31b10

File tree

9 files changed

+80
-1
lines changed

9 files changed

+80
-1
lines changed

β€Žentities.goβ€Ž

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,25 @@ package linodego
22

33
import "context"
44

5+
// LinodeEntity is anything in Linode with IAM Permissions
56
type LinodeEntity struct {
67
ID int `json:"id"`
78
Label string `json:"label"`
89
Type string `json:"type"`
910
}
1011

12+
// ListEntities returns a paginated list of all entities
1113
func (c *Client) ListEntities(ctx context.Context, opts *ListOptions) ([]LinodeEntity, error) {
1214
return getPaginatedResults[LinodeEntity](ctx, c, "entities", opts)
1315
}
16+
17+
// GetEntityRoles returns a list of roles for the entity and user
18+
func (c *Client) GetEntityRoles(ctx context.Context, username string, entityType string, entityID int) ([]string, error) {
19+
perms, err := doGETRequest[[]string](ctx, c,
20+
formatAPIPath("iam/users/%s/permissions/%s/%d", username, entityType, entityID))
21+
if err != nil || perms == nil {
22+
return nil, err
23+
}
24+
25+
return (*perms), err
26+
}

β€Žiam.goβ€Ž

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,79 @@ package linodego
22

33
import "context"
44

5+
// UserRolePermissions are the account and entity permissions for the User
56
type UserRolePermissions struct {
67
AccountAccess []string `json:"account_access"`
78
EntityAccess []UserAccess `json:"entity_access"`
89
}
910

11+
// GetUpdateOptions converts UserRolePermissions for use in UpdateUserRolePermissions
1012
func (p *UserRolePermissions) GetUpdateOptions() UserRolePermissionsUpdateOptions {
1113
return UserRolePermissionsUpdateOptions{
1214
AccountAccess: p.AccountAccess,
1315
EntityAccess: p.EntityAccess,
1416
}
1517
}
1618

19+
// UserRolePermissionsUpdateOptions are fields accepted by UpdateUserRolePermissions
1720
type UserRolePermissionsUpdateOptions struct {
1821
AccountAccess []string `json:"account_access"`
1922
EntityAccess []UserAccess `json:"entity_access"`
2023
}
2124

25+
// UserAccess is the breakdown of entities Roles
2226
type UserAccess struct {
2327
ID int `json:"id"`
2428
Type string `json:"type"`
2529
Roles []string `json:"roles"`
2630
}
2731

32+
// AccountRolePermissions are the account and entity roles for the Account
2833
type AccountRolePermissions struct {
2934
AccountAccess []AccountAccess `json:"account_access"`
3035
EntityAccess []AccountAccess `json:"entity_access"`
3136
}
3237

38+
// AccountAccess is the Roles for each Type for the Account
3339
type AccountAccess struct {
3440
Type string `json:"type"`
3541
Roles []Role `json:"roles"`
3642
}
3743

44+
// Role is the IAM Role and its Permissions
3845
type Role struct {
3946
Name string `json:"name"`
4047
Description string `json:"description"`
4148
Permissions []string `json:"permissions"`
4249
}
4350

51+
// GetUserRolePermissions returns any role permissions for username
4452
func (c *Client) GetUserRolePermissions(ctx context.Context, username string) (*UserRolePermissions, error) {
4553
return doGETRequest[UserRolePermissions](ctx, c,
4654
formatAPIPath("iam/users/%s/role-permissions", username),
4755
)
4856
}
4957

58+
// UpdateUserRolePermissions updates any role permissions for username
5059
func (c *Client) UpdateUserRolePermissions(ctx context.Context, username string, opts UserRolePermissionsUpdateOptions) (*UserRolePermissions, error) {
5160
return doPUTRequest[UserRolePermissions](ctx, c,
5261
formatAPIPath("iam/users/%s/role-permissions", username),
5362
opts,
5463
)
5564
}
5665

66+
// GetAccountRolePermissions returns the role permissions for this Account
5767
func (c *Client) GetAccountRolePermissions(ctx context.Context) (*AccountRolePermissions, error) {
5868
return doGETRequest[AccountRolePermissions](ctx, c, "iam/role-permissions")
5969
}
70+
71+
// GetUserAccountPermissions returns the account permissions for username
72+
func (c *Client) GetUserAccountPermissions(ctx context.Context, username string) ([]string, error) {
73+
perms, err := doGETRequest[[]string](ctx, c,
74+
formatAPIPath("iam/users/%s/permissions/account", username))
75+
if err != nil || perms == nil {
76+
return nil, err
77+
}
78+
79+
return (*perms), err
80+
}

β€Žtest/unit/entities_test.goβ€Ž

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,19 @@ func TestEntities_List(t *testing.T) {
2323

2424
assert.Equal(t, 7, entities[0].ID)
2525
}
26+
27+
func TestEntitiesPermissions_Get(t *testing.T) {
28+
fixtureData, err := fixtures.GetFixture("entities_permissions")
29+
assert.NoError(t, err)
30+
31+
var base ClientBaseCase
32+
base.SetUp(t)
33+
defer base.TearDown(t)
34+
35+
base.MockGet(formatMockAPIPath("iam/users/Linode/permissions/linode/123"), fixtureData)
36+
37+
perms, err := base.Client.GetEntityRoles(context.Background(), "Linode", "linode", 123)
38+
assert.NoError(t, err)
39+
40+
assert.Equal(t, "rebuild_linode", perms[1])
41+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
"generate_linode_lish_token_remote",
3+
"rebuild_linode",
4+
"shutdown_linode"
5+
]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
"list_events",
3+
"view_account_settings",
4+
"cancel_account"
5+
]

β€Žtest/unit/fixtures/volume_get.jsonβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"hardware_type": "",
1111
"linode_label": "",
1212
"encryption": "",
13+
"io_ready": true,
1314
"created": "2025-01-01T12:00:00",
1415
"updated": "2025-01-10T12:00:00"
1516
}
16-
17+

β€Žtest/unit/iam_test.goβ€Ž

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,19 @@ func TestIAMUserRolePermissions_Update(t *testing.T) {
6161
assert.Equal(t, 1, after.EntityAccess[0].ID)
6262
assert.NotEqual(t, before.AccountAccess, after.AccountAccess)
6363
}
64+
65+
func TestIAMUserAccountPermissions_Get(t *testing.T) {
66+
fixtureData, err := fixtures.GetFixture("iam_user_account_permissions_get")
67+
assert.NoError(t, err)
68+
69+
var base ClientBaseCase
70+
base.SetUp(t)
71+
defer base.TearDown(t)
72+
73+
base.MockGet(formatMockAPIPath("iam/users/Linode/permissions/account"), fixtureData)
74+
75+
perms, err := base.Client.GetUserAccountPermissions(context.Background(), "Linode")
76+
assert.NoError(t, err)
77+
78+
assert.Equal(t, "list_events", perms[0])
79+
}

β€Žtest/unit/volume_test.goβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ func TestGetVolume(t *testing.T) {
5858
assert.Contains(t, volume.Tags, "test", "Expected tags to include 'test'")
5959
assert.Empty(t, volume.HardwareType, "Expected hardware type to be empty")
6060
assert.Empty(t, volume.LinodeLabel, "Expected Linode label to be empty")
61+
assert.Equal(t, true, volume.IOReady, "Expected IO Ready true")
6162
}
6263

6364
func TestCreateVolume(t *testing.T) {

β€Žvolumes.goβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type Volume struct {
3737
Tags []string `json:"tags"`
3838
HardwareType string `json:"hardware_type"`
3939
LinodeLabel string `json:"linode_label"`
40+
IOReady bool `json:"io_ready"`
4041
Created *time.Time `json:"-"`
4142
Updated *time.Time `json:"-"`
4243

0 commit comments

Comments
Β (0)