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

Commitd3ccb07

Browse files
JoshVeemafredri
andauthored
feat(cli): support header and header-command in config-ssh (#10413)
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parentd6cdaae commitd3ccb07

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

‎cli/configssh.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/cli/safeexec"
2020
"github.com/pkg/diff"
2121
"github.com/pkg/diff/write"
22+
"golang.org/x/exp/constraints"
2223
"golang.org/x/exp/slices"
2324
"golang.org/x/sync/errgroup"
2425
"golang.org/x/xerrors"
@@ -51,6 +52,8 @@ type sshConfigOptions struct {
5152
userHostPrefixstring
5253
sshOptions []string
5354
disableAutostartbool
55+
header []string
56+
headerCommandstring
5457
}
5558

5659
// addOptions expects options in the form of "option=value" or "option value".
@@ -100,15 +103,25 @@ func (o *sshConfigOptions) addOption(option string) error {
100103
}
101104

102105
func (osshConfigOptions)equal(othersshConfigOptions)bool {
103-
// Compare without side-effects or regard to order.
104-
opt1:=slices.Clone(o.sshOptions)
105-
sort.Strings(opt1)
106-
opt2:=slices.Clone(other.sshOptions)
107-
sort.Strings(opt2)
108-
if!slices.Equal(opt1,opt2) {
106+
if!slicesSortedEqual(o.sshOptions,other.sshOptions) {
109107
returnfalse
110108
}
111-
returno.waitEnum==other.waitEnum&&o.userHostPrefix==other.userHostPrefix&&o.disableAutostart==other.disableAutostart
109+
if!slicesSortedEqual(o.header,other.header) {
110+
returnfalse
111+
}
112+
returno.waitEnum==other.waitEnum&&o.userHostPrefix==other.userHostPrefix&&o.disableAutostart==other.disableAutostart&&o.headerCommand==other.headerCommand
113+
}
114+
115+
// slicesSortedEqual compares two slices without side-effects or regard to order.
116+
funcslicesSortedEqual[S~[]E,E constraints.Ordered](a,bS)bool {
117+
iflen(a)!=len(b) {
118+
returnfalse
119+
}
120+
a=slices.Clone(a)
121+
slices.Sort(a)
122+
b=slices.Clone(b)
123+
slices.Sort(b)
124+
returnslices.Equal(a,b)
112125
}
113126

114127
func (osshConfigOptions)asList() (list []string) {
@@ -124,6 +137,13 @@ func (o sshConfigOptions) asList() (list []string) {
124137
for_,opt:=rangeo.sshOptions {
125138
list=append(list,fmt.Sprintf("ssh-option: %s",opt))
126139
}
140+
for_,h:=rangeo.header {
141+
list=append(list,fmt.Sprintf("header: %s",h))
142+
}
143+
ifo.headerCommand!="" {
144+
list=append(list,fmt.Sprintf("header-command: %s",o.headerCommand))
145+
}
146+
127147
returnlist
128148
}
129149

@@ -230,6 +250,8 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
230250
// specifies skip-proxy-command, then wait cannot be applied.
231251
returnxerrors.Errorf("cannot specify both --skip-proxy-command and --wait")
232252
}
253+
sshConfigOpts.header=r.header
254+
sshConfigOpts.headerCommand=r.headerCommand
233255

234256
recvWorkspaceConfigs:=sshPrepareWorkspaceConfigs(inv.Context(),client)
235257

@@ -393,6 +415,14 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
393415
}
394416

395417
if!skipProxyCommand {
418+
rootFlags:=fmt.Sprintf("--global-config %s",escapedGlobalConfig)
419+
for_,h:=rangesshConfigOpts.header {
420+
rootFlags+=fmt.Sprintf(" --header %q",h)
421+
}
422+
ifsshConfigOpts.headerCommand!="" {
423+
rootFlags+=fmt.Sprintf(" --header-command %q",sshConfigOpts.headerCommand)
424+
}
425+
396426
flags:=""
397427
ifsshConfigOpts.waitEnum!="auto" {
398428
flags+=" --wait="+sshConfigOpts.waitEnum
@@ -401,8 +431,8 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
401431
flags+=" --disable-autostart=true"
402432
}
403433
defaultOptions=append(defaultOptions,fmt.Sprintf(
404-
"ProxyCommand %s--global-config%s ssh --stdio%s %s",
405-
escapedCoderBinary,escapedGlobalConfig,flags,workspaceHostname,
434+
"ProxyCommand %s %s ssh --stdio%s %s",
435+
escapedCoderBinary,rootFlags,flags,workspaceHostname,
406436
))
407437
}
408438

@@ -623,6 +653,12 @@ func sshConfigWriteSectionHeader(w io.Writer, addNewline bool, o sshConfigOption
623653
for_,opt:=rangeo.sshOptions {
624654
_,_=fmt.Fprintf(&ow,"# :%s=%s\n","ssh-option",opt)
625655
}
656+
for_,h:=rangeo.header {
657+
_,_=fmt.Fprintf(&ow,"# :%s=%s\n","header",h)
658+
}
659+
ifo.headerCommand!="" {
660+
_,_=fmt.Fprintf(&ow,"# :%s=%s\n","header-command",o.headerCommand)
661+
}
626662
ifow.Len()>0 {
627663
_,_=fmt.Fprint(w,sshConfigOptionsHeader)
628664
_,_=fmt.Fprint(w,ow.String())
@@ -654,6 +690,10 @@ func sshConfigParseLastOptions(r io.Reader) (o sshConfigOptions) {
654690
o.sshOptions=append(o.sshOptions,parts[1])
655691
case"disable-autostart":
656692
o.disableAutostart,_=strconv.ParseBool(parts[1])
693+
case"header":
694+
o.header=append(o.header,parts[1])
695+
case"header-command":
696+
o.headerCommand=parts[1]
657697
default:
658698
// Unknown option, ignore.
659699
}

‎cli/configssh_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
462462
"# Last config-ssh options:",
463463
"# :wait=yes",
464464
"# :ssh-host-prefix=coder-test.",
465+
"# :header=X-Test-Header=foo",
466+
"# :header=X-Test-Header2=bar",
467+
"# :header-command=printf h1=v1 h2=\"v2\" h3='v3'",
465468
"#",
466469
headerEnd,
467470
"",
@@ -471,6 +474,9 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
471474
"--yes",
472475
"--wait=yes",
473476
"--ssh-host-prefix","coder-test.",
477+
"--header","X-Test-Header=foo",
478+
"--header","X-Test-Header2=bar",
479+
"--header-command","printf h1=v1 h2=\"v2\" h3='v3'",
474480
},
475481
},
476482
{
@@ -563,6 +569,55 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
563569
regexMatch:"ProxyCommand /foo/bar/coder",
564570
},
565571
},
572+
{
573+
name:"Header",
574+
args: []string{
575+
"--yes",
576+
"--header","X-Test-Header=foo",
577+
"--header","X-Test-Header2=bar",
578+
},
579+
wantErr:false,
580+
hasAgent:true,
581+
wantConfig:wantConfig{
582+
regexMatch:`ProxyCommand .* --header "X-Test-Header=foo" --header "X-Test-Header2=bar" ssh`,
583+
},
584+
},
585+
{
586+
name:"Header command",
587+
args: []string{
588+
"--yes",
589+
"--header-command","printf h1=v1",
590+
},
591+
wantErr:false,
592+
hasAgent:true,
593+
wantConfig:wantConfig{
594+
regexMatch:`ProxyCommand .* --header-command "printf h1=v1" ssh`,
595+
},
596+
},
597+
{
598+
name:"Header command with double quotes",
599+
args: []string{
600+
"--yes",
601+
"--header-command","printf h1=v1 h2=\"v2\"",
602+
},
603+
wantErr:false,
604+
hasAgent:true,
605+
wantConfig:wantConfig{
606+
regexMatch:`ProxyCommand .* --header-command "printf h1=v1 h2=\\\"v2\\\"" ssh`,
607+
},
608+
},
609+
{
610+
name:"Header command with single quotes",
611+
args: []string{
612+
"--yes",
613+
"--header-command","printf h1=v1 h2='v2'",
614+
},
615+
wantErr:false,
616+
hasAgent:true,
617+
wantConfig:wantConfig{
618+
regexMatch:`ProxyCommand .* --header-command "printf h1=v1 h2='v2'" ssh`,
619+
},
620+
},
566621
}
567622
for_,tt:=rangetests {
568623
tt:=tt

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp