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

Commit 2c14487

Browse files
committed
Add envs create command
1 parent 8917fb8 commit 2c14487

26 files changed

+179
-12
lines changed

ci/integration/envs_test.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package integration
2+
3+
import (
4+
"context"
5+
"regexp"
6+
"testing"
7+
8+
"cdr.dev/coder-cli/ci/tcli"
9+
)
10+
11+
// From Coder organization images
12+
const ubuntuImgID = "5f443b16-30652892427b955601330fa5"
13+
14+
func TestEnvsCLI(t *testing.T) {
15+
t.Parallel()
16+
17+
run(t, "coder-cli-env-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
18+
headlessLogin(ctx, t, c)
19+
20+
// Ensure binary is present.
21+
c.Run(ctx, "which coder").Assert(t,
22+
tcli.Success(),
23+
tcli.StdoutMatches("/usr/sbin/coder"),
24+
tcli.StderrEmpty(),
25+
)
26+
27+
// Minimum args not received.
28+
c.Run(ctx, "coder envs create").Assert(t,
29+
tcli.StderrMatches(regexp.QuoteMeta("accepts 1 arg(s), received 0")),
30+
tcli.Error(),
31+
)
32+
33+
// Successfully output help.
34+
c.Run(ctx, "coder envs create --help").Assert(t,
35+
tcli.Success(),
36+
tcli.StdoutMatches(regexp.QuoteMeta("Create a new environment under the active user.")),
37+
tcli.StderrEmpty(),
38+
)
39+
40+
// TODO(Faris) : uncomment this when we can safely purge the environments
41+
// the integrations tests would create in the sidecar
42+
// Successfully create environment.
43+
// c.Run(ctx, "coder envs create --image "+ubuntuImgID+" test-ubuntu").Assert(t,
44+
// tcli.Success(),
45+
// // why does flog.Success write to stderr?
46+
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"test-ubuntu\"")),
47+
// )
48+
49+
// Invalid environment name should fail.
50+
c.Run(ctx, "coder envs create --image "+ubuntuImgID+" this-IS-an-invalid-EnvironmentName").Assert(t,
51+
tcli.Error(),
52+
tcli.StderrMatches(regexp.QuoteMeta("environment name must conform to regex ^[a-z0-9]([a-z0-9-]+)?")),
53+
)
54+
55+
// TODO(Faris) : uncomment this when we can safely purge the environments
56+
// the integrations tests would create in the sidecar
57+
// Successfully provision environment with fractional resource amounts
58+
// c.Run(ctx, fmt.Sprintf(`coder envs create -i %s -c 1.2 -m 1.4 non-whole-resource-amounts`, ubuntuImgID)).Assert(t,
59+
// tcli.Success(),
60+
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"non-whole-resource-amounts\"")),
61+
// )
62+
63+
// Image does not exist should fail.
64+
c.Run(ctx, "coder envs create --image does-not-exist env-will-not-be-created").Assert(t,
65+
tcli.Error(),
66+
tcli.StderrMatches(regexp.QuoteMeta("does not exist")),
67+
)
68+
})
69+
}

ci/steps/gendocs.sh

-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ rm -rf ./docs
1111
mkdir ./docs
1212
go run ./cmd/coder gen-docs ./docs
1313

14-
# remove cobra footer from each file
15-
for filename in ./docs/*.md; do
16-
trimmed=$(head -n -1 "$filename")
17-
echo "$trimmed" >$filename
18-
done
19-
2014
if [[ ${CI-} && $(git ls-files --other --modified --exclude-standard) ]]; then
2115
echo "Documentation needs generation:"
2216
git -c color.ui=always status | grep --color=no '\e\[31m'

coder-sdk/env.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ type CreateEnvironmentRequest struct {
7878
ImageID string `json:"image_id"`
7979
ImageTag string `json:"image_tag"`
8080
CPUCores float32 `json:"cpu_cores"`
81-
MemoryGB int `json:"memory_gb"`
81+
MemoryGB float32 `json:"memory_gb"`
8282
DiskGB int `json:"disk_gb"`
8383
GPUs int `json:"gpus"`
8484
Services []string `json:"services"`

docs/coder.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ coder provides a CLI for working with an existing Coder Enterprise installation
2525
* [coder sync](coder_sync.md) - Establish a one way directory sync to a Coder environment
2626
* [coder urls](coder_urls.md) - Interact with environment DevURLs
2727
* [coder users](coder_users.md) - Interact with Coder user accounts
28+

docs/coder_completion.md

+1
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,4 @@ MacOS:
6767
### SEE ALSO
6868

6969
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
70+

docs/coder_config-ssh.md

+1
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ coder config-ssh [flags]
2727
### SEE ALSO
2828

2929
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
30+

docs/coder_envs.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ Perform operations on the Coder environments owned by the active user.
2424
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
2525
* [coder envs ls](coder_envs_ls.md) - list all environments owned by the active user
2626
* [coder envs stop](coder_envs_stop.md) - stop Coder environments by name
27+

docs/coder_envs_ls.md

+1
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ coder envs ls [flags]
2727
### SEE ALSO
2828

2929
* [coder envs](coder_envs.md) - Interact with Coder environments
30+

docs/coder_envs_stop.md

+1
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ coder envs --user charlie@coder.com ls -o json \
4141
### SEE ALSO
4242

4343
* [coder envs](coder_envs.md) - Interact with Coder environments
44+

docs/coder_login.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ coder login [Coder Enterprise URL eg. https://my.coder.domain/] [flags]
2525
### SEE ALSO
2626

2727
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
28+

docs/coder_logout.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ coder logout [flags]
2525
### SEE ALSO
2626

2727
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
28+

docs/coder_secrets.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ Interact with secrets objects owned by the active user.
2626
* [coder secrets ls](coder_secrets_ls.md) - List all secrets owned by the active user
2727
* [coder secrets rm](coder_secrets_rm.md) - Remove one or more secrets by name
2828
* [coder secrets view](coder_secrets_view.md) - View a secret by name
29+

docs/coder_secrets_create.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ coder secrets create aws-credentials --from-file ./credentials.json
3838
### SEE ALSO
3939

4040
* [coder secrets](coder_secrets.md) - Interact with Coder Secrets
41+

docs/coder_secrets_ls.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ coder secrets ls [flags]
2626
### SEE ALSO
2727

2828
* [coder secrets](coder_secrets.md) - Interact with Coder Secrets
29+

docs/coder_secrets_rm.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ coder secrets rm mysql-password mysql-user
3232
### SEE ALSO
3333

3434
* [coder secrets](coder_secrets.md) - Interact with Coder Secrets
35+

docs/coder_secrets_view.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ coder secrets view mysql-password
3232
### SEE ALSO
3333

3434
* [coder secrets](coder_secrets.md) - Interact with Coder Secrets
35+

docs/coder_sh.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ coder sh backend-env
3131
### SEE ALSO
3232

3333
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
34+

docs/coder_sync.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ coder sync [local directory] [<env name>:<remote directory>] [flags]
2626
### SEE ALSO
2727

2828
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
29+

docs/coder_urls.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ Interact with environment DevURLs
2424
* [coder urls create](coder_urls_create.md) - Create a new devurl for an environment
2525
* [coder urls ls](coder_urls_ls.md) - List all DevURLs for an environment
2626
* [coder urls rm](coder_urls_rm.md) - Remove a dev url
27+

docs/coder_urls_create.md

+1
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ coder urls create [env_name] [port] [--access <level>] [--name <name>] [flags]
2727
### SEE ALSO
2828

2929
* [coder urls](coder_urls.md) - Interact with environment DevURLs
30+

docs/coder_urls_ls.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ coder urls ls [environment_name] [flags]
2626
### SEE ALSO
2727

2828
* [coder urls](coder_urls.md) - Interact with environment DevURLs
29+

docs/coder_urls_rm.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ coder urls rm [environment_name] [port] [flags]
2525
### SEE ALSO
2626

2727
* [coder urls](coder_urls.md) - Interact with environment DevURLs
28+

docs/coder_users.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ Interact with Coder user accounts
2222

2323
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
2424
* [coder users ls](coder_users_ls.md) - list all user accounts
25+

docs/coder_users_ls.md

+1
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ coder users ls -o json | jq .[] | jq -r .email
3333
### SEE ALSO
3434

3535
* [coder users](coder_users.md) - Interact with Coder user accounts
36+

internal/cmd/cmd.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ var verbose bool = false
1313
// Make constructs the "coder" root command
1414
func Make() *cobra.Command {
1515
app := &cobra.Command{
16-
Use: "coder",
17-
Short: "coder provides a CLI for working with an existing Coder Enterprise installation",
18-
SilenceErrors: true,
19-
SilenceUsage: true,
16+
Use: "coder",
17+
Short: "coder provides a CLI for working with an existing Coder Enterprise installation",
18+
SilenceErrors: true,
19+
SilenceUsage: true,
20+
DisableAutoGenTag: true,
2021
}
2122

2223
app.AddCommand(

internal/cmd/envs.go

+83-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ import (
1414
"golang.org/x/xerrors"
1515
)
1616

17+
const (
18+
defaultOrg = "default"
19+
defaultImgTag = "latest"
20+
defaultCPUCores float32 = 1
21+
defaultMemGB float32 = 1
22+
defaultDiskGB = 10
23+
defaultGPUs = 0
24+
)
25+
1726
func envsCommand() *cobra.Command {
1827
var outputFmt string
1928
var user string
@@ -64,9 +73,9 @@ func envsCommand() *cobra.Command {
6473
lsCmd.Flags().StringVarP(&outputFmt, "output", "o", "human", "human | json")
6574
cmd.AddCommand(lsCmd)
6675
cmd.AddCommand(stopEnvCommand(&user))
67-
6876
cmd.AddCommand(watchBuildLogCommand())
6977
cmd.AddCommand(rebuildEnvCommand())
78+
cmd.AddCommand(createEnvCommand())
7079
return cmd
7180
}
7281

@@ -125,3 +134,76 @@ coder envs --user charlie@coder.com ls -o json \
125134
},
126135
}
127136
}
137+
138+
func createEnvCommand() *cobra.Command {
139+
var (
140+
org string
141+
img string
142+
tag string
143+
follow bool
144+
)
145+
146+
cmd := &cobra.Command{
147+
Use: "create [environment_name]",
148+
Short: "create a new environment.",
149+
Args: cobra.ExactArgs(1),
150+
// Don't unhide this command until we can pass image names instead of image id's.
151+
Hidden: true,
152+
Long: "Create a new environment under the active user.",
153+
Example: `# create a new environment using default resource amounts
154+
coder envs create --image 5f443b16-30652892427b955601330fa5 my-env-name
155+
156+
# create a new environment using custom resource amounts
157+
coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955601330fa5 my-env-name`,
158+
RunE: func(cmd *cobra.Command, args []string) error {
159+
if img == "" {
160+
return xerrors.New("image id unset")
161+
}
162+
// ExactArgs(1) ensures our name value can't panic on an out of bounds.
163+
createReq := &coder.CreateEnvironmentRequest{
164+
Name: args[0],
165+
ImageID: img,
166+
ImageTag: tag,
167+
}
168+
// We're explicitly ignoring errors for these because all of these flags
169+
// have a non-zero-value default value set already.
170+
createReq.CPUCores, _ = cmd.Flags().GetFloat32("cpu")
171+
createReq.MemoryGB, _ = cmd.Flags().GetFloat32("memory")
172+
createReq.DiskGB, _ = cmd.Flags().GetInt("disk")
173+
createReq.GPUs, _ = cmd.Flags().GetInt("gpus")
174+
175+
client, err := newClient()
176+
if err != nil {
177+
return err
178+
}
179+
180+
env, err := client.CreateEnvironment(cmd.Context(), org, *createReq)
181+
if err != nil {
182+
return xerrors.Errorf("create environment: %w", err)
183+
}
184+
185+
clog.LogSuccess(
186+
"creating environment...",
187+
clog.BlankLine,
188+
clog.Tip(`run "coder envs watch-build %q" to trail the build logs`, args[0]),
189+
)
190+
191+
if follow {
192+
if err := trailBuildLogs(cmd.Context(), client, env.ID); err != nil {
193+
return err
194+
}
195+
}
196+
return nil
197+
},
198+
}
199+
cmd.Flags().StringVarP(&org, "org", "o", defaultOrg, "ID of the organization the environment should be created under.")
200+
cmd.Flags().StringVarP(&tag, "tag", "t", defaultImgTag, "tag of the image the environment will be based off of.")
201+
cmd.Flags().Float32P("cpu", "c", defaultCPUCores, "number of cpu cores the environment should be provisioned with.")
202+
cmd.Flags().Float32P("memory", "m", defaultMemGB, "GB of RAM an environment should be provisioned with.")
203+
cmd.Flags().IntP("disk", "d", defaultDiskGB, "GB of disk storage an environment should be provisioned with.")
204+
cmd.Flags().IntP("gpus", "g", defaultGPUs, "number GPUs an environment should be provisioned with.")
205+
cmd.Flags().StringVarP(&img, "image", "i", "", "ID of the image to base the environment off of.")
206+
cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild")
207+
cmd.MarkFlagRequired("image")
208+
return cmd
209+
}

0 commit comments

Comments
 (0)