diff --git a/ci/integration/envs_test.go b/ci/integration/envs_test.go index cfa96983..634496f7 100644 --- a/ci/integration/envs_test.go +++ b/ci/integration/envs_test.go @@ -108,7 +108,7 @@ func TestEnvsCLI(t *testing.T) { // Successfully output help. c.Run(ctx, "coder envs create --help").Assert(t, tcli.Success(), - tcli.StdoutMatches(regexp.QuoteMeta("Create a new environment under the active user.")), + tcli.StdoutMatches(regexp.QuoteMeta("Create a new Coder environment.")), tcli.StderrEmpty(), ) diff --git a/coder-sdk/client.go b/coder-sdk/client.go index 12a7c476..8076c517 100644 --- a/coder-sdk/client.go +++ b/coder-sdk/client.go @@ -6,7 +6,7 @@ import ( "net/url" ) -// Me is the route param to access resources of the authenticated user. +// Me is the user ID of the authenticated user. const Me = "me" // Client wraps the Coder HTTP API. diff --git a/coder-sdk/error.go b/coder-sdk/error.go index e5d16eb2..bdbef50f 100644 --- a/coder-sdk/error.go +++ b/coder-sdk/error.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "net/http/httputil" "golang.org/x/xerrors" ) @@ -34,16 +33,11 @@ type HTTPError struct { } func (e *HTTPError) Error() string { - dump, err := httputil.DumpResponse(e.Response, false) - if err != nil { - return fmt.Sprintf("dump response: %+v", err) - } - var msg APIError // Try to decode the payload as an error, if it fails or if there is no error message, // return the response URL with the dump. if err := json.NewDecoder(e.Response.Body).Decode(&msg); err != nil || msg.Err.Msg == "" { - return fmt.Sprintf("%s\n%s", e.Response.Request.URL, dump) + return fmt.Sprintf("%s: %d %s", e.Request.URL, e.StatusCode, e.Status) } // If the payload was a in the expected error format with a message, include it. @@ -51,5 +45,5 @@ func (e *HTTPError) Error() string { } func bodyError(resp *http.Response) error { - return &HTTPError{resp} + return &HTTPError{Response: resp} } diff --git a/docs/coder_envs.md b/docs/coder_envs.md index c89a5060..90d14880 100644 --- a/docs/coder_envs.md +++ b/docs/coder_envs.md @@ -22,6 +22,8 @@ Perform operations on the Coder environments owned by the active user. ### SEE ALSO * [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation +* [coder envs create](coder_envs_create.md) - create a new environment. +* [coder envs edit](coder_envs_edit.md) - edit an existing environment and initiate a rebuild. * [coder envs ls](coder_envs_ls.md) - list all environments owned by the active user * [coder envs rebuild](coder_envs_rebuild.md) - rebuild a Coder environment * [coder envs rm](coder_envs_rm.md) - remove Coder environments by name diff --git a/docs/coder_envs_create.md b/docs/coder_envs_create.md new file mode 100644 index 00000000..67c2cb8c --- /dev/null +++ b/docs/coder_envs_create.md @@ -0,0 +1,45 @@ +## coder envs create + +create a new environment. + +### Synopsis + +Create a new Coder environment. + +``` +coder envs create [environment_name] [flags] +``` + +### Examples + +``` +# create a new environment using default resource amounts +coder envs create my-new-env --image ubuntu +coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ubuntu +``` + +### Options + +``` + -c, --cpu float32 number of cpu cores the environment should be provisioned with. + -d, --disk int GB of disk storage an environment should be provisioned with. + --follow follow buildlog after initiating rebuild + -g, --gpus int number GPUs an environment should be provisioned with. + -h, --help help for create + -i, --image string name of the image to base the environment off of. + -m, --memory float32 GB of RAM an environment should be provisioned with. + -o, --org string ID of the organization the environment should be created under. + -t, --tag string tag of the image the environment will be based off of. (default "latest") +``` + +### Options inherited from parent commands + +``` + --user string Specify the user whose resources to target (default "me") + -v, --verbose show verbose output +``` + +### SEE ALSO + +* [coder envs](coder_envs.md) - Interact with Coder environments + diff --git a/docs/coder_envs_edit.md b/docs/coder_envs_edit.md new file mode 100644 index 00000000..72416b2c --- /dev/null +++ b/docs/coder_envs_edit.md @@ -0,0 +1,45 @@ +## coder envs edit + +edit an existing environment and initiate a rebuild. + +### Synopsis + +Edit an existing environment and initate a rebuild. + +``` +coder envs edit [flags] +``` + +### Examples + +``` +coder envs edit back-end-env --cpu 4 + +coder envs edit back-end-env --disk 20 +``` + +### Options + +``` + -c, --cpu float32 The number of cpu cores the environment should be provisioned with. + -d, --disk int The amount of disk storage an environment should be provisioned with. + --follow follow buildlog after initiating rebuild + -g, --gpu int The amount of disk storage to provision the environment with. + -h, --help help for edit + -i, --image string name of the image you want the environment to be based off of. + -m, --memory float32 The amount of RAM an environment should be provisioned with. + -o, --org string name of the organization the environment should be created under. + -t, --tag string image tag of the image you want to base the environment off of. (default "latest") +``` + +### Options inherited from parent commands + +``` + --user string Specify the user whose resources to target (default "me") + -v, --verbose show verbose output +``` + +### SEE ALSO + +* [coder envs](coder_envs.md) - Interact with Coder environments + diff --git a/internal/cmd/ceapi.go b/internal/cmd/ceapi.go index 1e7e2480..8d155de1 100644 --- a/internal/cmd/ceapi.go +++ b/internal/cmd/ceapi.go @@ -84,13 +84,12 @@ func findEnv(ctx context.Context, client *coder.Client, envName, userEmail strin } type findImgConf struct { - client *coder.Client email string imgName string orgName string } -func findImg(ctx context.Context, conf findImgConf) (*coder.Image, error) { +func findImg(ctx context.Context, client *coder.Client, conf findImgConf) (*coder.Image, error) { switch { case conf.email == "": return nil, xerrors.New("user email unset") @@ -98,13 +97,10 @@ func findImg(ctx context.Context, conf findImgConf) (*coder.Image, error) { return nil, xerrors.New("image name unset") } - imgs, err := getImgs(ctx, - getImgsConf{ - client: conf.client, - email: conf.email, - orgName: conf.orgName, - }, - ) + imgs, err := getImgs(ctx, client, getImgsConf{ + email: conf.email, + orgName: conf.orgName, + }) if err != nil { return nil, err } @@ -129,30 +125,29 @@ func findImg(ctx context.Context, conf findImgConf) (*coder.Image, error) { return nil, xerrors.New("image not found - did you forget to import this image?") } - lines := []string{clog.Tipf("Did you mean?")} + lines := []string{clog.Hintf("Did you mean?")} for _, img := range possibleMatches { - lines = append(lines, img.Repository) + lines = append(lines, fmt.Sprintf(" %s", img.Repository)) } return nil, clog.Fatal( - fmt.Sprintf("Found %d possible matches for %q.", len(possibleMatches), conf.imgName), + fmt.Sprintf("image %s not found", conf.imgName), lines..., ) } type getImgsConf struct { - client *coder.Client email string orgName string } -func getImgs(ctx context.Context, conf getImgsConf) ([]coder.Image, error) { - u, err := conf.client.UserByEmail(ctx, conf.email) +func getImgs(ctx context.Context, client *coder.Client, conf getImgsConf) ([]coder.Image, error) { + u, err := client.UserByEmail(ctx, conf.email) if err != nil { return nil, err } - orgs, err := conf.client.Organizations(ctx) + orgs, err := client.Organizations(ctx) if err != nil { return nil, err } @@ -160,7 +155,7 @@ func getImgs(ctx context.Context, conf getImgsConf) ([]coder.Image, error) { orgs = lookupUserOrgs(u, orgs) for _, org := range orgs { - imgs, err := conf.client.OrganizationImages(ctx, org.ID) + imgs, err := client.OrganizationImages(ctx, org.ID) if err != nil { return nil, err } diff --git a/internal/cmd/envs.go b/internal/cmd/envs.go index 4dff187b..a35fa6ed 100644 --- a/internal/cmd/envs.go +++ b/internal/cmd/envs.go @@ -141,6 +141,10 @@ coder envs --user charlie@coder.com ls -o json \ func createEnvCmd(user *string) *cobra.Command { var ( org string + cpu float32 + memory float32 + disk int + gpus int img string tag string follow bool @@ -150,14 +154,10 @@ func createEnvCmd(user *string) *cobra.Command { Use: "create [environment_name]", Short: "create a new environment.", Args: cobra.ExactArgs(1), - // Don't unhide this command until we can pass image names instead of image id's. - Hidden: true, - Long: "Create a new environment under the active user.", + Long: "Create a new Coder environment.", Example: `# create a new environment using default resource amounts -coder envs create --image 5f443b16-30652892427b955601330fa5 my-env-name - -# create a new environment using custom resource amounts -coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955601330fa5 my-env-name`, +coder envs create my-new-env --image ubuntu +coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ubuntu`, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() if img == "" { @@ -178,14 +178,11 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 return xerrors.New("org is required for multi-org members") } - importedImg, err := findImg(ctx, - findImgConf{ - client: client, - email: *user, - imgName: img, - orgName: org, - }, - ) + importedImg, err := findImg(ctx, client, findImgConf{ + email: *user, + imgName: img, + orgName: org, + }) if err != nil { return err } @@ -195,13 +192,11 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 Name: args[0], ImageID: importedImg.ID, ImageTag: tag, + CPUCores: cpu, + MemoryGB: memory, + DiskGB: disk, + GPUs: gpus, } - // We're explicitly ignoring errors for these because all we - // need to now is if the numeric type is 0 or not. - createReq.CPUCores, _ = cmd.Flags().GetFloat32("cpu") - createReq.MemoryGB, _ = cmd.Flags().GetFloat32("memory") - createReq.DiskGB, _ = cmd.Flags().GetInt("disk") - createReq.GPUs, _ = cmd.Flags().GetInt("gpus") // if any of these defaulted to their zero value we provision // the create request with the imported image defaults instead. @@ -230,17 +225,17 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 clog.LogSuccess("creating environment...", clog.BlankLine, - clog.Tipf(`run "coder envs watch-build %q" to trail the build logs`, env.Name), + clog.Tipf(`run "coder envs watch-build %s" to trail the build logs`, env.Name), ) return nil }, } cmd.Flags().StringVarP(&org, "org", "o", "", "ID of the organization the environment should be created under.") cmd.Flags().StringVarP(&tag, "tag", "t", defaultImgTag, "tag of the image the environment will be based off of.") - cmd.Flags().Float32P("cpu", "c", 0, "number of cpu cores the environment should be provisioned with.") - cmd.Flags().Float32P("memory", "m", 0, "GB of RAM an environment should be provisioned with.") - cmd.Flags().IntP("disk", "d", 0, "GB of disk storage an environment should be provisioned with.") - cmd.Flags().IntP("gpus", "g", 0, "number GPUs an environment should be provisioned with.") + cmd.Flags().Float32VarP(&cpu, "cpu", "c", 0, "number of cpu cores the environment should be provisioned with.") + cmd.Flags().Float32VarP(&memory, "memory", "m", 0, "GB of RAM an environment should be provisioned with.") + cmd.Flags().IntVarP(&disk, "disk", "d", 0, "GB of disk storage an environment should be provisioned with.") + cmd.Flags().IntVarP(&gpus, "gpus", "g", 0, "number GPUs an environment should be provisioned with.") cmd.Flags().StringVarP(&img, "image", "i", "", "name of the image to base the environment off of.") cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild") _ = cmd.MarkFlagRequired("image") @@ -249,22 +244,21 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955 func editEnvCmd(user *string) *cobra.Command { var ( - org string - img string - tag string - cpuCores float32 - memGB float32 - diskGB int - gpus int - follow bool + org string + img string + tag string + cpu float32 + memory float32 + disk int + gpus int + follow bool ) cmd := &cobra.Command{ - Use: "edit", - Short: "edit an existing environment owned by the active user.", - Args: cobra.ExactArgs(1), - Hidden: true, - Long: "Edit an existing environment owned by the active user.", + Use: "edit", + Short: "edit an existing environment and initiate a rebuild.", + Args: cobra.ExactArgs(1), + Long: "Edit an existing environment and initate a rebuild.", Example: `coder envs edit back-end-env --cpu 4 coder envs edit back-end-env --disk 20`, @@ -292,25 +286,17 @@ coder envs edit back-end-env --disk 20`, return xerrors.New("org is required for multi-org members") } - cpuCores, _ = cmd.Flags().GetFloat32("cpu") - memGB, _ = cmd.Flags().GetFloat32("memory") - diskGB, _ = cmd.Flags().GetInt("disk") - gpus, _ = cmd.Flags().GetInt("gpus") - - req, err := buildUpdateReq(ctx, - updateConf{ - cpu: cpuCores, - memGB: memGB, - diskGB: diskGB, - gpus: gpus, - client: client, - environment: env, - user: user, - image: img, - imageTag: tag, - orgName: org, - }, - ) + req, err := buildUpdateReq(ctx, client, updateConf{ + cpu: cpu, + memGB: memory, + diskGB: disk, + gpus: gpus, + environment: env, + user: user, + image: img, + imageTag: tag, + orgName: org, + }) if err != nil { return err } @@ -329,7 +315,7 @@ coder envs edit back-end-env --disk 20`, clog.LogSuccess("applied changes to the environment, rebuilding...", clog.BlankLine, - clog.Tipf(`run "coder envs watch-build %q" to trail the build logs`, envName), + clog.Tipf(`run "coder envs watch-build %s" to trail the build logs`, envName), ) return nil }, @@ -337,10 +323,10 @@ coder envs edit back-end-env --disk 20`, cmd.Flags().StringVarP(&org, "org", "o", "", "name of the organization the environment should be created under.") cmd.Flags().StringVarP(&img, "image", "i", "", "name of the image you want the environment to be based off of.") cmd.Flags().StringVarP(&tag, "tag", "t", "latest", "image tag of the image you want to base the environment off of.") - cmd.Flags().Float32P("cpu", "c", cpuCores, "The number of cpu cores the environment should be provisioned with.") - cmd.Flags().Float32P("memory", "m", memGB, "The amount of RAM an environment should be provisioned with.") - cmd.Flags().IntP("disk", "d", diskGB, "The amount of disk storage an environment should be provisioned with.") - cmd.Flags().IntP("gpu", "g", gpus, "The amount of disk storage to provision the environment with.") + cmd.Flags().Float32VarP(&cpu, "cpu", "c", 0, "The number of cpu cores the environment should be provisioned with.") + cmd.Flags().Float32VarP(&memory, "memory", "m", 0, "The amount of RAM an environment should be provisioned with.") + cmd.Flags().IntVarP(&disk, "disk", "d", 0, "The amount of disk storage an environment should be provisioned with.") + cmd.Flags().IntVarP(&gpus, "gpu", "g", 0, "The amount of disk storage to provision the environment with.") cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild") return cmd } @@ -364,7 +350,7 @@ func rmEnvsCmd(user *string) *cobra.Command { } if _, err := confirm.Run(); err != nil { return clog.Fatal( - "failed to confirm prompt", clog.BlankLine, + "failed to confirm deletion", clog.BlankLine, clog.Tipf(`use "--force" to rebuild without a confirmation prompt`), ) } @@ -400,7 +386,6 @@ type updateConf struct { memGB float32 diskGB int gpus int - client *coder.Client environment *coder.Environment user *string image string @@ -408,7 +393,7 @@ type updateConf struct { orgName string } -func buildUpdateReq(ctx context.Context, conf updateConf) (*coder.UpdateEnvironmentReq, error) { +func buildUpdateReq(ctx context.Context, client *coder.Client, conf updateConf) (*coder.UpdateEnvironmentReq, error) { var ( updateReq coder.UpdateEnvironmentReq defaultCPUCores float32 @@ -418,14 +403,11 @@ func buildUpdateReq(ctx context.Context, conf updateConf) (*coder.UpdateEnvironm // If this is not empty it means the user is requesting to change the environment image. if conf.image != "" { - importedImg, err := findImg(ctx, - findImgConf{ - client: conf.client, - email: *conf.user, - imgName: conf.image, - orgName: conf.orgName, - }, - ) + importedImg, err := findImg(ctx, client, findImgConf{ + email: *conf.user, + imgName: conf.image, + orgName: conf.orgName, + }) if err != nil { return nil, err } 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