Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 23d4b95

Browse files
authored
Add more coder-sdk update, create, and delete operations (#169)
1 parent 7a9addf commit 23d4b95

File tree

7 files changed

+157
-59
lines changed

7 files changed

+157
-59
lines changed

coder-sdk/env.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"net/http"
66
"time"
77

8-
"cdr.dev/coder-cli/internal/x/xjson"
98
"golang.org/x/xerrors"
109
"nhooyr.io/websocket"
1110
"nhooyr.io/websocket/wsjson"
@@ -31,14 +30,14 @@ type Environment struct {
3130
UpdatedAt time.Time `json:"updated_at" table:"-"`
3231
LastOpenedAt time.Time `json:"last_opened_at" table:"-"`
3332
LastConnectionAt time.Time `json:"last_connection_at" table:"-"`
34-
AutoOffThreshold xjson.MSDuration `json:"auto_off_threshold" table:"-"`
33+
AutoOffThreshold Duration `json:"auto_off_threshold" table:"-"`
3534
}
3635

3736
// RebuildMessage defines the message shown when an Environment requires a rebuild for it can be accessed.
3837
type RebuildMessage struct {
39-
Text string `json:"text"`
40-
Required bool `json:"required"`
41-
AutoOffThreshold xjson.MSDuration `json:"auto_off_threshold" table:"-"`
38+
Text string `json:"text"`
39+
Required bool `json:"required"`
40+
AutoOffThreshold Duration `json:"auto_off_threshold"`
4241
}
4342

4443
// EnvironmentStat represents the state of an environment

coder-sdk/error.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ var ErrNotFound = xerrors.Errorf("resource not found")
1414

1515
// APIError is the expected payload format for our errors.
1616
type APIError struct {
17-
Err struct {
18-
Msg string `json:"msg"`
19-
} `json:"error"`
17+
Err APIErrorMsg `json:"error"`
18+
}
19+
20+
// APIErrorMsg contains the rich error information returned by API errors.
21+
type APIErrorMsg struct {
22+
Msg string `json:"msg"`
2023
}
2124

2225
// HTTPError represents an error from the Coder API.

coder-sdk/image.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ type NewRegistryRequest struct {
2626
Password string `json:"password"`
2727
}
2828

29-
// ImportImageRequest is used to import new images and registries into Coder
30-
type ImportImageRequest struct {
29+
// ImportImageReq is used to import new images and registries into Coder
30+
type ImportImageReq struct {
3131
RegistryID *string `json:"registry_id"` // Used to import images to existing registries.
3232
NewRegistry *NewRegistryRequest `json:"new_registry"` // Used when adding a new registry.
3333
Repository string `json:"repository"` // Refers to the image. Ex: "codercom/ubuntu".
@@ -40,7 +40,7 @@ type ImportImageRequest struct {
4040
}
4141

4242
// ImportImage creates a new image and optionally a new registry
43-
func (c Client) ImportImage(ctx context.Context, orgID string, req ImportImageRequest) (*Image, error) {
43+
func (c Client) ImportImage(ctx context.Context, orgID string, req ImportImageReq) (*Image, error) {
4444
var img Image
4545
if err := c.requestBody(ctx, http.MethodPost, "/api/orgs/"+orgID+"/images", req, &img); err != nil {
4646
return nil, err

coder-sdk/org.go

+48-11
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,15 @@ type Organization struct {
1616
// OrganizationUser user wraps the basic User type and adds data specific to the user's membership of an organization
1717
type OrganizationUser struct {
1818
User
19-
OrganizationRoles []OrganizationRole `json:"organization_roles"`
20-
RolesUpdatedAt time.Time `json:"roles_updated_at"`
19+
OrganizationRoles []Role `json:"organization_roles"`
20+
RolesUpdatedAt time.Time `json:"roles_updated_at"`
2121
}
2222

23-
// OrganizationRole defines an organization OrganizationRole
24-
type OrganizationRole string
25-
26-
// The OrganizationRole enum values
23+
// Organization Roles
2724
const (
28-
RoleOrgMember OrganizationRole = "organization-member"
29-
RoleOrgAdmin OrganizationRole = "organization-admin"
30-
RoleOrgManager OrganizationRole = "organization-manager"
25+
RoleOrgMember Role = "organization-member"
26+
RoleOrgAdmin Role = "organization-admin"
27+
RoleOrgManager Role = "organization-manager"
3128
)
3229

3330
// Organizations gets all Organizations
@@ -39,11 +36,51 @@ func (c Client) Organizations(ctx context.Context) ([]Organization, error) {
3936
return orgs, nil
4037
}
4138

42-
// OrgMembers get all members of the given organization
43-
func (c Client) OrgMembers(ctx context.Context, orgID string) ([]OrganizationUser, error) {
39+
func (c Client) OrganizationByID(ctx context.Context, orgID string) (*Organization, error) {
40+
var org Organization
41+
err := c.requestBody(ctx, http.MethodGet, "/api/orgs/"+orgID, nil, &org)
42+
if err != nil {
43+
return nil, err
44+
}
45+
return &org, nil
46+
}
47+
48+
// OrganizationMembers get all members of the given organization
49+
func (c Client) OrganizationMembers(ctx context.Context, orgID string) ([]OrganizationUser, error) {
4450
var members []OrganizationUser
4551
if err := c.requestBody(ctx, http.MethodGet, "/api/orgs/"+orgID+"/members", nil, &members); err != nil {
4652
return nil, err
4753
}
4854
return members, nil
4955
}
56+
57+
type UpdateOrganizationReq struct {
58+
Name *string `json:"name"`
59+
Description *string `json:"description"`
60+
Default *bool `json:"default"`
61+
AutoOffThreshold *Duration `json:"auto_off_threshold"`
62+
CPUProvisioningRate *float32 `json:"cpu_provisioning_rate"`
63+
MemoryProvisioningRate *float32 `json:"memory_provisioning_rate"`
64+
}
65+
66+
func (c Client) UpdateOrganization(ctx context.Context, orgID string, req UpdateOrganizationReq) error {
67+
return c.requestBody(ctx, http.MethodPatch, "/api/orgs/"+orgID, req, nil)
68+
}
69+
70+
type CreateOrganizationReq struct {
71+
Name string `json:"name"`
72+
Description string `json:"description"`
73+
Default bool `json:"default"`
74+
ResourceNamespace string `json:"resource_namespace"`
75+
AutoOffThreshold Duration `json:"auto_off_threshold"`
76+
CPUProvisioningRate float32 `json:"cpu_provisioning_rate"`
77+
MemoryProvisioningRate float32 `json:"memory_provisioning_rate"`
78+
}
79+
80+
func (c Client) CreateOrganization(ctx context.Context, req CreateOrganizationReq) error {
81+
return c.requestBody(ctx, http.MethodPost, "/api/orgs", req, nil)
82+
}
83+
84+
func (c Client) DeleteOrganization(ctx context.Context, orgID string) error {
85+
return c.requestBody(ctx, http.MethodDelete, "/api/orgs/"+orgID, nil, nil)
86+
}

coder-sdk/users.go

+61-6
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,38 @@ import (
88

99
// User describes a Coder user account.
1010
type User struct {
11-
ID string `json:"id" table:"-"`
12-
Email string `json:"email" table:"Email"`
13-
Username string `json:"username" table:"Username"`
14-
Name string `json:"name" table:"Name"`
15-
CreatedAt time.Time `json:"created_at" table:"CreatedAt"`
16-
UpdatedAt time.Time `json:"updated_at" table:"-"`
11+
ID string `json:"id" table:"-"`
12+
Email string `json:"email" table:"Email"`
13+
Username string `json:"username" table:"Username"`
14+
Name string `json:"name" table:"Name"`
15+
Roles []Role `json:"roles" table:"-"`
16+
TemporaryPassword bool `json:"temporary_password" table:"-"`
17+
LoginType string `json:"login_type" table:"-"`
18+
KeyRegeneratedAt time.Time `json:"key_regenerated_at" table:"-"`
19+
CreatedAt time.Time `json:"created_at" table:"CreatedAt"`
20+
UpdatedAt time.Time `json:"updated_at" table:"-"`
1721
}
1822

23+
type Role string
24+
25+
type Roles []Role
26+
27+
// Site Roles
28+
const (
29+
SiteAdmin Role = "site-admin"
30+
SiteAuditor Role = "site-auditor"
31+
SiteManager Role = "site-manager"
32+
SiteMember Role = "site-member"
33+
)
34+
35+
type LoginType string
36+
37+
const (
38+
LoginTypeBuiltIn LoginType = "built-in"
39+
LoginTypeSAML LoginType = "saml"
40+
LoginTypeOIDC LoginType = "oidc"
41+
)
42+
1943
// Me gets the details of the authenticated user.
2044
func (c Client) Me(ctx context.Context) (*User, error) {
2145
return c.UserByID(ctx, Me)
@@ -70,3 +94,34 @@ func (c Client) UserByEmail(ctx context.Context, email string) (*User, error) {
7094
}
7195
return nil, ErrNotFound
7296
}
97+
98+
// UpdateUserReq defines a modification to the user, updating the
99+
// value of all non-nil values.
100+
type UpdateUserReq struct {
101+
// TODO(@cmoog) add update password option
102+
Revoked *bool `json:"revoked,omitempty"`
103+
Roles *Roles `json:"roles,omitempty"`
104+
LoginType *LoginType `json:"login_type,omitempty"`
105+
Name *string `json:"name,omitempty"`
106+
Username *string `json:"username,omitempty"`
107+
Email *string `json:"email,omitempty"`
108+
DotfilesGitURL *string `json:"dotfiles_git_uri,omitempty"`
109+
}
110+
111+
func (c Client) UpdateUser(ctx context.Context, userID string, req UpdateUserReq) error {
112+
return c.requestBody(ctx, http.MethodPatch, "/api/users/"+userID, req, nil)
113+
}
114+
115+
type CreateUserReq struct {
116+
Name string `json:"name"`
117+
Username string `json:"username"`
118+
Email string `json:"email"`
119+
Password string `json:"password"`
120+
TemporaryPassword bool `json:"temporary_password"`
121+
LoginType LoginType `json:"login_type"`
122+
OrganizationsIDs []string `json:"organizations"`
123+
}
124+
125+
func (c Client) CreateUser(ctx context.Context, req CreateUserReq) error {
126+
return c.requestBody(ctx, http.MethodPost, "/api/users", req, nil)
127+
}

coder-sdk/util.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package coder
2+
3+
import (
4+
"encoding/json"
5+
"strconv"
6+
"time"
7+
)
8+
9+
func String(s string) *string {
10+
return &s
11+
}
12+
13+
// Duration is a time.Duration wrapper that marshals to millisecond precision.
14+
// While it looses precision, most javascript applications expect durations to be in milliseconds.
15+
type Duration time.Duration
16+
17+
// MarshalJSON marshals the duration to millisecond precision.
18+
func (d Duration) MarshalJSON() ([]byte, error) {
19+
du := time.Duration(d)
20+
return json.Marshal(du.Milliseconds())
21+
}
22+
23+
// UnmarshalJSON unmarshals a millisecond-precision integer to
24+
// a time.Duration.
25+
func (d *Duration) UnmarshalJSON(b []byte) error {
26+
i, err := strconv.ParseInt(string(b), 10, 64)
27+
if err != nil {
28+
return err
29+
}
30+
31+
*d = Duration(time.Duration(i) * time.Millisecond)
32+
return nil
33+
}
34+
35+
func (d Duration) String() string { return time.Duration(d).String() }

internal/x/xjson/duration.go

-31
This file was deleted.

0 commit comments

Comments
 (0)