@@ -16,6 +16,7 @@ import (
16
16
"os"
17
17
"regexp"
18
18
"slices"
19
+ "sort"
19
20
"strings"
20
21
"time"
21
22
@@ -82,13 +83,15 @@ type sshConfig struct {
82
83
Args []string `yaml:",flow,omitempty"`
83
84
}
84
85
86
+ // We use interface{} instead of real type to check if the option was specified
87
+ // or not.
85
88
type etcdConfig struct {
86
89
Endpoints []string `yaml:",flow"`
87
90
TLS etcdTLSConfig `yaml:",omitempty"`
88
91
Username string `yaml:",omitempty"`
89
92
Password string `yaml:",omitempty"`
90
93
KeyTTL int64 `yaml:",omitempty"`
91
- Mandatory bool `yaml:",omitempty"`
94
+ Mandatory interface {} `yaml:",omitempty"`
92
95
}
93
96
94
97
type etcdTLSConfig struct {
@@ -108,12 +111,12 @@ type subConfig struct {
108
111
Dump interface {} `yaml:",omitempty"`
109
112
DumpLimitSize interface {} `yaml:"dump_limit_size,omitempty"`
110
113
DumpLimitWindow interface {} `yaml:"dump_limit_window,omitempty"`
111
- Etcd interface {} `yaml:",omitempty"`
114
+ Etcd etcdConfig `yaml:",omitempty"`
112
115
EtcdStatsInterval interface {} `yaml:"etcd_stats_interval,omitempty"`
113
116
LogStatsInterval interface {} `yaml:"log_stats_interval,omitempty"`
114
117
BlockingCommand interface {} `yaml:"blocking_command,omitempty"`
115
118
BgCommand interface {} `yaml:"bg_command,omitempty"`
116
- SSH interface {} `yaml:",omitempty"`
119
+ SSH sshConfig `yaml:",omitempty"`
117
120
TranslateCommands map [string ]* TranslateCommandConfig `yaml:"translate_commands,omitempty"`
118
121
Environment map [string ]string `yaml:",omitempty"`
119
122
Service interface {} `yaml:",omitempty"`
@@ -143,8 +146,15 @@ func PrintConfig(config *Config, groups map[string]bool) []string {
143
146
output = append (output , fmt .Sprintf ("config.blocking_command = %s" , config .BlockingCommand ))
144
147
output = append (output , fmt .Sprintf ("config.bg_command = %s" , config .BgCommand ))
145
148
output = append (output , fmt .Sprintf ("config.ssh = %+v" , config .SSH ))
146
- for k , v := range config .TranslateCommands {
147
- output = append (output , fmt .Sprintf ("config.TranslateCommands.%s = %+v" , k , v ))
149
+ // Internally, we don't care of TranslateCommands's order. But we want to
150
+ // always display it in the same order
151
+ keys := make ([]string , 0 , len (config .TranslateCommands ))
152
+ for k := range config .TranslateCommands {
153
+ keys = append (keys , k )
154
+ }
155
+ sort .Strings (keys )
156
+ for _ , k := range keys {
157
+ output = append (output , fmt .Sprintf ("config.TranslateCommands.%s = %+v" , k , config .TranslateCommands [k ]))
148
158
}
149
159
output = append (output , fmt .Sprintf ("config.environment = %v" , config .Environment ))
150
160
output = append (output , fmt .Sprintf ("config.service = %s" , config .Service ))
@@ -168,6 +178,9 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
168
178
}
169
179
170
180
if subconfig .CheckInterval != nil {
181
+ if fmt .Sprintf ("%T" , subconfig .CheckInterval ) != "string" {
182
+ return fmt .Errorf ("check_interval: %v is not a string" , subconfig .CheckInterval )
183
+ }
171
184
var err error
172
185
config .CheckInterval , err = time .ParseDuration (subconfig .CheckInterval .(string ))
173
186
if err != nil {
@@ -188,18 +201,52 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
188
201
}
189
202
190
203
if subconfig .DumpLimitWindow != nil {
204
+ if fmt .Sprintf ("%T" , subconfig .DumpLimitWindow ) != "string" {
205
+ return fmt .Errorf ("dump_limit_window: %v is not a string" , subconfig .DumpLimitWindow )
206
+ }
191
207
var err error
192
208
config .DumpLimitWindow , err = time .ParseDuration (subconfig .DumpLimitWindow .(string ))
193
209
if err != nil {
194
210
return err
195
211
}
196
212
}
197
213
198
- if subconfig .Etcd != nil {
199
- config .Etcd = subconfig .Etcd .(etcdConfig )
214
+ if subconfig .Etcd .Endpoints != nil {
215
+ config .Etcd .Endpoints = subconfig .Etcd .Endpoints
216
+ }
217
+
218
+ if subconfig .Etcd .TLS .CAFile != "" {
219
+ config .Etcd .TLS .CAFile = subconfig .Etcd .TLS .CAFile
220
+ }
221
+
222
+ if subconfig .Etcd .TLS .KeyFile != "" {
223
+ config .Etcd .TLS .KeyFile = subconfig .Etcd .TLS .KeyFile
224
+ }
225
+
226
+ if subconfig .Etcd .TLS .CertFile != "" {
227
+ config .Etcd .TLS .CertFile = subconfig .Etcd .TLS .CertFile
228
+ }
229
+
230
+ if subconfig .Etcd .Username != "" {
231
+ config .Etcd .Username = subconfig .Etcd .Username
232
+ }
233
+
234
+ if subconfig .Etcd .Password != "" {
235
+ config .Etcd .Password = subconfig .Etcd .Password
236
+ }
237
+
238
+ if subconfig .Etcd .KeyTTL != 0 {
239
+ config .Etcd .KeyTTL = subconfig .Etcd .KeyTTL
240
+ }
241
+
242
+ if subconfig .Etcd .Mandatory != nil {
243
+ config .Etcd .Mandatory = subconfig .Etcd .Mandatory
200
244
}
201
245
202
246
if subconfig .EtcdStatsInterval != nil {
247
+ if fmt .Sprintf ("%T" , subconfig .EtcdStatsInterval ) != "string" {
248
+ return fmt .Errorf ("etcd_stats_interval: %v is not a string" , subconfig .EtcdStatsInterval )
249
+ }
203
250
var err error
204
251
config .EtcdStatsInterval , err = time .ParseDuration (subconfig .EtcdStatsInterval .(string ))
205
252
if err != nil {
@@ -208,6 +255,9 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
208
255
}
209
256
210
257
if subconfig .LogStatsInterval != nil {
258
+ if fmt .Sprintf ("%T" , subconfig .LogStatsInterval ) != "string" {
259
+ return fmt .Errorf ("log_stats_interval: %v is not a string" , subconfig .LogStatsInterval )
260
+ }
211
261
var err error
212
262
config .LogStatsInterval , err = time .ParseDuration (subconfig .LogStatsInterval .(string ))
213
263
if err != nil {
@@ -223,8 +273,12 @@ func parseSubConfig(config *Config, subconfig *subConfig) error {
223
273
config .BgCommand = subconfig .BgCommand .(string )
224
274
}
225
275
226
- if subconfig .SSH != nil {
227
- config .SSH = subconfig .SSH .(sshConfig )
276
+ if subconfig .SSH .Exe != "" {
277
+ config .SSH .Exe = subconfig .SSH .Exe
278
+ }
279
+
280
+ if subconfig .SSH .Args != nil {
281
+ config .SSH .Args = subconfig .SSH .Args
228
282
}
229
283
230
284
// merge translate_commands
@@ -296,7 +350,14 @@ func LoadAllDestsFromConfig(filename string) ([]string, error) {
296
350
config .Dest = append (config .Dest , override .Dest ... )
297
351
}
298
352
}
299
- return config .Dest , nil
353
+ // expand destination nodesets
354
+ _ , nodesetDlclose , nodesetExpand := nodesets .InitExpander ()
355
+ defer nodesetDlclose ()
356
+ dsts , err := nodesetExpand (strings .Join (config .Dest , "," ))
357
+ if err != nil {
358
+ return nil , fmt .Errorf ("invalid nodeset: %s" , err )
359
+ }
360
+ return dsts , nil
300
361
}
301
362
302
363
// LoadConfig load configuration file and adapt it according to specified user/group/sshdHostPort.
0 commit comments