Skip to content

Commit cb33e3e

Browse files
committed
SCALRCORE-21783 Add ServiceAccountTokens service
1 parent a859777 commit cb33e3e

File tree

8 files changed

+248
-47
lines changed

8 files changed

+248
-47
lines changed

access_token.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,25 @@ type AccessToken struct {
3737
Token string `jsonapi:"attr,token"`
3838
}
3939

40+
// AccessTokenListOptions represents the options for listing access tokens.
41+
type AccessTokenListOptions struct {
42+
ListOptions
43+
}
44+
45+
// AccessTokenCreateOptions represents the options for creating a new AccessToken.
46+
type AccessTokenCreateOptions struct {
47+
// For internal use only!
48+
ID string `jsonapi:"primary,access-tokens"`
49+
50+
Description *string `jsonapi:"attr,description,omitempty"`
51+
}
52+
4053
// AccessTokenUpdateOptions represents the options for updating an AccessToken.
4154
type AccessTokenUpdateOptions struct {
42-
ID string `jsonapi:"primary,access-tokens"`
43-
Description *string `jsonapi:"attr,description"`
55+
// For internal use only!
56+
ID string `jsonapi:"primary,access-tokens"`
57+
58+
Description *string `jsonapi:"attr,description,omitempty"`
4459
}
4560

4661
// Update is used to update an AccessToken.

access_token_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func TestAccessTokenDelete(t *testing.T) {
5757
err := client.AccessTokens.Delete(ctx, apt.ID)
5858
require.NoError(t, err)
5959

60-
l, err := client.AgentPoolTokens.List(ctx, ap.ID, AgentPoolTokenListOptions{})
60+
l, err := client.AgentPoolTokens.List(ctx, ap.ID, AccessTokenListOptions{})
6161
assert.Len(t, l.Items, 0)
6262
})
6363

agent_pool_token.go

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"net/url"
7-
"time"
87
)
98

109
// Compile-time proof of interface implementation.
@@ -13,48 +12,23 @@ var _ AgentPoolTokens = (*agentPoolTokens)(nil)
1312
// AgentPoolTokens describes all the access token related methods that the
1413
// Scalr IACP API supports.
1514
type AgentPoolTokens interface {
16-
List(ctx context.Context, agentPoolID string, options AgentPoolTokenListOptions) (*AgentPoolTokenList, error)
17-
Create(ctx context.Context, agentPoolID string, options AgentPoolTokenCreateOptions) (*AgentPoolToken, error)
15+
List(ctx context.Context, agentPoolID string, options AccessTokenListOptions) (*AccessTokenList, error)
16+
Create(ctx context.Context, agentPoolID string, options AccessTokenCreateOptions) (*AccessToken, error)
1817
}
1918

2019
// agentPoolTokens implements AgentPoolTokens.
2120
type agentPoolTokens struct {
2221
client *Client
2322
}
2423

