From 84a4c7158b4388fab4b321080193334b8e6528d9 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Mon, 2 Nov 2020 18:05:40 -0600 Subject: [PATCH] Add more coder-sdk update, create, and delete operations --- coder-sdk/env.go | 9 +++-- coder-sdk/error.go | 9 +++-- coder-sdk/image.go | 6 ++-- coder-sdk/org.go | 59 +++++++++++++++++++++++++------ coder-sdk/users.go | 67 ++++++++++++++++++++++++++++++++---- coder-sdk/util.go | 35 +++++++++++++++++++ internal/x/xjson/duration.go | 31 ----------------- 7 files changed, 157 insertions(+), 59 deletions(-) create mode 100644 coder-sdk/util.go delete mode 100644 internal/x/xjson/duration.go diff --git a/coder-sdk/env.go b/coder-sdk/env.go index a15f1caa..42bb6467 100644 --- a/coder-sdk/env.go +++ b/coder-sdk/env.go @@ -5,7 +5,6 @@ import ( "net/http" "time" - "cdr.dev/coder-cli/internal/x/xjson" "golang.org/x/xerrors" "nhooyr.io/websocket" "nhooyr.io/websocket/wsjson" @@ -31,14 +30,14 @@ type Environment struct { UpdatedAt time.Time `json:"updated_at" table:"-"` LastOpenedAt time.Time `json:"last_opened_at" table:"-"` LastConnectionAt time.Time `json:"last_connection_at" table:"-"` - AutoOffThreshold xjson.MSDuration `json:"auto_off_threshold" table:"-"` + AutoOffThreshold Duration `json:"auto_off_threshold" table:"-"` } // RebuildMessage defines the message shown when an Environment requires a rebuild for it can be accessed. type RebuildMessage struct { - Text string `json:"text"` - Required bool `json:"required"` - AutoOffThreshold xjson.MSDuration `json:"auto_off_threshold" table:"-"` + Text string `json:"text"` + Required bool `json:"required"` + AutoOffThreshold Duration `json:"auto_off_threshold"` } // EnvironmentStat represents the state of an environment diff --git a/coder-sdk/error.go b/coder-sdk/error.go index 91ebfa30..2b312378 100644 --- a/coder-sdk/error.go +++ b/coder-sdk/error.go @@ -14,9 +14,12 @@ var ErrNotFound = xerrors.Errorf("resource not found") // APIError is the expected payload format for our errors. type APIError struct { - Err struct { - Msg string `json:"msg"` - } `json:"error"` + Err APIErrorMsg `json:"error"` +} + +// APIErrorMsg contains the rich error information returned by API errors. +type APIErrorMsg struct { + Msg string `json:"msg"` } // HTTPError represents an error from the Coder API. diff --git a/coder-sdk/image.go b/coder-sdk/image.go index c9122cc9..edeecabf 100644 --- a/coder-sdk/image.go +++ b/coder-sdk/image.go @@ -26,8 +26,8 @@ type NewRegistryRequest struct { Password string `json:"password"` } -// ImportImageRequest is used to import new images and registries into Coder -type ImportImageRequest struct { +// ImportImageReq is used to import new images and registries into Coder +type ImportImageReq struct { RegistryID *string `json:"registry_id"` // Used to import images to existing registries. NewRegistry *NewRegistryRequest `json:"new_registry"` // Used when adding a new registry. Repository string `json:"repository"` // Refers to the image. Ex: "codercom/ubuntu". @@ -40,7 +40,7 @@ type ImportImageRequest struct { } // ImportImage creates a new image and optionally a new registry -func (c Client) ImportImage(ctx context.Context, orgID string, req ImportImageRequest) (*Image, error) { +func (c Client) ImportImage(ctx context.Context, orgID string, req ImportImageReq) (*Image, error) { var img Image if err := c.requestBody(ctx, http.MethodPost, "/api/orgs/"+orgID+"/images", req, &img); err != nil { return nil, err diff --git a/coder-sdk/org.go b/coder-sdk/org.go index e3fe4583..0caa9d18 100644 --- a/coder-sdk/org.go +++ b/coder-sdk/org.go @@ -16,18 +16,15 @@ type Organization struct { // OrganizationUser user wraps the basic User type and adds data specific to the user's membership of an organization type OrganizationUser struct { User - OrganizationRoles []OrganizationRole `json:"organization_roles"` - RolesUpdatedAt time.Time `json:"roles_updated_at"` + OrganizationRoles []Role `json:"organization_roles"` + RolesUpdatedAt time.Time `json:"roles_updated_at"` } -// OrganizationRole defines an organization OrganizationRole -type OrganizationRole string - -// The OrganizationRole enum values +// Organization Roles const ( - RoleOrgMember OrganizationRole = "organization-member" - RoleOrgAdmin OrganizationRole = "organization-admin" - RoleOrgManager OrganizationRole = "organization-manager" + RoleOrgMember Role = "organization-member" + RoleOrgAdmin Role = "organization-admin" + RoleOrgManager Role = "organization-manager" ) // Organizations gets all Organizations @@ -39,11 +36,51 @@ func (c Client) Organizations(ctx context.Context) ([]Organization, error) { return orgs, nil } -// OrgMembers get all members of the given organization -func (c Client) OrgMembers(ctx context.Context, orgID string) ([]OrganizationUser, error) { +func (c Client) OrganizationByID(ctx context.Context, orgID string) (*Organization, error) { + var org Organization + err := c.requestBody(ctx, http.MethodGet, "/api/orgs/"+orgID, nil, &org) + if err != nil { + return nil, err + } + return &org, nil +} + +// OrganizationMembers get all members of the given organization +func (c Client) OrganizationMembers(ctx context.Context, orgID string) ([]OrganizationUser, error) { var members []OrganizationUser if err := c.requestBody(ctx, http.MethodGet, "/api/orgs/"+orgID+"/members", nil, &members); err != nil { return nil, err } return members, nil } + +type UpdateOrganizationReq struct { + Name *string `json:"name"` + Description *string `json:"description"` + Default *bool `json:"default"` + AutoOffThreshold *Duration `json:"auto_off_threshold"` + CPUProvisioningRate *float32 `json:"cpu_provisioning_rate"` + MemoryProvisioningRate *float32 `json:"memory_provisioning_rate"` +} + +func (c Client) UpdateOrganization(ctx context.Context, orgID string, req UpdateOrganizationReq) error { + return c.requestBody(ctx, http.MethodPatch, "/api/orgs/"+orgID, req, nil) +} + +type CreateOrganizationReq struct { + Name string `json:"name"` + Description string `json:"description"` + Default bool `json:"default"` + ResourceNamespace string `json:"resource_namespace"` + AutoOffThreshold Duration `json:"auto_off_threshold"` + CPUProvisioningRate float32 `json:"cpu_provisioning_rate"` + MemoryProvisioningRate float32 `json:"memory_provisioning_rate"` +} + +func (c Client) CreateOrganization(ctx context.Context, req CreateOrganizationReq) error { + return c.requestBody(ctx, http.MethodPost, "/api/orgs", req, nil) +} + +func (c Client) DeleteOrganization(ctx context.Context, orgID string) error { + return c.requestBody(ctx, http.MethodDelete, "/api/orgs/"+orgID, nil, nil) +} diff --git a/coder-sdk/users.go b/coder-sdk/users.go index e988a697..6117bace 100644 --- a/coder-sdk/users.go +++ b/coder-sdk/users.go @@ -8,14 +8,38 @@ import ( // User describes a Coder user account. type User struct { - ID string `json:"id" table:"-"` - Email string `json:"email" table:"Email"` - Username string `json:"username" table:"Username"` - Name string `json:"name" table:"Name"` - CreatedAt time.Time `json:"created_at" table:"CreatedAt"` - UpdatedAt time.Time `json:"updated_at" table:"-"` + ID string `json:"id" table:"-"` + Email string `json:"email" table:"Email"` + Username string `json:"username" table:"Username"` + Name string `json:"name" table:"Name"` + Roles []Role `json:"roles" table:"-"` + TemporaryPassword bool `json:"temporary_password" table:"-"` + LoginType string `json:"login_type" table:"-"` + KeyRegeneratedAt time.Time `json:"key_regenerated_at" table:"-"` + CreatedAt time.Time `json:"created_at" table:"CreatedAt"` + UpdatedAt time.Time `json:"updated_at" table:"-"` } +type Role string + +type Roles []Role + +// Site Roles +const ( + SiteAdmin Role = "site-admin" + SiteAuditor Role = "site-auditor" + SiteManager Role = "site-manager" + SiteMember Role = "site-member" +) + +type LoginType string + +const ( + LoginTypeBuiltIn LoginType = "built-in" + LoginTypeSAML LoginType = "saml" + LoginTypeOIDC LoginType = "oidc" +) + // Me gets the details of the authenticated user. func (c Client) Me(ctx context.Context) (*User, error) { return c.UserByID(ctx, Me) @@ -70,3 +94,34 @@ func (c Client) UserByEmail(ctx context.Context, email string) (*User, error) { } return nil, ErrNotFound } + +// UpdateUserReq defines a modification to the user, updating the +// value of all non-nil values. +type UpdateUserReq struct { + // TODO(@cmoog) add update password option + Revoked *bool `json:"revoked,omitempty"` + Roles *Roles `json:"roles,omitempty"` + LoginType *LoginType `json:"login_type,omitempty"` + Name *string `json:"name,omitempty"` + Username *string `json:"username,omitempty"` + Email *string `json:"email,omitempty"` + DotfilesGitURL *string `json:"dotfiles_git_uri,omitempty"` +} + +func (c Client) UpdateUser(ctx context.Context, userID string, req UpdateUserReq) error { + return c.requestBody(ctx, http.MethodPatch, "/api/users/"+userID, req, nil) +} + +type CreateUserReq struct { + Name string `json:"name"` + Username string `json:"username"` + Email string `json:"email"` + Password string `json:"password"` + TemporaryPassword bool `json:"temporary_password"` + LoginType LoginType `json:"login_type"` + OrganizationsIDs []string `json:"organizations"` +} + +func (c Client) CreateUser(ctx context.Context, req CreateUserReq) error { + return c.requestBody(ctx, http.MethodPost, "/api/users", req, nil) +} diff --git a/coder-sdk/util.go b/coder-sdk/util.go new file mode 100644 index 00000000..882b3ced --- /dev/null +++ b/coder-sdk/util.go @@ -0,0 +1,35 @@ +package coder + +import ( + "encoding/json" + "strconv" + "time" +) + +func String(s string) *string { + return &s +} + +// Duration is a time.Duration wrapper that marshals to millisecond precision. +// While it looses precision, most javascript applications expect durations to be in milliseconds. +type Duration time.Duration + +// MarshalJSON marshals the duration to millisecond precision. +func (d Duration) MarshalJSON() ([]byte, error) { + du := time.Duration(d) + return json.Marshal(du.Milliseconds()) +} + +// UnmarshalJSON unmarshals a millisecond-precision integer to +// a time.Duration. +func (d *Duration) UnmarshalJSON(b []byte) error { + i, err := strconv.ParseInt(string(b), 10, 64) + if err != nil { + return err + } + + *d = Duration(time.Duration(i) * time.Millisecond) + return nil +} + +func (d Duration) String() string { return time.Duration(d).String() } diff --git a/internal/x/xjson/duration.go b/internal/x/xjson/duration.go deleted file mode 100644 index 04ec1f17..00000000 --- a/internal/x/xjson/duration.go +++ /dev/null @@ -1,31 +0,0 @@ -package xjson - -import ( - "encoding/json" - "strconv" - "time" -) - -// MSDuration is a time.MSDuration that marshals to millisecond precision. -// While is looses precision, most javascript applications expect durations to be in milliseconds. -type MSDuration time.Duration - -// MarshalJSON marshals the duration to millisecond precision. -func (d MSDuration) MarshalJSON() ([]byte, error) { - du := time.Duration(d) - return json.Marshal(du.Milliseconds()) -} - -// UnmarshalJSON unmarshals a millisecond-precision integer to -// a time.Duration. -func (d *MSDuration) UnmarshalJSON(b []byte) error { - i, err := strconv.ParseInt(string(b), 10, 64) - if err != nil { - return err - } - - *d = MSDuration(time.Duration(i) * time.Millisecond) - return nil -} - -func (d MSDuration) String() string { return time.Duration(d).String() } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy