1
1
package cli
2
2
3
3
import (
4
- "errors"
5
4
"fmt"
6
5
"sort"
7
6
"time"
8
7
9
- "github.com/fatih/color"
10
- "github.com/manifoldco/promptui"
11
8
"github.com/spf13/cobra"
12
9
"golang.org/x/xerrors"
13
10
11
+ "github.com/coder/coder/cli/cliflag"
14
12
"github.com/coder/coder/cli/cliui"
15
13
"github.com/coder/coder/coderd/database"
16
14
"github.com/coder/coder/codersdk"
17
15
)
18
16
19
17
func workspaceCreate () * cobra.Command {
20
18
var (
21
- templateName string
19
+ workspaceName string
22
20
)
23
21
cmd := & cobra.Command {
24
- Use : "create <name>" ,
25
- Args : cobra .ExactArgs (1 ),
22
+ Use : "create [template]" ,
26
23
Short : "Create a workspace from a template" ,
27
24
RunE : func (cmd * cobra.Command , args []string ) error {
28
25
client , err := createClient (cmd )
@@ -34,9 +31,14 @@ func workspaceCreate() *cobra.Command {
34
31
return err
35
32
}
36
33
34
+ templateName := ""
35
+ if len (args ) >= 1 {
36
+ templateName = args [0 ]
37
+ }
38
+
37
39
var template codersdk.Template
38
40
if templateName == "" {
39
- _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Wrap .Render ("Select a template:" ))
41
+ _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Wrap .Render ("Select a template below to preview the provisioned infrastructure :" ))
40
42
41
43
templateNames := []string {}
42
44
templateByName := map [string ]codersdk.Template {}
@@ -45,8 +47,16 @@ func workspaceCreate() *cobra.Command {
45
47
return err
46
48
}
47
49
for _ , template := range templates {
48
- templateNames = append (templateNames , template .Name )
49
- templateByName [template .Name ] = template
50
+ templateName := template .Name
51
+ if template .WorkspaceOwnerCount > 0 {
52
+ developerText := "developer"
53
+ if template .WorkspaceOwnerCount != 1 {
54
+ developerText = "developers"
55
+ }
56
+ templateName += cliui .Styles .Placeholder .Render (fmt .Sprintf (" (used by %d %s)" , template .WorkspaceOwnerCount , developerText ))
57
+ }
58
+ templateNames = append (templateNames , templateName )
59
+ templateByName [templateName ] = template
50
60
}
51
61
sort .Slice (templateNames , func (i , j int ) bool {
52
62
return templateByName [templateNames [i ]].WorkspaceOwnerCount > templateByName [templateNames [j ]].WorkspaceOwnerCount
@@ -70,10 +80,22 @@ func workspaceCreate() *cobra.Command {
70
80
}
71
81
}
72
82
73
- _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
74
- _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Prompt .String ()+ "Creating with the " + cliui .Styles .Field .Render (template .Name )+ " template..." )
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
+ }
75
98
76
- workspaceName := args [0 ]
77
99
_ , err = client .WorkspaceByName (cmd .Context (), codersdk .Me , workspaceName )
78
100
if err == nil {
79
101
return xerrors .Errorf ("A workspace already exists named %q!" , workspaceName )
@@ -95,10 +117,9 @@ func workspaceCreate() *cobra.Command {
95
117
continue
96
118
}
97
119
if ! printed {
98
- _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Paragraph .Render ("This template has customizable parameters! These can be changed after create, but may have unintended side effects (like data loss)." )+ "\r \n " )
120
+ _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Paragraph .Render ("This template has customizable parameters. Values can be changed after create, but may have unintended side effects (like data loss)." )+ "\r \n " )
99
121
printed = true
100
122
}
101
-
102
123
value , err := cliui .ParameterSchema (cmd , parameterSchema )
103
124
if err != nil {
104
125
return err
@@ -110,11 +131,8 @@ func workspaceCreate() *cobra.Command {
110
131
DestinationScheme : parameterSchema .DefaultDestinationScheme ,
111
132
})
112
133
}
113
- if printed {
114
- _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
115
- _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .FocusedPrompt .String ()+ "Previewing resources..." )
116
- _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
117
- }
134
+ _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
135
+
118
136
resources , err := client .TemplateVersionResources (cmd .Context (), templateVersion .ID )
119
137
if err != nil {
120
138
return err
@@ -123,20 +141,17 @@ func workspaceCreate() *cobra.Command {
123
141
WorkspaceName : workspaceName ,
124
142
// Since agent's haven't connected yet, hiding this makes more sense.
125
143
HideAgentState : true ,
144
+ Title : "Workspace Preview" ,
126
145
})
127
146
if err != nil {
128
147
return err
129
148
}
130
149
131
150
_ , err = cliui .Prompt (cmd , cliui.PromptOptions {
132
- Text : fmt .Sprintf ("Create workspace %s?" , color .HiCyanString (workspaceName )),
133
- Default : "yes" ,
151
+ Text : "Confirm create?" ,
134
152
IsConfirm : true ,
135
153
})
136
154
if err != nil {
137
- if errors .Is (err , promptui .ErrAbort ) {
138
- return nil
139
- }
140
155
return err
141
156
}
142
157
@@ -149,29 +164,26 @@ func workspaceCreate() *cobra.Command {
149
164
if err != nil {
150
165
return err
151
166
}
152
- err = cliui .ProvisionerJob (cmd .Context (), cmd .OutOrStdout (), cliui.ProvisionerJobOptions {
153
- Fetch : func () (codersdk.ProvisionerJob , error ) {
154
- build , err := client .WorkspaceBuild (cmd .Context (), workspace .LatestBuild .ID )
155
- return build .Job , err
156
- },
157
- Cancel : func () error {
158
- return client .CancelWorkspaceBuild (cmd .Context (), workspace .LatestBuild .ID )
159
- },
160
- Logs : func () (<- chan codersdk.ProvisionerJobLog , error ) {
161
- return client .WorkspaceBuildLogsAfter (cmd .Context (), workspace .LatestBuild .ID , before )
162
- },
163
- })
167
+ err = cliui .WorkspaceBuild (cmd .Context (), cmd .OutOrStdout (), client , workspace .LatestBuild .ID , before )
168
+ if err != nil {
169
+ return err
170
+ }
171
+ resources , err = client .WorkspaceResourcesByBuild (cmd .Context (), workspace .LatestBuild .ID )
164
172
if err != nil {
165
173
return err
166
174
}
167
- _ , _ = fmt .Fprintf (cmd .OutOrStdout (), "\n The %s workspace has been created!\n \n " , cliui .Styles .Keyword .Render (workspace .Name ))
168
- _ , _ = fmt .Fprintln (cmd .OutOrStdout (), " " + cliui .Styles .Code .Render ("coder ssh " + workspace .Name ))
169
- _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
170
175
171
- return err
176
+ err = cliui .WorkspaceResources (cmd .OutOrStdout (), resources , cliui.WorkspaceResourcesOptions {
177
+ WorkspaceName : workspaceName ,
178
+ })
179
+ if err != nil {
180
+ return err
181
+ }
182
+ _ , _ = fmt .Fprintf (cmd .OutOrStdout (), "The %s workspace has been created!\n " , cliui .Styles .Keyword .Render (workspace .Name ))
183
+ return nil
172
184
},
173
185
}
174
- cmd .Flags (). StringVarP ( & templateName , "template " , "p " , "" , "Specify a template name." )
186
+ cliflag . StringVarP ( cmd .Flags (), & workspaceName , "name " , "n " , "CODER_WORKSPACE_NAME " , "" , " Specify a workspace name." )
175
187
176
188
return cmd
177
189
}
0 commit comments