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

Commit f5e35d6

Browse files
committed
Add coder envs edit command
1 parent 8917fb8 commit f5e35d6

File tree

5 files changed

+131
-13
lines changed

5 files changed

+131
-13
lines changed

ci/steps/gendocs.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ go run ./cmd/coder gen-docs ./docs
1313

1414
# remove cobra footer from each file
1515
for filename in ./docs/*.md; do
16-
trimmed=$(head -n -1 "$filename")
16+
trimmed=$(head -n $(( $(wc -l "$filename" | awk '{print $1}') - 1 )) "$filename")
1717
echo "$trimmed" >$filename
1818
done
1919

go.mod

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ require (
1616
github.com/rjeczalik/notify v0.9.2
1717
github.com/spf13/cobra v1.0.0
1818
github.com/stretchr/testify v1.6.1
19-
golang.org/x/crypto v0.0.0-20200422194213-44a606286825
20-
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
19+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
20+
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
21+
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
2122
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13
2223
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
23-
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
24+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
2425
nhooyr.io/websocket v1.8.6
2526
)

go.sum

+11-4
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
273273
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
274274
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
275275
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
276-
golang.org/x/crypto v0.0.0-20200422194213-44a606286825 h1:dSChiwOTvzwbHFTMq2l6uRardHH7/E6SqEkqccinS/o=
277-
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
276+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
277+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
278278
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
279279
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
280280
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -288,6 +288,7 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
288288
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
289289
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
290290
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
291+
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
291292
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
292293
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
293294
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -308,6 +309,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
308309
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
309310
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
310311
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
312+
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
313+
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
311314
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
312315
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
313316
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -316,8 +319,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
316319
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
317320
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
318321
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
319-
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
320-
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
322+
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
323+
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
321324
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
322325
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
323326
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -337,6 +340,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
337340
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
338341
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
339342
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
343+
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
340344
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 h1:5jaG59Zhd+8ZXe8C+lgiAGqkOaZBruqrWclLkgAww34=
341345
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
342346
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -363,10 +367,13 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
363367
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
364368
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
365369
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
370+
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2 h1:EtTFh6h4SAKemS+CURDMTDIANuduG5zKEXShyy18bGA=
366371
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
367372
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
368373
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
369374
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
375+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
376+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
370377
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
371378
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
372379
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=

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

+110-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ func envsCommand() *cobra.Command {
6363
}
6464
lsCmd.Flags().StringVarP(&outputFmt, "output", "o", "human", "human | json")
6565
cmd.AddCommand(lsCmd)
66-
cmd.AddCommand(stopEnvCommand(&user))
6766

67+
cmd.AddCommand(editEnvCommand(&user))
68+
cmd.AddCommand(stopEnvCommand(&user))
6869
cmd.AddCommand(watchBuildLogCommand())
6970
cmd.AddCommand(rebuildEnvCommand())
7071
return cmd
@@ -125,3 +126,111 @@ coder envs --user charlie@coder.com ls -o json \
125126
},
126127
}
127128
}
129+
130+
func editEnvCommand(user *string) *cobra.Command {
131+
var (
132+
img string
133+
tag string
134+
cpuCores float32
135+
memGB float32
136+
diskGB int
137+
gpus int
138+
follow bool
139+
)
140+
141+
cmd := &cobra.Command{
142+
Use: "edit",
143+
Short: "edit an existing environment owned by the active user.",
144+
Args: cobra.ExactArgs(1),
145+
Hidden: true,
146+
Long: "Edit an existing environment owned by the active user.",
147+
Example: `coder envs edit back-end-env --cores 4
148+
149+
coder envs edit back-end-env --disk 20`,
150+
RunE: func(cmd *cobra.Command, args []string) error {
151+
// We're explicitly ignoring these errors because if any of these
152+
// fail we are left with the zero value for the corresponding numeric type.
153+
cpuCores, _ = cmd.Flags().GetFloat32("cpu")
154+
memGB, _ = cmd.Flags().GetFloat32("memory")
155+
diskGB, _ = cmd.Flags().GetInt("disk")
156+
gpus, _ = cmd.Flags().GetInt("gpus")
157+
158+
client, err := newClient()
159+
if err != nil {
160+
return err
161+
}
162+
163+
envName := args[0]
164+
165+
env, err := findEnv(cmd.Context(), client, envName, *user)
166+
if err != nil {
167+
return err
168+
}
169+
170+
var updateReq coder.UpdateEnvironmentReq
171+
172+
// If any of the flags have defaulted to zero-values, it implies the user does not wish to change that value.
173+
// With that said, we can enforce this by reassigning the request field to the corresponding existing environment value.
174+
if cpuCores == 0 {
175+
updateReq.CPUCores = &env.CPUCores
176+
} else {
177+
updateReq.CPUCores = &cpuCores
178+
}
179+
180+
if memGB == 0 {
181+
updateReq.MemoryGB = &env.MemoryGB
182+
} else {
183+
updateReq.MemoryGB = &memGB
184+
}
185+
186+
if diskGB == 0 {
187+
updateReq.DiskGB = &env.DiskGB
188+
} else {
189+
updateReq.DiskGB = &diskGB
190+
}
191+
192+
if gpus == 0 {
193+
updateReq.GPUs = &env.GPUs
194+
} else {
195+
updateReq.GPUs = &gpus
196+
}
197+
198+
if img == "" {
199+
updateReq.ImageID = &env.ImageID
200+
} else {
201+
updateReq.ImageID = &img
202+
}
203+
204+
if tag == "" {
205+
updateReq.ImageTag = &env.ImageTag
206+
} else {
207+
updateReq.ImageTag = &tag
208+
}
209+
210+
if err := client.EditEnvironment(cmd.Context(), env.ID, updateReq); err != nil {
211+
return xerrors.Errorf("failed to apply changes to environment: '%s'", envName)
212+
}
213+
214+
clog.LogSuccess(
215+
"applied changes to the environment, rebuilding...",
216+
clog.BlankLine,
217+
clog.Tip(`run "coder envs watch-build %q" to trail the build logs`, envName),
218+
)
219+
220+
if follow {
221+
if err := trailBuildLogs(cmd.Context(), client, env.ID); err != nil {
222+
return err
223+
}
224+
}
225+
return nil
226+
},
227+
}
228+
cmd.Flags().StringVarP(&img, "image", "i", "", "image ID of the image you wan't the environment to be based off of.")
229+
cmd.Flags().StringVarP(&tag, "tag", "t", "latest", "image tag of the image you wan't to base the environment off of.")
230+
cmd.Flags().Float32P("cpu", "c", cpuCores, "The number of cpu cores the environment should be provisioned with.")
231+
cmd.Flags().Float32P("memory", "m", memGB, "The amount of RAM an environment should be provisioned with.")
232+
cmd.Flags().IntP("disk", "d", diskGB, "The amount of disk storage an environment should be provisioned with.")
233+
cmd.Flags().IntP("gpu", "g", gpus, "The amount of disk storage to provision the environment with.")
234+
cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild")
235+
return cmd
236+
}

0 commit comments

Comments
 (0)