25-
// AgentPoolTokenList represents a list of agent pools.
26-
type AgentPoolTokenList struct {
27-
*Pagination
28-
Items []*AgentPoolToken
29-
}
30-
31-
// AgentPoolToken represents a Scalr agent pool.
32-
type AgentPoolToken struct {
33-
ID string `jsonapi:"primary,access-tokens"`
34-
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
35-
Description string `jsonapi:"attr,description"`
36-
Token string `jsonapi:"attr,token"`
37-
}
38-
39-
// AgentPoolTokenCreateOptions represents the options for creating a new AgentPoolToken.
40-
type AgentPoolTokenListOptions struct {
41-
ListOptions
42-
}
43-
44-
// AgentPoolTokenCreateOptions represents the options for creating a new AgentPoolToken.
45-
type AgentPoolTokenCreateOptions struct {
46-
ID string `jsonapi:"primary,access-tokens"`
47-
Description *string `jsonapi:"attr,description,omitempty"`
48-
}
49-
50-
// List all the agent pools.
51-
func (s *agentPoolTokens) List(ctx context.Context, agentPoolID string, options AgentPoolTokenListOptions) (*AgentPoolTokenList, error) {
24+
// List all the agent pool's tokens.
25+
func (s *agentPoolTokens) List(ctx context.Context, agentPoolID string, options AccessTokenListOptions) (*AccessTokenList, error) {
5226
req, err := s.client.newRequest("GET", fmt.Sprintf("agent-pools/%s/access-tokens", url.QueryEscape(agentPoolID)), &options)
5327
if err != nil {
5428
return nil, err
5529
}
5630

57-
tl := &AgentPoolTokenList{}
31+
tl := &AccessTokenList{}
5832
err = s.client.do(ctx, req, tl)
5933
if err != nil {
6034
return nil, err
@@ -63,8 +37,8 @@ func (s *agentPoolTokens) List(ctx context.Context, agentPoolID string, options
6337
return tl, nil
6438
}
6539

66-
// Create is used to create a new AgentPoolToken.
67-
func (s *agentPoolTokens) Create(ctx context.Context, agentPoolID string, options AgentPoolTokenCreateOptions) (*AgentPoolToken, error) {
40+
// Create is used to create a new AccessToken for AgentPool.
41+
func (s *agentPoolTokens) Create(ctx context.Context, agentPoolID string, options AccessTokenCreateOptions) (*AccessToken, error) {
6842

6943
// Make sure we don't send a user provided ID.
7044
options.ID = ""
@@ -78,7 +52,7 @@ func (s *agentPoolTokens) Create(ctx context.Context, agentPoolID string, option
7852
return nil, err
7953
}
8054

81-
agentPoolToken := &AgentPoolToken{}
55+
agentPoolToken := &AccessToken{}
8256
err = s.client.do(ctx, req, agentPoolToken)
8357
if err != nil {
8458
return nil, err

agent_pool_token_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ func TestAgentPoolTokenList(t *testing.T) {
2020
defer aptCleanup()
2121

2222
t.Run("with valid agent pool", func(t *testing.T) {
23-
tList, err := client.AgentPoolTokens.List(ctx, ap.ID, AgentPoolTokenListOptions{})
23+
tList, err := client.AgentPoolTokens.List(ctx, ap.ID, AccessTokenListOptions{})
2424
require.NoError(t, err)
2525
assert.Len(t, tList.Items, 1)
2626
assert.Equal(t, tList.Items[0].ID, apt.ID)
2727
})
2828
t.Run("with nonexistent agent pool", func(t *testing.T) {
29-
_, err := client.AgentPoolTokens.List(ctx, "ap-123", AgentPoolTokenListOptions{})
29+
_, err := client.AgentPoolTokens.List(ctx, "ap-123", AccessTokenListOptions{})
3030
assert.Equal(
3131
t,
3232
ResourceNotFoundError{
@@ -45,15 +45,15 @@ func TestAgentPoolTokenCreate(t *testing.T) {
4545
defer apCleanup()
4646

4747
t.Run("when description is provided", func(t *testing.T) {
48-
options := AgentPoolTokenCreateOptions{
48+
options := AccessTokenCreateOptions{
4949
Description: String("provider tests token"),
5050
}
5151

5252
apToken, err := client.AgentPoolTokens.Create(ctx, ap.ID, options)
5353
require.NoError(t, err)
5454

5555
// Get a refreshed view from the API.
56-
aptList, err := client.AgentPoolTokens.List(ctx, ap.ID, AgentPoolTokenListOptions{})
56+
aptList, err := client.AgentPoolTokens.List(ctx, ap.ID, AccessTokenListOptions{})
5757
require.NoError(t, err)
5858

5959
refreshed := aptList.Items[0]
@@ -66,12 +66,12 @@ func TestAgentPoolTokenCreate(t *testing.T) {
6666
})
6767

6868
t.Run("when description is not provided", func(t *testing.T) {
69-
options := AgentPoolTokenCreateOptions{}
69+
options := AccessTokenCreateOptions{}
7070
apToken, err := client.AgentPoolTokens.Create(ctx, ap.ID, options)
7171
require.NoError(t, err)
7272

7373
// Get a refreshed view from the API.
74-
aptList, err := client.AgentPoolTokens.List(ctx, ap.ID, AgentPoolTokenListOptions{})
74+
aptList, err := client.AgentPoolTokens.List(ctx, ap.ID, AccessTokenListOptions{})
7575
require.NoError(t, err)
7676

7777
refreshed := aptList.Items[0]
@@ -85,7 +85,7 @@ func TestAgentPoolTokenCreate(t *testing.T) {
8585

8686
t.Run("with nonexistent pool id", func(t *testing.T) {
8787
var apID = "ap-234"
88-
_, err := client.AgentPoolTokens.Create(ctx, apID, AgentPoolTokenCreateOptions{})
88+
_, err := client.AgentPoolTokens.Create(ctx, apID, AccessTokenCreateOptions{})
8989
assert.Equal(
9090
t,
9191
ResourceNotFoundError{
@@ -97,7 +97,7 @@ func TestAgentPoolTokenCreate(t *testing.T) {
9797

9898
t.Run("with invalid pool id", func(t *testing.T) {
9999
apID := badIdentifier
100-
ap, err := client.AgentPoolTokens.Create(ctx, apID, AgentPoolTokenCreateOptions{})
100+
ap, err := client.AgentPoolTokens.Create(ctx, apID, AccessTokenCreateOptions{})
101101
assert.Nil(t, ap)
102102
assert.EqualError(t, err, fmt.Sprintf("invalid value for agent pool ID: '%s'", apID))
103103

helper_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ func createAgentPool(t *testing.T, client *Client) (*AgentPool, func()) {
6363
}
6464
}
6565

66-
func createAgentPoolToken(t *testing.T, client *Client, poolID string) (*AgentPoolToken, func()) {
66+
func createAgentPoolToken(t *testing.T, client *Client, poolID string) (*AccessToken, func()) {
6767
ctx := context.Background()
68-
apt, err := client.AgentPoolTokens.Create(ctx, poolID, AgentPoolTokenCreateOptions{Description: String("provider test token")})
68+
apt, err := client.AgentPoolTokens.Create(ctx, poolID, AccessTokenCreateOptions{Description: String("provider test token")})
6969
if err != nil {
7070
t.Fatal(err)
7171
}
@@ -442,6 +442,24 @@ func createServiceAccount(
442442
}
443443
}
444444

445+
func createServiceAccountToken(t *testing.T, client *Client, serviceAccountID string) (*AccessToken, func()) {
446+
ctx := context.Background()
447+
sat, err := client.ServiceAccountTokens.Create(
448+
ctx, serviceAccountID, AccessTokenCreateOptions{Description: String("tst-description-" + randomString(t))},
449+
)
450+
if err != nil {
451+
t.Fatal(err)
452+
}
453+
454+
return sat, func() {
455+
if err := client.AccessTokens.Delete(ctx, sat.ID); err != nil {
456+
t.Errorf("Error destroying service account token! WARNING: Dangling resources\n"+
457+
"may exist! The full error is shown below.\n\n"+
458+
"Service account token: %s\nError: %s", sat.ID, err)
459+
}
460+
}
461+
}
462+
445463
func assignTagsToWorkspace(t *testing.T, client *Client, workspace *Workspace, tags []*Tag) {
446464
ctx := context.Background()
447465
tagRels := make([]*TagRelation, len(tags))

scalr.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ type Client struct {
136136
Roles Roles
137137
RunTriggers RunTriggers
138138
Runs Runs
139+
ServiceAccountTokens ServiceAccountTokens
139140
ServiceAccounts ServiceAccounts
140141
Tags Tags
141142
Teams Teams
@@ -232,6 +233,7 @@ func NewClient(cfg *Config) (*Client, error) {
232233
client.Roles = &roles{client: client}
233234
client.RunTriggers = &runTriggers{client: client}
234235
client.Runs = &runs{client: client}
236+
client.ServiceAccountTokens = &serviceAccountTokens{client: client}
235237
client.ServiceAccounts = &serviceAccounts{client: client}
236238
client.Tags = &tags{client: client}
237239
client.Teams = &teams{client: client}

service_account_token.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package scalr
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/url"
8+
)
9+
10+
// Compile-time proof of interface implementation.
11+
var _ ServiceAccountTokens = (*serviceAccountTokens)(nil)
12+
13+
// ServiceAccountTokens describes all the access token related methods that the
14+
// Scalr IACP API supports.
15+
type ServiceAccountTokens interface {
16+
// List service account's access tokens
17+
List(ctx context.Context, serviceAccountID string, options AccessTokenListOptions) (*AccessTokenList, error)
18+
// Create new access token for service account
19+
Create(ctx context.Context, serviceAccountID string, options AccessTokenCreateOptions) (*AccessToken, error)
20+
}
21+
22+
// serviceAccountTokens implements ServiceAccountTokens.
23+
type serviceAccountTokens struct {
24+
client *Client
25+
}
26+
27+
// List the access tokens of ServiceAccount.
28+
func (s *serviceAccountTokens) List(
29+
ctx context.Context, serviceAccountID string, options AccessTokenListOptions,
30+
) (*AccessTokenList, error) {
31+
req, err := s.client.newRequest(
32+
"GET",
33+
fmt.Sprintf("service-accounts/%s/access-tokens", url.QueryEscape(serviceAccountID)),
34+
&options,
35+
)
36+
if err != nil {
37+
return nil, err
38+
}
39+
40+
atl := &AccessTokenList{}
41+
err = s.client.do(ctx, req, atl)
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
return atl, nil
47+
}
48+
49+
// Create is used to create a new AccessToken for ServiceAccount.
50+
func (s *serviceAccountTokens) Create(
51+
ctx context.Context, serviceAccountID string, options AccessTokenCreateOptions,
52+
) (*AccessToken, error) {
53+
54+
// Make sure we don't send a user provided ID.
55+
options.ID = ""
56+
57+
if !validStringID(&serviceAccountID) {
58+
return nil, errors.New("invalid value for service account ID")
59+
}
60+
61+
req, err := s.client.newRequest(
62+
"POST",
63+
fmt.Sprintf("service-accounts/%s/access-tokens", url.QueryEscape(serviceAccountID)),
64+
&options,
65+
)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
at := &AccessToken{}
71+
err = s.client.do(ctx, req, at)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
return at, nil
77+
}

0 commit comments

Comments
 (0)