Skip to content

Commit f803e37

Browse files
authored
chore: use workspace name as arg in coder workspaces create (#1007)
1 parent 7090227 commit f803e37

File tree

5 files changed

+64
-44
lines changed

5 files changed

+64
-44
lines changed

cli/templatecreate.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ func templateCreate() *cobra.Command {
2626
provisioner string
2727
)
2828
cmd := &cobra.Command{
29-
Use: "create <directory> [name]",
29+
Use: "create [name]",
3030
Short: "Create a template from the current directory",
3131
RunE: func(cmd *cobra.Command, args []string) error {
3232
client, err := createClient(cmd)
3333
if err != nil {
3434
return err
3535
}
36+
3637
organization, err := currentOrganization(cmd, client)
3738
if err != nil {
3839
return err
@@ -44,6 +45,7 @@ func templateCreate() *cobra.Command {
4445
} else {
4546
templateName = args[0]
4647
}
48+
4749
_, err = client.TemplateByName(cmd.Context(), organization.ID, templateName)
4850
if err == nil {
4951
return xerrors.Errorf("A template already exists named %q!", templateName)
@@ -113,7 +115,7 @@ func templateCreate() *cobra.Command {
113115
"The "+cliui.Styles.Keyword.Render(templateName)+" template has been created! "+
114116
"Developers can provision a workspace with this template using:")+"\n")
115117

116-
_, _ = fmt.Fprintln(cmd.OutOrStdout(), " "+cliui.Styles.Code.Render("coder workspaces create "+templateName))
118+
_, _ = fmt.Fprintln(cmd.OutOrStdout(), " "+cliui.Styles.Code.Render(fmt.Sprintf("coder workspaces create --template=%q [workspace name]", templateName)))
117119
_, _ = fmt.Fprintln(cmd.OutOrStdout())
118120

119121
return nil
@@ -214,9 +216,15 @@ func createValidTemplateVersion(cmd *cobra.Command, client *codersdk.Client, org
214216
if err != nil {
215217
return nil, nil, err
216218
}
217-
return &version, parameters, cliui.WorkspaceResources(cmd.OutOrStdout(), resources, cliui.WorkspaceResourcesOptions{
219+
220+
err = cliui.WorkspaceResources(cmd.OutOrStdout(), resources, cliui.WorkspaceResourcesOptions{
218221
HideAgentState: true,
219222
HideAccess: true,
220223
Title: "Template Preview",
221224
})
225+
if err != nil {
226+
return nil, nil, xerrors.Errorf("preview template resources: %w", err)
227+
}
228+
229+
return &version, parameters, nil
222230
}

cli/workspacecreate.go

+43-34
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package cli
22

33
import (
44
"fmt"
5-
"sort"
65
"time"
76

87
"github.com/spf13/cobra"
8+
"golang.org/x/exp/slices"
99
"golang.org/x/xerrors"
1010

1111
"github.com/coder/coder/cli/cliflag"
@@ -17,50 +17,79 @@ import (
1717
func workspaceCreate() *cobra.Command {
1818
var (
1919
workspaceName string
20+
templateName string
2021
)
2122
cmd := &cobra.Command{
22-
Use: "create [template]",
23+
Use: "create [name]",
2324
Short: "Create a workspace from a template",
2425
RunE: func(cmd *cobra.Command, args []string) error {
2526
client, err := createClient(cmd)
2627
if err != nil {
2728
return err
2829
}
30+
2931
organization, err := currentOrganization(cmd, client)
3032
if err != nil {
3133
return err
3234
}
3335

34-
templateName := ""
3536
if len(args) >= 1 {
36-
templateName = args[0]
37+
workspaceName = args[0]
38+
}
39+
40+
if workspaceName == "" {
41+
workspaceName, err = cliui.Prompt(cmd, cliui.PromptOptions{
42+
Text: "Specify a name for your workspace:",
43+
Validate: func(workspaceName string) error {
44+
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
45+
if err == nil {
46+
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
47+
}
48+
return nil
49+
},
50+
})
51+
if err != nil {
52+
return err
53+
}
54+
}
55+
56+
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
57+
if err == nil {
58+
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
3759
}
3860

3961
var template codersdk.Template
4062
if templateName == "" {
4163
_, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Wrap.Render("Select a template below to preview the provisioned infrastructure:"))
4264

43-
templateNames := []string{}
44-
templateByName := map[string]codersdk.Template{}
4565
templates, err := client.TemplatesByOrganization(cmd.Context(), organization.ID)
4666
if err != nil {
4767
return err
4868
}
69+
70+
slices.SortFunc(templates, func(a, b codersdk.Template) bool {
71+
return a.WorkspaceOwnerCount > b.WorkspaceOwnerCount
72+
})
73+
74+
templateNames := make([]string, 0, len(templates))
75+
templateByName := make(map[string]codersdk.Template, len(templates))
76+
4977
for _, template := range templates {
5078
templateName := template.Name
79+
5180
if template.WorkspaceOwnerCount > 0 {
5281
developerText := "developer"
5382
if template.WorkspaceOwnerCount != 1 {
5483
developerText = "developers"
5584
}
85+
5686
templateName += cliui.Styles.Placeholder.Render(fmt.Sprintf(" (used by %d %s)", template.WorkspaceOwnerCount, developerText))
5787
}
88+
5889
templateNames = append(templateNames, templateName)
5990
templateByName[templateName] = template
6091
}
61-
sort.Slice(templateNames, func(i, j int) bool {
62-
return templateByName[templateNames[i]].WorkspaceOwnerCount > templateByName[templateNames[j]].WorkspaceOwnerCount
63-
})
92+
6493
// Move the cursor up a single line for nicer display!
6594
option, err := cliui.Select(cmd, cliui.SelectOptions{
6695
Options: templateNames,
@@ -69,36 +98,13 @@ func workspaceCreate() *cobra.Command {
6998
if err != nil {
7099
return err
71100
}
101+
72102
template = templateByName[option]
73103
} else {
74104
template, err = client.TemplateByName(cmd.Context(), organization.ID, templateName)
75105
if err != nil {
76106
return xerrors.Errorf("get template by name: %w", err)
77107
}
78-
if err != nil {
79-
return err
80-
}
81-
}
82-
83-
if workspaceName == "" {
84-
workspaceName, err = cliui.Prompt(cmd, cliui.PromptOptions{
85-
Text: "Specify a name for your workspace:",
86-
Validate: func(workspaceName string) error {
87-
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
88-
if err == nil {
89-
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
90-
}
91-
return nil
92-
},
93-
})
94-
if err != nil {
95-
return err
96-
}
97-
}
98-
99-
_, err = client.WorkspaceByName(cmd.Context(), codersdk.Me, workspaceName)
100-
if err == nil {
101-
return xerrors.Errorf("A workspace already exists named %q!", workspaceName)
102108
}
103109

104110
templateVersion, err := client.TemplateVersion(cmd.Context(), template.ActiveVersionID)
@@ -164,10 +170,12 @@ func workspaceCreate() *cobra.Command {
164170
if err != nil {
165171
return err
166172
}
173+
167174
err = cliui.WorkspaceBuild(cmd.Context(), cmd.OutOrStdout(), client, workspace.LatestBuild.ID, before)
168175
if err != nil {
169176
return err
170177
}
178+
171179
resources, err = client.WorkspaceResourcesByBuild(cmd.Context(), workspace.LatestBuild.ID)
172180
if err != nil {
173181
return err
@@ -179,11 +187,12 @@ func workspaceCreate() *cobra.Command {
179187
if err != nil {
180188
return err
181189
}
190+
182191
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "The %s workspace has been created!\n", cliui.Styles.Keyword.Render(workspace.Name))
183192
return nil
184193
},
185194
}
186-
cliflag.StringVarP(cmd.Flags(), &workspaceName, "name", "n", "CODER_WORKSPACE_NAME", "", "Specify a workspace name.")
187195

196+
cliflag.StringVarP(cmd.Flags(), &templateName, "template", "t", "CODER_TEMPLATE_NAME", "", "Specify a template name.")
188197
return cmd
189198
}

cli/workspacecreate_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestWorkspaceCreate(t *testing.T) {
2222
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
2323
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
2424
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
25-
cmd, root := clitest.New(t, "workspaces", "create", template.Name, "--name", "my-workspace")
25+
cmd, root := clitest.New(t, "workspaces", "create", "my-workspace", "--template", template.Name)
2626
clitest.SetupConfig(t, client, root)
2727
doneChan := make(chan struct{})
2828
pty := ptytest.New(t)
@@ -52,7 +52,7 @@ func TestWorkspaceCreate(t *testing.T) {
5252
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
5353
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
5454
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
55-
cmd, root := clitest.New(t, "workspaces", "create", "--name", "my-workspace")
55+
cmd, root := clitest.New(t, "workspaces", "create", "my-workspace")
5656
clitest.SetupConfig(t, client, root)
5757
doneChan := make(chan struct{})
5858
pty := ptytest.New(t)
@@ -82,7 +82,7 @@ func TestWorkspaceCreate(t *testing.T) {
8282
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
8383
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
8484
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
85-
cmd, root := clitest.New(t, "workspaces", "create", "--name", "")
85+
cmd, root := clitest.New(t, "workspaces", "create", "")
8686
clitest.SetupConfig(t, client, root)
8787
doneChan := make(chan struct{})
8888
pty := ptytest.New(t)
@@ -134,7 +134,7 @@ func TestWorkspaceCreate(t *testing.T) {
134134
})
135135
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
136136
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
137-
cmd, root := clitest.New(t, "workspaces", "create", "--name", "")
137+
cmd, root := clitest.New(t, "workspaces", "create", "")
138138
clitest.SetupConfig(t, client, root)
139139
doneChan := make(chan struct{})
140140
pty := ptytest.New(t)

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ require (
9292
go.uber.org/atomic v1.9.0
9393
go.uber.org/goleak v1.1.12
9494
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
95-
golang.org/x/mod v0.5.1
95+
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd
96+
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57
9697
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a
9798
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
9899
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
17871787
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
17881788
golang.org/x/exp v0.0.0-20200901203048-c4f52b2c50aa/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
17891789
golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925/go.mod h1:1phAWC201xIgDyaFpmDeZkgf70Q4Pd/CNqfRtVPtxNw=
1790+
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd h1:zVFyTKZN/Q7mNRWSs1GOYnHM9NiFSJ54YVRsD0rNWT4=
1791+
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
17901792
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
17911793
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
17921794
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1821,8 +1823,8 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM
18211823
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
18221824
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
18231825
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1824-
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
1825-
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
1826+
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4=
1827+
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
18261828
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
18271829
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
18281830
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

0 commit comments

Comments
 (0)