Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit592ce3b

Browse files
authored
feat(cli): allow direct tar upload in template update/create (#5720)
1 parent5f7cce7 commit592ce3b

File tree

7 files changed

+174
-75
lines changed

7 files changed

+174
-75
lines changed

‎cli/templatecreate.go

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"time"
1010
"unicode/utf8"
1111

12-
"github.com/briandowns/spinner"
1312
"github.com/google/uuid"
1413
"github.com/spf13/cobra"
1514
"golang.org/x/xerrors"
@@ -19,16 +18,16 @@ import (
1918
"github.com/coder/coder/coderd/util/ptr"
2019
"github.com/coder/coder/codersdk"
2120
"github.com/coder/coder/provisionerd"
22-
"github.com/coder/coder/provisionersdk"
2321
)
2422

2523
functemplateCreate()*cobra.Command {
2624
var (
27-
directorystring
2825
provisionerstring
2926
provisionerTags []string
3027
parameterFilestring
3128
defaultTTL time.Duration
29+
30+
uploadFlagstemplateUploadFlags
3231
)
3332
cmd:=&cobra.Command{
3433
Use:"create [name]",
@@ -45,11 +44,9 @@ func templateCreate() *cobra.Command {
4544
returnerr
4645
}
4746

48-
vartemplateNamestring
49-
iflen(args)==0 {
50-
templateName=filepath.Base(directory)
51-
}else {
52-
templateName=args[0]
47+
templateName,err:=uploadFlags.templateName(args)
48+
iferr!=nil {
49+
returnerr
5350
}
5451

5552
ifutf8.RuneCountInString(templateName)>31 {
@@ -62,31 +59,10 @@ func templateCreate() *cobra.Command {
6259
}
6360

6461
// Confirm upload of the directory.
65-
prettyDir:=prettyDirectoryPath(directory)
66-
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
67-
Text:fmt.Sprintf("Create and upload %q?",prettyDir),
68-
IsConfirm:true,
69-
Default:cliui.ConfirmYes,
70-
})
71-
iferr!=nil {
72-
returnerr
73-
}
74-
75-
spin:=spinner.New(spinner.CharSets[5],100*time.Millisecond)
76-
spin.Writer=cmd.OutOrStdout()
77-
spin.Suffix=cliui.Styles.Keyword.Render(" Uploading directory...")
78-
spin.Start()
79-
deferspin.Stop()
80-
archive,err:=provisionersdk.Tar(directory,provisionersdk.TemplateArchiveLimit)
81-
iferr!=nil {
82-
returnerr
83-
}
84-
85-
resp,err:=client.Upload(cmd.Context(),codersdk.ContentTypeTar,archive)
62+
resp,err:=uploadFlags.upload(cmd,client)
8663
iferr!=nil {
8764
returnerr
8865
}
89-
spin.Stop()
9066

9167
tags,err:=ParseProvisionerTags(provisionerTags)
9268
iferr!=nil {
@@ -105,12 +81,14 @@ func templateCreate() *cobra.Command {
10581
returnerr
10682
}
10783

108-
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
109-
Text:"Confirm create?",
110-
IsConfirm:true,
111-
})
112-
iferr!=nil {
113-
returnerr
84+
if!uploadFlags.stdin() {
85+
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
86+
Text:"Confirm create?",
87+
IsConfirm:true,
88+
})
89+
iferr!=nil {
90+
returnerr
91+
}
11492
}
11593

11694
createReq:= codersdk.CreateTemplateRequest{
@@ -134,12 +112,11 @@ func templateCreate() *cobra.Command {
134112
returnnil
135113
},
136114
}
137-
currentDirectory,_:=os.Getwd()
138-
cmd.Flags().StringVarP(&directory,"directory","d",currentDirectory,"Specify the directory to create from")
139-
cmd.Flags().StringVarP(&provisioner,"test.provisioner","","terraform","Customize the provisioner backend")
140115
cmd.Flags().StringVarP(&parameterFile,"parameter-file","","","Specify a file path with parameter values.")
141116
cmd.Flags().StringArrayVarP(&provisionerTags,"provisioner-tag","", []string{},"Specify a set of tags to target provisioner daemons.")
142117
cmd.Flags().DurationVarP(&defaultTTL,"default-ttl","",24*time.Hour,"Specify a default TTL for workspaces created from this template.")
118+
uploadFlags.register(cmd.Flags())
119+
cmd.Flags().StringVarP(&provisioner,"test.provisioner","","terraform","Customize the provisioner backend")
143120
// This is for testing!
144121
err:=cmd.Flags().MarkHidden("test.provisioner")
145122
iferr!=nil {

‎cli/templatecreate_test.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cli_test
22

33
import (
4+
"bytes"
45
"os"
56
"testing"
67

@@ -69,7 +70,7 @@ func TestTemplateCreate(t *testing.T) {
6970
matchstring
7071
writestring
7172
}{
72-
{match:"Create and upload",write:"yes"},
73+
{match:"Upload",write:"yes"},
7374
{match:"compute.main"},
7475
{match:"smith (linux, i386)"},
7576
{match:"Confirm create?",write:"yes"},
@@ -84,6 +85,38 @@ func TestTemplateCreate(t *testing.T) {
8485
require.NoError(t,<-execDone)
8586
})
8687

88+
t.Run("CreateStdin",func(t*testing.T) {
89+
t.Parallel()
90+
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
91+
coderdtest.CreateFirstUser(t,client)
92+
source,err:=echo.Tar(&echo.Responses{
93+
Parse:echo.ParseComplete,
94+
ProvisionApply:provisionCompleteWithAgent,
95+
})
96+
require.NoError(t,err)
97+
98+
args:= []string{
99+
"templates",
100+
"create",
101+
"my-template",
102+
"--directory","-",
103+
"--test.provisioner",string(database.ProvisionerTypeEcho),
104+
"--default-ttl","24h",
105+
}
106+
cmd,root:=clitest.New(t,args...)
107+
clitest.SetupConfig(t,client,root)
108+
pty:=ptytest.New(t)
109+
cmd.SetIn(bytes.NewReader(source))
110+
cmd.SetOut(pty.Output())
111+
112+
execDone:=make(chanerror)
113+
gofunc() {
114+
execDone<-cmd.Execute()
115+
}()
116+
117+
require.NoError(t,<-execDone)
118+
})
119+
87120
t.Run("WithParameter",func(t*testing.T) {
88121
t.Parallel()
89122
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
@@ -108,7 +141,7 @@ func TestTemplateCreate(t *testing.T) {
108141
matchstring
109142
writestring
110143
}{
111-
{match:"Create and upload",write:"yes"},
144+
{match:"Upload",write:"yes"},
112145
{match:"Enter a value:",write:"bananas"},
113146
{match:"Confirm create?",write:"yes"},
114147
}
@@ -148,7 +181,7 @@ func TestTemplateCreate(t *testing.T) {
148181
matchstring
149182
writestring
150183
}{
151-
{match:"Create and upload",write:"yes"},
184+
{match:"Upload",write:"yes"},
152185
{match:"Confirm create?",write:"yes"},
153186
}
154187
for_,m:=rangematches {
@@ -188,7 +221,7 @@ func TestTemplateCreate(t *testing.T) {
188221
writestring
189222
}{
190223
{
191-
match:"Create and upload",
224+
match:"Upload",
192225
write:"yes",
193226
},
194227
{

‎cli/templatepush.go

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package cli
22

33
import (
44
"fmt"
5+
"io"
56
"os"
67
"path/filepath"
78
"time"
89

910
"github.com/briandowns/spinner"
1011
"github.com/spf13/cobra"
12+
"github.com/spf13/pflag"
1113
"golang.org/x/xerrors"
1214

1315
"github.com/coder/coder/cli/cliui"
@@ -16,14 +18,81 @@ import (
1618
"github.com/coder/coder/provisionersdk"
1719
)
1820

21+
// templateUploadFlags is shared by `templates create` and `templates push`.
22+
typetemplateUploadFlagsstruct {
23+
directorystring
24+
}
25+
26+
func (pf*templateUploadFlags)register(f*pflag.FlagSet) {
27+
currentDirectory,_:=os.Getwd()
28+
f.StringVarP(&pf.directory,"directory","d",currentDirectory,"Specify the directory to create from, use '-' to read tar from stdin")
29+
}
30+
31+
func (pf*templateUploadFlags)stdin()bool {
32+
returnpf.directory=="-"
33+
}
34+
35+
func (pf*templateUploadFlags)upload(cmd*cobra.Command,client*codersdk.Client) (*codersdk.UploadResponse,error) {
36+
var (
37+
content []byte
38+
errerror
39+
)
40+
ifpf.stdin() {
41+
content,err=io.ReadAll(cmd.InOrStdin())
42+
}else {
43+
prettyDir:=prettyDirectoryPath(pf.directory)
44+
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
45+
Text:fmt.Sprintf("Upload %q?",prettyDir),
46+
IsConfirm:true,
47+
Default:cliui.ConfirmYes,
48+
})
49+
iferr!=nil {
50+
returnnil,err
51+
}
52+
53+
content,err=provisionersdk.Tar(pf.directory,provisionersdk.TemplateArchiveLimit)
54+
}
55+
iferr!=nil {
56+
returnnil,xerrors.Errorf("read tar: %w",err)
57+
}
58+
59+
spin:=spinner.New(spinner.CharSets[5],100*time.Millisecond)
60+
spin.Writer=cmd.OutOrStdout()
61+
spin.Suffix=cliui.Styles.Keyword.Render(" Uploading directory...")
62+
spin.Start()
63+
deferspin.Stop()
64+
65+
resp,err:=client.Upload(cmd.Context(),codersdk.ContentTypeTar,content)
66+
iferr!=nil {
67+
returnnil,xerrors.Errorf("upload: %w",err)
68+
}
69+
return&resp,nil
70+
}
71+
72+
func (pf*templateUploadFlags)templateName(args []string) (string,error) {
73+
ifpf.stdin() {
74+
// Can't infer name from directory if none provided.
75+
iflen(args)==0 {
76+
return"",xerrors.New("template name argument must be provided")
77+
}
78+
returnargs[0],nil
79+
}
80+
81+
name:=filepath.Base(pf.directory)
82+
iflen(args)>0 {
83+
name=args[0]
84+
}
85+
returnname,nil
86+
}
87+
1988
functemplatePush()*cobra.Command {
2089
var (
21-
directorystring
2290
versionNamestring
2391
provisionerstring
2492
parameterFilestring
2593
alwaysPromptbool
2694
provisionerTags []string
95+
uploadFlagstemplateUploadFlags
2796
)
2897

2998
cmd:=&cobra.Command{
@@ -40,41 +109,20 @@ func templatePush() *cobra.Command {
40109
returnerr
41110
}
42111

43-
name:=filepath.Base(directory)
44-
iflen(args)>0 {
45-
name=args[0]
46-
}
47-
48-
template,err:=client.TemplateByName(cmd.Context(),organization.ID,name)
112+
name,err:=uploadFlags.templateName(args)
49113
iferr!=nil {
50114
returnerr
51115
}
52116

53-
// Confirm upload of the directory.
54-
prettyDir:=prettyDirectoryPath(directory)
55-
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
56-
Text:fmt.Sprintf("Upload %q?",prettyDir),
57-
IsConfirm:true,
58-
Default:cliui.ConfirmYes,
59-
})
117+
template,err:=client.TemplateByName(cmd.Context(),organization.ID,name)
60118
iferr!=nil {
61119
returnerr
62120
}
63121

64-
spin:=spinner.New(spinner.CharSets[5],100*time.Millisecond)
65-
spin.Writer=cmd.OutOrStdout()
66-
spin.Suffix=cliui.Styles.Keyword.Render(" Uploading directory...")
67-
spin.Start()
68-
deferspin.Stop()
69-
content,err:=provisionersdk.Tar(directory,provisionersdk.TemplateArchiveLimit)
122+
resp,err:=uploadFlags.upload(cmd,client)
70123
iferr!=nil {
71124
returnerr
72125
}
73-
resp,err:=client.Upload(cmd.Context(),codersdk.ContentTypeTar,content)
74-
iferr!=nil {
75-
returnerr
76-
}
77-
spin.Stop()
78126

79127
tags,err:=ParseProvisionerTags(provisionerTags)
80128
iferr!=nil {
@@ -112,13 +160,12 @@ func templatePush() *cobra.Command {
112160
},
113161
}
114162

115-
currentDirectory,_:=os.Getwd()
116-
cmd.Flags().StringVarP(&directory,"directory","d",currentDirectory,"Specify the directory to create from")
117163
cmd.Flags().StringVarP(&provisioner,"test.provisioner","","terraform","Customize the provisioner backend")
118164
cmd.Flags().StringVarP(&parameterFile,"parameter-file","","","Specify a file path with parameter values.")
119165
cmd.Flags().StringVarP(&versionName,"name","","","Specify a name for the new template version. It will be automatically generated if not provided.")
120166
cmd.Flags().StringArrayVarP(&provisionerTags,"provisioner-tag","", []string{},"Specify a set of tags to target provisioner daemons.")
121167
cmd.Flags().BoolVar(&alwaysPrompt,"always-prompt",false,"Always prompt all parameters. Does not pull parameter values from active template version")
168+
uploadFlags.register(cmd.Flags())
122169
cliui.AllowSkipPrompt(cmd)
123170
// This is for testing!
124171
err:=cmd.Flags().MarkHidden("test.provisioner")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp