Skip to content

Commit 2e4de52

Browse files
committed
add migrate command to sshproxyctl
1 parent a49296b commit 2e4de52

11 files changed

+485
-118
lines changed

README.asciidoc

+3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ Version 2 brings a lot of changes to sshproxy:
143143
connection to the destination. If the command does not return 0, the
144144
connection is aborted
145145
2. command line interface:
146+
- `sshproxyctl convert` has been added: it converts your old v1
147+
configuration file to the v2 format. Can be used like this:
148+
`sshproxyctl -c /etc/sshproxy/sshproxy.old.yaml convert > /etc/sshproxy/sshproxy.new.yaml`
146149
- in all the tables, `Host` and `Port` columns are now merged into a single
147150
`Host:Port`
148151
- `sshproxyctl get_config` has been removed and replaced by

cmd/sshproxy/sshproxy.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ var log = logging.MustGetLogger("sshproxy")
4646

4747
type etcdChecker struct {
4848
LastState utils.State
49-
checkInterval utils.Duration
49+
checkInterval time.Duration
5050
cli *utils.Client
5151
}
5252

@@ -68,7 +68,7 @@ func (c *etcdChecker) Check(hostport string) bool {
6868
c.LastState = c.doCheck(hostport)
6969
case host.State == utils.Disabled:
7070
c.LastState = host.State
71-
case ts.Sub(host.Ts) > c.checkInterval.Duration():
71+
case ts.Sub(host.Ts) > c.checkInterval:
7272
c.LastState = c.doCheck(hostport)
7373
default:
7474
c.LastState = host.State
@@ -478,7 +478,7 @@ func mainExitCode() int {
478478

479479
var recorder *Recorder
480480
if config.Dump != "" {
481-
recorder = NewRecorder(conninfo, config.Dump, doCmd, config.EtcdStatsInterval.Duration(), config.LogStatsInterval.Duration(), config.DumpLimitSize, config.DumpLimitWindow.Duration())
481+
recorder = NewRecorder(conninfo, config.Dump, doCmd, config.EtcdStatsInterval, config.LogStatsInterval, config.DumpLimitSize, config.DumpLimitWindow)
482482

483483
wg.Add(1)
484484
go func() {

cmd/sshproxyctl/sshproxyctl.go

+26
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ The commands are:
601601
forget forget a host/error_banner in etcd
602602
disable disable a host in etcd
603603
error_banner set the error banner in etcd
604+
convert displays the config, converted from v1 to v2
604605
605606
The common options are:
606607
`, os.Args[0])
@@ -728,6 +729,20 @@ The options are:
728729
return fs
729730
}
730731

732+
func newConvertParser() *flag.FlagSet {
733+
fs := flag.NewFlagSet("convert", flag.ExitOnError)
734+
fs.Usage = func() {
735+
fmt.Fprintf(flag.CommandLine.Output(), `Usage: %s convert
736+
737+
Show configuration converted from v1 to v2 and exit.
738+
Should be used like this:
739+
%s -c %s.old convert > %s.new
740+
`, os.Args[0], os.Args[0], defaultConfig, defaultConfig)
741+
os.Exit(2)
742+
}
743+
return fs
744+
}
745+
731746
func getHostPortFromCommandLine(allFlag bool, hostsNodeset string, portsNodeset string, configFile string) ([]string, error) {
732747
_, nodesetDlclose, nodesetExpand := nodesets.InitExpander()
733748
defer nodesetDlclose()
@@ -875,6 +890,7 @@ func main() {
875890
"forget": newForgetParser(&allFlag, &hostString, &portString),
876891
"disable": newDisableParser(&allFlag, &hostString, &portString),
877892
"error_banner": newErrorBannerParser(&expire),
893+
"convert": newConvertParser(),
878894
}
879895

880896
cmd := flag.Arg(0)
@@ -1016,6 +1032,16 @@ func main() {
10161032
p.Usage()
10171033
}
10181034
setErrorBanner(errorBanner, t, *configFile)
1035+
case "convert":
1036+
p := parsers[cmd]
1037+
p.Parse(args)
1038+
yamlOutput, err := utils.ConvertConfigV1(*configFile)
1039+
if err != nil {
1040+
fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
1041+
usage()
1042+
}
1043+
fmt.Println("---")
1044+
fmt.Print(string(yamlOutput[:]))
10191045
default:
10201046
fmt.Fprintf(os.Stderr, "ERROR: unknown command: %s\n\n", cmd)
10211047
usage()

doc/sshproxyctl.txt

+3
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ COMMANDS
105105
(host[:port]) is given with the '-source' option, the configuration
106106
will be calculated for this specific source.
107107

108+
*convert*::
109+
Displays the configuration, converted from v1 to v2.
110+
108111

109112
FILES
110113
-----

pkg/utils/config.go

+67-67
Original file line numberDiff line numberDiff line change
@@ -41,54 +41,54 @@ var cachedConfig Config
4141

4242
// Config represents the configuration for sshproxy.
4343
type Config struct {
44-
ready bool // true when the configuration has already been loaded
45-
Nodeset string
46-
Debug bool
47-
Log string
48-
CheckInterval Duration `yaml:"check_interval"`
49-
ErrorBanner string `yaml:"error_banner"`
50-
Dump string
51-
DumpLimitSize uint64 `yaml:"dump_limit_size"`
52-
DumpLimitWindow Duration `yaml:"dump_limit_window"`
53-
Etcd etcdConfig
54-
EtcdStatsInterval Duration `yaml:"etcd_stats_interval"`
55-
LogStatsInterval Duration `yaml:"log_stats_interval"`
56-
BlockingCommand string `yaml:"blocking_command"`
57-
BgCommand string `yaml:"bg_command"`
58-
SSH sshConfig
59-
TranslateCommands map[string]*TranslateCommandConfig `yaml:"translate_commands"`
60-
Environment map[string]string
61-
Service string
62-
Dest []string
63-
RouteSelect string `yaml:"route_select"`
64-
Mode string
65-
ForceCommand string `yaml:"force_command"`
66-
CommandMustMatch bool `yaml:"command_must_match"`
67-
EtcdKeyTTL int64 `yaml:"etcd_keyttl"`
68-
MaxConnectionsPerUser int `yaml:"max_connections_per_user"`
69-
Overrides []subConfig
44+
ready bool // true when the configuration has already been loaded
45+
Nodeset string `yaml:",omitempty"`
46+
Debug bool `yaml:",omitempty"`
47+
Log string `yaml:",omitempty"`
48+
CheckInterval time.Duration `yaml:"check_interval,omitempty"`
49+
ErrorBanner string `yaml:"error_banner,omitempty"`
50+
Dump string `yaml:",omitempty"`
51+
DumpLimitSize uint64 `yaml:"dump_limit_size,omitempty"`
52+
DumpLimitWindow time.Duration `yaml:"dump_limit_window,omitempty"`
53+
Etcd etcdConfig `yaml:",omitempty"`
54+
EtcdStatsInterval time.Duration `yaml:"etcd_stats_interval,omitempty"`
55+
LogStatsInterval time.Duration `yaml:"log_stats_interval,omitempty"`
56+
BlockingCommand string `yaml:"blocking_command,omitempty"`
57+
BgCommand string `yaml:"bg_command,omitempty"`
58+
SSH sshConfig `yaml:",omitempty"`
59+
TranslateCommands map[string]*TranslateCommandConfig `yaml:"translate_commands,omitempty"`
60+
Environment map[string]string `yaml:",omitempty"`
61+
Service string `yaml:",omitempty"`
62+
Dest []string `yaml:",flow,omitempty"`
63+
RouteSelect string `yaml:"route_select,omitempty"`
64+
Mode string `yaml:",omitempty"`
65+
ForceCommand string `yaml:"force_command,omitempty"`
66+
CommandMustMatch bool `yaml:"command_must_match,omitempty"`
67+
EtcdKeyTTL int64 `yaml:"etcd_keyttl,omitempty"`
68+
MaxConnectionsPerUser int `yaml:"max_connections_per_user,omitempty"`
69+
Overrides []subConfig `yaml:",omitempty"`
7070
}
7171

7272
// TranslateCommandConfig represents the configuration of a translate_command.
7373
// SSHArgs is optional. Command is mandatory. DisableDump defaults to false
7474
type TranslateCommandConfig struct {
7575
SSHArgs []string `yaml:"ssh_args"`
7676
Command string
77-
DisableDump bool `yaml:"disable_dump"`
77+
DisableDump bool `yaml:"disable_dump,omitempty"`
7878
}
7979

8080
type sshConfig struct {
81-
Exe string
82-
Args []string
81+
Exe string `yaml:",omitempty"`
82+
Args []string `yaml:",flow,omitempty"`
8383
}
8484

8585
type etcdConfig struct {
86-
Endpoints []string
87-
TLS etcdTLSConfig
88-
Username string
89-
Password string
90-
KeyTTL int64
91-
Mandatory bool
86+
Endpoints []string `yaml:",flow"`
87+
TLS etcdTLSConfig `yaml:",omitempty"`
88+
Username string `yaml:",omitempty"`
89+
Password string `yaml:",omitempty"`
90+
KeyTTL int64 `yaml:",omitempty"`
91+
Mandatory bool `yaml:",omitempty"`
9292
}
9393

9494
type etcdTLSConfig struct {
@@ -100,30 +100,30 @@ type etcdTLSConfig struct {
100100
// We use interface{} instead of real type to check if the option was specified
101101
// or not.
102102
type subConfig struct {
103-
Match []map[string][]string
104-
Debug interface{}
105-
Log interface{}
106-
CheckInterval interface{} `yaml:"check_interval"`
107-
ErrorBanner interface{} `yaml:"error_banner"`
108-
Dump interface{}
109-
DumpLimitSize interface{} `yaml:"dump_limit_size"`
110-
DumpLimitWindow interface{} `yaml:"dump_limit_window"`
111-
Etcd interface{}
112-
EtcdStatsInterval interface{} `yaml:"etcd_stats_interval"`
113-
LogStatsInterval interface{} `yaml:"log_stats_interval"`
114-
BlockingCommand interface{} `yaml:"blocking_command"`
115-
BgCommand interface{} `yaml:"bg_command"`
116-
SSH interface{}
117-
TranslateCommands map[string]*TranslateCommandConfig `yaml:"translate_commands"`
118-
Environment map[string]string
119-
Service interface{}
120-
Dest []string
121-
RouteSelect interface{} `yaml:"route_select"`
122-
Mode interface{}
123-
ForceCommand interface{} `yaml:"force_command"`
124-
CommandMustMatch interface{} `yaml:"command_must_match"`
125-
EtcdKeyTTL interface{} `yaml:"etcd_keyttl"`
126-
MaxConnectionsPerUser interface{} `yaml:"max_connections_per_user"`
103+
Match []map[string][]string `yaml:",omitempty"`
104+
Debug interface{} `yaml:",omitempty"`
105+
Log interface{} `yaml:",omitempty"`
106+
CheckInterval interface{} `yaml:"check_interval,omitempty"`
107+
ErrorBanner interface{} `yaml:"error_banner,omitempty"`
108+
Dump interface{} `yaml:",omitempty"`
109+
DumpLimitSize interface{} `yaml:"dump_limit_size,omitempty"`
110+
DumpLimitWindow interface{} `yaml:"dump_limit_window,omitempty"`
111+
Etcd interface{} `yaml:",omitempty"`
112+
EtcdStatsInterval interface{} `yaml:"etcd_stats_interval,omitempty"`
113+
LogStatsInterval interface{} `yaml:"log_stats_interval,omitempty"`
114+
BlockingCommand interface{} `yaml:"blocking_command,omitempty"`
115+
BgCommand interface{} `yaml:"bg_command,omitempty"`
116+
SSH interface{} `yaml:",omitempty"`
117+
TranslateCommands map[string]*TranslateCommandConfig `yaml:"translate_commands,omitempty"`
118+
Environment map[string]string `yaml:",omitempty"`
119+
Service interface{} `yaml:",omitempty"`
120+
Dest []string `yaml:",flow,omitempty"`
121+
RouteSelect interface{} `yaml:"route_select,omitempty"`
122+
Mode interface{} `yaml:",omitempty"`
123+
ForceCommand interface{} `yaml:"force_command,omitempty"`
124+
CommandMustMatch interface{} `yaml:"command_must_match,omitempty"`
125+
EtcdKeyTTL interface{} `yaml:"etcd_keyttl,omitempty"`
126+
MaxConnectionsPerUser interface{} `yaml:"max_connections_per_user,omitempty"`
127127
}
128128

129129
// Return slice of strings containing formatted configuration values
@@ -132,14 +132,14 @@ func PrintConfig(config *Config, groups map[string]bool) []string {
132132
output = append(output, fmt.Sprintf("groups = %v", groups))
133133
output = append(output, fmt.Sprintf("config.debug = %v", config.Debug))
134134
output = append(output, fmt.Sprintf("config.log = %s", config.Log))
135-
output = append(output, fmt.Sprintf("config.check_interval = %s", config.CheckInterval.Duration()))
135+
output = append(output, fmt.Sprintf("config.check_interval = %s", config.CheckInterval))
136136
output = append(output, fmt.Sprintf("config.error_banner = %s", config.ErrorBanner))
137137
output = append(output, fmt.Sprintf("config.dump = %s", config.Dump))
138138
output = append(output, fmt.Sprintf("config.dump_limit_size = %d", config.DumpLimitSize))
139-
output = append(output, fmt.Sprintf("config.dump_limit_window = %s", config.DumpLimitWindow.Duration()))
139+
output = append(output, fmt.Sprintf("config.dump_limit_window = %s", config.DumpLimitWindow))
140140
output = append(output, fmt.Sprintf("config.etcd = %+v", config.Etcd))
141-
output = append(output, fmt.Sprintf("config.etcd_stats_interval = %s", config.EtcdStatsInterval.Duration()))
142-
output = append(output, fmt.Sprintf("config.log_stats_interval = %s", config.LogStatsInterval.Duration()))
141+
output = append(output, fmt.Sprintf("config.etcd_stats_interval = %s", config.EtcdStatsInterval))
142+
output = append(output, fmt.Sprintf("config.log_stats_interval = %s", config.LogStatsInterval))
143143
output = append(output, fmt.Sprintf("config.blocking_command = %s", config.BlockingCommand))
144144
output = append(output, fmt.Sprintf("config.bg_command = %s", config.BgCommand))
145145
output = append(output, fmt.Sprintf("config.ssh = %+v", config.SSH))
@@ -169,7 +169,7 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
169169

170170
if subconfig.CheckInterval != nil {
171171
var err error
172-
config.CheckInterval, err = ParseDuration(subconfig.CheckInterval.(string))
172+
config.CheckInterval, err = time.ParseDuration(subconfig.CheckInterval.(string))
173173
if err != nil {
174174
return err
175175
}
@@ -189,7 +189,7 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
189189

190190
if subconfig.DumpLimitWindow != nil {
191191
var err error
192-
config.DumpLimitWindow, err = ParseDuration(subconfig.DumpLimitWindow.(string))
192+
config.DumpLimitWindow, err = time.ParseDuration(subconfig.DumpLimitWindow.(string))
193193
if err != nil {
194194
return err
195195
}
@@ -201,15 +201,15 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
201201

202202
if subconfig.EtcdStatsInterval != nil {
203203
var err error
204-
config.EtcdStatsInterval, err = ParseDuration(subconfig.EtcdStatsInterval.(string))
204+
config.EtcdStatsInterval, err = time.ParseDuration(subconfig.EtcdStatsInterval.(string))
205205
if err != nil {
206206
return err
207207
}
208208
}
209209

210210
if subconfig.LogStatsInterval != nil {
211211
var err error
212-
config.LogStatsInterval, err = ParseDuration(subconfig.LogStatsInterval.(string))
212+
config.LogStatsInterval, err = time.ParseDuration(subconfig.LogStatsInterval.(string))
213213
if err != nil {
214214
return err
215215
}

0 commit comments

Comments
 (0)