|
1 | 1 | package cli
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "errors" |
5 | 4 | "fmt"
|
6 |
| - "io" |
7 |
| - "strings" |
8 |
| - "time" |
9 |
| - |
10 |
| - "github.com/google/uuid" |
11 |
| - "golang.org/x/xerrors" |
12 |
| - |
13 |
| - "github.com/coder/pretty" |
14 | 5 |
|
15 | 6 | "github.com/coder/coder/v2/cli/clibase"
|
16 | 7 | "github.com/coder/coder/v2/cli/cliui"
|
17 |
| - "github.com/coder/coder/v2/codersdk" |
| 8 | + "github.com/coder/pretty" |
18 | 9 | )
|
19 | 10 |
|
20 |
| -func (r *RootCmd) templateCreate() *clibase.Cmd { |
21 |
| - var ( |
22 |
| - provisioner string |
23 |
| - provisionerTags []string |
24 |
| - variablesFile string |
25 |
| - commandLineVariables []string |
26 |
| - versionName string |
27 |
| - |
28 |
| - uploadFlags templateUploadFlags |
29 |
| - ) |
30 |
| - client := new(codersdk.Client) |
| 11 | +func (*RootCmd) templateCreate() *clibase.Cmd { |
31 | 12 | cmd := &clibase.Cmd{
|
32 |
| - Use: "create [name]", |
33 |
| - Short: "Create a template from the current directory or as specified by flag", |
34 |
| - Middleware: clibase.Chain( |
35 |
| - clibase.RequireRangeArgs(0, 1), |
36 |
| - r.InitClient(client), |
37 |
| - ), |
| 13 | + Use: "create [name]", |
| 14 | + Short: "Create a template from the current directory or as specified by flag", |
| 15 | + Hidden: true, |
38 | 16 | Handler: func(inv *clibase.Invocation) error {
|
39 | 17 | _, _ = fmt.Fprintln(inv.Stdout, "\n"+pretty.Sprint(cliui.DefaultStyles.Wrap,
|
40 | 18 | pretty.Sprint(
|
41 |
| - cliui.DefaultStyles.Warn, "DEPRECATION WARNING: The `coder templates push` command should be used instead. This command will be removed in a future release. ")+"\n")) |
42 |
| - time.Sleep(1 * time.Second) |
43 |
| - |
44 |
| - organization, err := CurrentOrganization(inv, client) |
45 |
| - if err != nil { |
46 |
| - return err |
47 |
| - } |
48 |
| - |
49 |
| - name, err := uploadFlags.templateName(inv.Args) |
50 |
| - if err != nil { |
51 |
| - return err |
52 |
| - } |
53 |
| - |
54 |
| - job, _, err := createTemplateVersion(createTemplateVersionArgs{ |
55 |
| - inv: inv, |
56 |
| - client: client, |
57 |
| - name: name, |
58 |
| - org: organization, |
59 |
| - uploadFlags: uploadFlags, |
60 |
| - provisionerTags: provisionerTags, |
61 |
| - provisioner: provisioner, |
62 |
| - variablesFile: variablesFile, |
63 |
| - commandLineVariables: commandLineVariables, |
64 |
| - versionName: versionName, |
65 |
| - alwaysPrompt: false, |
66 |
| - }) |
67 |
| - if err != nil { |
68 |
| - return err |
69 |
| - } |
70 |
| - |
71 |
| - if !uploadFlags.stdin() { |
72 |
| - _, err = cliui.Prompt(inv, cliui.PromptOptions{ |
73 |
| - Text: "Confirm create?", |
74 |
| - IsConfirm: true, |
75 |
| - }) |
76 |
| - if err != nil { |
77 |
| - return err |
78 |
| - } |
79 |
| - } |
80 |
| - |
81 |
| - createReq := codersdk.CreateTemplateRequest{ |
82 |
| - Name: name, |
83 |
| - VersionID: job.ID, |
84 |
| - } |
85 |
| - |
86 |
| - _, err = client.CreateTemplate(inv.Context(), organization.ID, createReq) |
87 |
| - if err != nil { |
88 |
| - return err |
89 |
| - } |
90 |
| - |
91 |
| - _, _ = fmt.Fprintln(inv.Stdout, "\n"+pretty.Sprint(cliui.DefaultStyles.Wrap, |
92 |
| - "The "+pretty.Sprint( |
93 |
| - cliui.DefaultStyles.Keyword, name)+" template has been created at "+ |
94 |
| - pretty.Sprint(cliui.DefaultStyles.DateTimeStamp, time.Now().Format(time.Stamp))+"! "+ |
95 |
| - "Developers can provision a workspace with this template using:")+"\n") |
96 |
| - |
97 |
| - _, _ = fmt.Fprintln(inv.Stdout, " "+pretty.Sprint(cliui.DefaultStyles.Code, fmt.Sprintf("coder create --template=%q [workspace name]", name))) |
98 |
| - _, _ = fmt.Fprintln(inv.Stdout) |
99 |
| - |
| 19 | + cliui.DefaultStyles.Error, |
| 20 | + "ERROR: The `coder templates create` command has been removed."+ |
| 21 | + "Use the `coder templates push` command to create and update templates. "+ |
| 22 | + "Use the `coder templates edit` command to change template settings."))) |
100 | 23 | return nil
|
101 | 24 | },
|
102 | 25 | }
|
103 |
| - cmd.Options = clibase.OptionSet{ |
104 |
| - { |
105 |
| - Flag: "variables-file", |
106 |
| - Description: "Specify a file path with values for Terraform-managed variables.", |
107 |
| - Value: clibase.StringOf(&variablesFile), |
108 |
| - }, |
109 |
| - { |
110 |
| - Flag: "variable", |
111 |
| - Description: "Specify a set of values for Terraform-managed variables.", |
112 |
| - Value: clibase.StringArrayOf(&commandLineVariables), |
113 |
| - }, |
114 |
| - { |
115 |
| - Flag: "var", |
116 |
| - Description: "Alias of --variable.", |
117 |
| - Value: clibase.StringArrayOf(&commandLineVariables), |
118 |
| - }, |
119 |
| - { |
120 |
| - Flag: "provisioner-tag", |
121 |
| - Description: "Specify a set of tags to target provisioner daemons.", |
122 |
| - Value: clibase.StringArrayOf(&provisionerTags), |
123 |
| - }, |
124 |
| - { |
125 |
| - Flag: "test.provisioner", |
126 |
| - Description: "Customize the provisioner backend.", |
127 |
| - Default: "terraform", |
128 |
| - Value: clibase.StringOf(&provisioner), |
129 |
| - Hidden: true, |
130 |
| - }, |
131 |
| - { |
132 |
| - Flag: "name", |
133 |
| - Description: "Specify a name for the new template version. It will be automatically generated if not provided.", |
134 |
| - Value: clibase.StringOf(&versionName), |
135 |
| - }, |
136 | 26 |
|
137 |
| - cliui.SkipPromptOption(), |
138 |
| - } |
139 |
| - cmd.Options = append(cmd.Options, uploadFlags.options()...) |
140 | 27 | return cmd
|
141 | 28 | }
|
142 |
| - |
143 |
| -type createValidTemplateVersionArgs struct { |
144 |
| - Name string |
145 |
| - Message string |
146 |
| - Client *codersdk.Client |
147 |
| - Organization codersdk.Organization |
148 |
| - Provisioner codersdk.ProvisionerType |
149 |
| - FileID uuid.UUID |
150 |
| - |
151 |
| - // Template is only required if updating a template's active version. |
152 |
| - Template *codersdk.Template |
153 |
| - // ReuseParameters will attempt to reuse params from the Template field |
154 |
| - // before prompting the user. Set to false to always prompt for param |
155 |
| - // values. |
156 |
| - ReuseParameters bool |
157 |
| - ProvisionerTags map[string]string |
158 |
| - UserVariableValues []codersdk.VariableValue |
159 |
| -} |
160 |
| - |
161 |
| -func createValidTemplateVersion(inv *clibase.Invocation, args createValidTemplateVersionArgs) (*codersdk.TemplateVersion, error) { |
162 |
| - client := args.Client |
163 |
| - |
164 |
| - req := codersdk.CreateTemplateVersionRequest{ |
165 |
| - Name: args.Name, |
166 |
| - Message: args.Message, |
167 |
| - StorageMethod: codersdk.ProvisionerStorageMethodFile, |
168 |
| - FileID: args.FileID, |
169 |
| - Provisioner: args.Provisioner, |
170 |
| - ProvisionerTags: args.ProvisionerTags, |
171 |
| - UserVariableValues: args.UserVariableValues, |
172 |
| - } |
173 |
| - if args.Template != nil { |
174 |
| - req.TemplateID = args.Template.ID |
175 |
| - } |
176 |
| - version, err := client.CreateTemplateVersion(inv.Context(), args.Organization.ID, req) |
177 |
| - if err != nil { |
178 |
| - return nil, err |
179 |
| - } |
180 |
| - |
181 |
| - err = cliui.ProvisionerJob(inv.Context(), inv.Stdout, cliui.ProvisionerJobOptions{ |
182 |
| - Fetch: func() (codersdk.ProvisionerJob, error) { |
183 |
| - version, err := client.TemplateVersion(inv.Context(), version.ID) |
184 |
| - return version.Job, err |
185 |
| - }, |
186 |
| - Cancel: func() error { |
187 |
| - return client.CancelTemplateVersion(inv.Context(), version.ID) |
188 |
| - }, |
189 |
| - Logs: func() (<-chan codersdk.ProvisionerJobLog, io.Closer, error) { |
190 |
| - return client.TemplateVersionLogsAfter(inv.Context(), version.ID, 0) |
191 |
| - }, |
192 |
| - }) |
193 |
| - if err != nil { |
194 |
| - var jobErr *cliui.ProvisionerJobError |
195 |
| - if errors.As(err, &jobErr) && !codersdk.JobIsMissingParameterErrorCode(jobErr.Code) { |
196 |
| - return nil, err |
197 |
| - } |
198 |
| - if err != nil { |
199 |
| - return nil, err |
200 |
| - } |
201 |
| - } |
202 |
| - version, err = client.TemplateVersion(inv.Context(), version.ID) |
203 |
| - if err != nil { |
204 |
| - return nil, err |
205 |
| - } |
206 |
| - |
207 |
| - if version.Job.Status != codersdk.ProvisionerJobSucceeded { |
208 |
| - return nil, xerrors.New(version.Job.Error) |
209 |
| - } |
210 |
| - |
211 |
| - resources, err := client.TemplateVersionResources(inv.Context(), version.ID) |
212 |
| - if err != nil { |
213 |
| - return nil, err |
214 |
| - } |
215 |
| - |
216 |
| - // Only display the resources on the start transition, to avoid listing them more than once. |
217 |
| - var startResources []codersdk.WorkspaceResource |
218 |
| - for _, r := range resources { |
219 |
| - if r.Transition == codersdk.WorkspaceTransitionStart { |
220 |
| - startResources = append(startResources, r) |
221 |
| - } |
222 |
| - } |
223 |
| - err = cliui.WorkspaceResources(inv.Stdout, startResources, cliui.WorkspaceResourcesOptions{ |
224 |
| - HideAgentState: true, |
225 |
| - HideAccess: true, |
226 |
| - Title: "Template Preview", |
227 |
| - }) |
228 |
| - if err != nil { |
229 |
| - return nil, xerrors.Errorf("preview template resources: %w", err) |
230 |
| - } |
231 |
| - |
232 |
| - return &version, nil |
233 |
| -} |
234 |
| - |
235 |
| -func ParseProvisionerTags(rawTags []string) (map[string]string, error) { |
236 |
| - tags := map[string]string{} |
237 |
| - for _, rawTag := range rawTags { |
238 |
| - parts := strings.SplitN(rawTag, "=", 2) |
239 |
| - if len(parts) < 2 { |
240 |
| - return nil, xerrors.Errorf("invalid tag format for %q. must be key=value", rawTag) |
241 |
| - } |
242 |
| - tags[parts[0]] = parts[1] |
243 |
| - } |
244 |
| - return tags, nil |
245 |
| -} |
0 commit comments