Skip to content

Commit aa42b7f

Browse files
committed
add nodeset capabilities to sshproxyctl
1 parent 50c8564 commit aa42b7f

31 files changed

+3592
-30
lines changed

cmd/sshproxyctl/sshproxyctl.go

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/cea-hpc/sshproxy/pkg/utils"
2626

27+
"github.com/iskylite/nodeset"
2728
"github.com/olekukonko/tablewriter"
2829
)
2930

@@ -502,7 +503,8 @@ func newEnableParser() *flag.FlagSet {
502503
fs.Usage = func() {
503504
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s enable HOST [PORT]
504505
505-
Enable a previously disabled host in etcd. The default port is %s.
506+
Enable a previously disabled host in etcd. The default port is %s. Host and port
507+
can be nodesets.
506508
`, os.Args[0], defaultHostPort)
507509
os.Exit(2)
508510
}
@@ -515,7 +517,7 @@ func newForgetParser() *flag.FlagSet {
515517
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s forget HOST [PORT]
516518
517519
Forget a host in etcd. The default port is %s. Remember that if this host is
518-
used, it will appear back in the list.
520+
used, it will appear back in the list. Host and port can be nodesets.
519521
`, os.Args[0], defaultHostPort)
520522
os.Exit(2)
521523
}
@@ -527,7 +529,7 @@ func newDisableParser() *flag.FlagSet {
527529
fs.Usage = func() {
528530
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s disable HOST [PORT]
529531
530-
Disabe a host in etcd. The default port is %s.
532+
Disabe a host in etcd. The default port is %s. Host and port can be nodesets.
531533
`, os.Args[0], defaultHostPort)
532534
os.Exit(2)
533535
}
@@ -550,25 +552,37 @@ The options are:
550552
return fs
551553
}
552554

553-
func getHostPortFromCommandLine(args []string) (string, string, error) {
554-
host, port := "", defaultHostPort
555+
func getHostPortFromCommandLine(args []string) ([]string, []string, error) {
556+
hostsNodeset, portsNodeset := "", defaultHostPort
555557
switch len(args) {
556558
case 2:
557-
host, port = args[0], args[1]
559+
hostsNodeset, portsNodeset = args[0], args[1]
558560
case 1:
559-
host = args[0]
561+
hostsNodeset = args[0]
560562
default:
561-
return "", "", fmt.Errorf("wrong number of arguments")
563+
return []string{}, []string{}, fmt.Errorf("wrong number of arguments")
562564
}
563-
if iport, err := strconv.Atoi(port); err != nil {
564-
return "", "", fmt.Errorf("port must be an integer")
565-
} else if iport < 0 || iport > 65535 {
566-
return "", "", fmt.Errorf("port must be in the 0-65535 range")
565+
hosts, err := nodeset.Expand(hostsNodeset)
566+
if err != nil {
567+
return []string{}, []string{}, fmt.Errorf("%s", err)
568+
}
569+
ports, err := nodeset.Expand(portsNodeset)
570+
if err != nil {
571+
return []string{}, []string{}, fmt.Errorf("%s", err)
567572
}
568-
if _, _, err := net.SplitHostPort(host + ":" + port); err != nil {
569-
return "", "", fmt.Errorf("%s", err)
573+
for _, port := range ports {
574+
if iport, err := strconv.Atoi(port); err != nil {
575+
return []string{}, []string{}, fmt.Errorf("port \"%s\" must be an integer", port)
576+
} else if iport < 0 || iport > 65535 {
577+
return []string{}, []string{}, fmt.Errorf("port \"%s\" must be in the 0-65535 range", port)
578+
}
579+
for _, host := range hosts {
580+
if _, _, err := net.SplitHostPort(host + ":" + port); err != nil {
581+
return []string{}, []string{}, fmt.Errorf("%s", err)
582+
}
583+
}
570584
}
571-
return host, port, nil
585+
return hosts, ports, nil
572586
}
573587

574588
func getErrorBannerFromCommandLine(args []string) (string, error) {
@@ -691,30 +705,42 @@ func main() {
691705
case "enable":
692706
p := parsers[cmd]
693707
p.Parse(args)
694-
host, port, err := getHostPortFromCommandLine(p.Args())
708+
hosts, ports, err := getHostPortFromCommandLine(p.Args())
695709
if err != nil {
696710
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
697711
p.Usage()
698712
}
699-
enableHost(host, port, *configFile)
713+
for _, host := range hosts {
714+
for _, port := range ports {
715+
enableHost(host, port, *configFile)
716+
}
717+
}
700718
case "forget":
701719
p := parsers[cmd]
702720
p.Parse(args)
703-
host, port, err := getHostPortFromCommandLine(p.Args())
721+
hosts, ports, err := getHostPortFromCommandLine(p.Args())
704722
if err != nil {
705723
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
706724
p.Usage()
707725
}
708-
forgetHost(host, port, *configFile)
726+
for _, host := range hosts {
727+
for _, port := range ports {
728+
forgetHost(host, port, *configFile)
729+
}
730+
}
709731
case "disable":
710732
p := parsers[cmd]
711733
p.Parse(args)
712-
host, port, err := getHostPortFromCommandLine(p.Args())
734+
hosts, ports, err := getHostPortFromCommandLine(p.Args())
713735
if err != nil {
714736
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
715737
p.Usage()
716738
}
717-
disableHost(host, port, *configFile)
739+
for _, host := range hosts {
740+
for _, port := range ports {
741+
disableHost(host, port, *configFile)
742+
}
743+
}
718744
case "error_banner":
719745
p := parsers[cmd]
720746
p.Parse(args)

doc/sshproxyctl.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,20 @@ COMMANDS
4040
Show version number and exit.
4141

4242
*enable HOST [PORT]*::
43-
Enable a destination host in etcd. The host was previously disabled by
43+
Enable a destination host in etcd if the host was previously disabled by
4444
the 'disable' command (see below). The port by default is 22 if not
45-
specified.
45+
specified. Host and port can be nodesets.
4646

4747
*disable HOST [PORT]*::
4848
Disable a destination host in etcd. A disabled host will not be
4949
proposed as a destination. The only way to enable it again is to send
5050
the 'enable' command. It could be used for host maintenance. The port
51-
by default is 22 if not specified.
51+
by default is 22 if not specified. Host and port can be nodesets.
5252

5353
*forget HOST [PORT]*::
54-
Forget a host in etcd. The default port is 22. Remember that if this
55-
host is used, it will appear back in the list.
54+
Forget a host in etcd. Remember that if this host is used, it will
55+
appear back in the list. The port by default is 22 if not specified.
56+
Host and port can be nodesets.
5657

5758
*error_banner [-expire] MESSAGE*::
5859
Set the error banner in etcd. Removes the error banner in etcd if

go.mod

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ go 1.21
44

55
require (
66
github.com/creack/pty v1.1.20
7+
github.com/iskylite/nodeset v1.0.1
78
github.com/moby/term v0.5.0
89
github.com/olekukonko/tablewriter v0.0.5
910
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
1011
go.etcd.io/etcd/client/v3 v3.5.10
12+
go.uber.org/zap v1.17.0
13+
google.golang.org/grpc v1.58.3
1114
gopkg.in/yaml.v2 v2.4.0
1215
)
1316

@@ -18,17 +21,17 @@ require (
1821
github.com/gogo/protobuf v1.3.2 // indirect
1922
github.com/golang/protobuf v1.5.3 // indirect
2023
github.com/mattn/go-runewidth v0.0.9 // indirect
24+
github.com/segmentio/fasthash v1.0.3 // indirect
25+
github.com/willf/bitset v1.1.10 // indirect
2126
go.etcd.io/etcd/api/v3 v3.5.10 // indirect
2227
go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
2328
go.uber.org/atomic v1.7.0 // indirect
2429
go.uber.org/multierr v1.6.0 // indirect
25-
go.uber.org/zap v1.17.0 // indirect
2630
golang.org/x/net v0.17.0 // indirect
2731
golang.org/x/sys v0.13.0 // indirect
2832
golang.org/x/text v0.13.0 // indirect
2933
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
3034
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
3135
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
32-
google.golang.org/grpc v1.58.3 // indirect
3336
google.golang.org/protobuf v1.31.0 // indirect
3437
)

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
1818
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
1919
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
2020
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
21+
github.com/iskylite/nodeset v1.0.1 h1:2yif2U3tyioRQyWSYSRVC47DUL0Raib4Ej+tEZIFlLs=
22+
github.com/iskylite/nodeset v1.0.1/go.mod h1:PCZzSaZBqVBbiHxCJb4PVHl7m6C5+5DrD1EVMl5+Clw=
2123
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
2224
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
2325
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@@ -32,11 +34,15 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
3234
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3335
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3436
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
37+
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
38+
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
3539
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
3640
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
3741
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3842
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
3943
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
44+
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
45+
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
4046
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
4147
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
4248
go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k=

test/centos-image/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ FROM fedora:latest
33
# Install development environment to compile RPM
44
RUN set -ex \
55
&& yum -y update \
6-
&& yum -y install asciidoc etcd git golang hostname iproute make openssh-server rpm-build
6+
&& yum -y install asciidoc etcd git golang hostname iproute make openssh-server rpm-build procps
77

88
# Create centos, user1 and user2 users ; centos and user1 groups
99
RUN set -ex \

test/centos-image/sshproxy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ func TestEnableDisableHost(t *testing.T) {
596596
t.Errorf("%s got %s, expected server1", cmdStr, dest)
597597
}
598598

599-
disableHost("server1")
599+
disableHost("server[1,100]")
600600
checkHostState(t, "server1", "disabled")
601601

602602
_, stdout, _, err = runCommand(ctx, "ssh", args, nil, nil)

vendor/github.com/iskylite/nodeset/.gitattributes

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/iskylite/nodeset/.gitignore

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)