@@ -75,6 +75,17 @@ type options struct {
75
75
EncryptKeepSrc bool
76
76
CipherPassphrase string
77
77
Decrypt bool
78
+
79
+
Upload string // values are none, s3
80
+
PurgeRemote bool
81
+
S3Region string
82
+
S3Bucket string
83
+
S3EndPoint string
84
+
S3Profile string
85
+
S3KeyID string
86
+
S3Secret string
87
+
S3ForcePath bool
88
+
S3DisableTLS bool
78
89
}
79
90
80
91
func defaultOptions() options {
@@ -95,6 +106,7 @@ func defaultOptions() options {
95
106
SumAlgo: "none",
96
107
CfgFile: defaultCfgFile,
97
108
TimeFormat: timeFormat,
109
+
Upload: "none",
98
110
}
99
111
}
100
112
@@ -158,6 +170,35 @@ func validatePurgeTimeLimitValue(i string) (time.Duration, error) {
158
170
159
171
}
160
172
173
+
func validateYesNoOption(s string) (bool, error) {
174
+
ls := strings.TrimSpace(strings.ToLower(s))
175
+
if ls == "y" || ls == "yes" {
176
+
return true, nil
177
+
}
178
+
179
+
if ls == "n" || ls == "no" {
180
+
return false, nil
181
+
}
182
+
183
+
return false, fmt.Errorf("value must be \"yes\" or \"no\"")
184
+
}
185
+
186
+
func validateEnum(s string, candidates []string) error {
187
+
found := false
188
+
ls := strings.TrimSpace(strings.ToLower(s))
189
+
for _, v := range candidates {
190
+
if v == ls {
191
+
found = true
192
+
}
193
+
}
194
+
195
+
if !found {
196
+
return fmt.Errorf("value not found in %v", candidates)
197
+
}
198
+
199
+
return nil
200
+
}
201
+
161
202
func parseCli(args []string) (options, []string, error) {
162
203
var format, purgeKeep, purgeInterval string
163
204
@@ -197,6 +238,18 @@ func parseCli(args []string) (options, []string, error) {
197
238
pflag.BoolVar(&opts.Decrypt, "decrypt", false, "decrypt files in the backup directory")
198
239
pflag.StringVar(&opts.CipherPassphrase, "cipher-pass", "", "cipher passphrase for encryption and decryption\n")
199
240
241
+
pflag.StringVar(&opts.Upload, "upload", "none", "upload produced files to target (s3, gcs,..) use \"none\" to override\nconfiguration file and disable upload")
242
+
purgeRemote := pflag.String("purge-remote", "no", "purge the file on remote location after upload, with the same rules as the local directory")
243
+
244
+
pflag.StringVar(&opts.S3Region, "s3-region", "", "S3 region")
245
+
pflag.StringVar(&opts.S3Bucket, "s3-bucket", "", "S3 bucket")
246
+
pflag.StringVar(&opts.S3Profile, "s3-profile", "", "AWS client profile name to get credentials")
247
+
pflag.StringVar(&opts.S3KeyID, "s3-key-id", "", "AWS Access key ID")
248
+
pflag.StringVar(&opts.S3Secret, "s3-secret", "", "AWS Secret access key")
249
+
pflag.StringVar(&opts.S3EndPoint, "s3-endpoint", "", "S3 endpoint URI")
250
+
S3ForcePath := pflag.String("s3-force-path", "no", "force path style addressing instead of virtual hosted bucket\naddressing")
251
+
S3UseTLS := pflag.String("s3-tls", "yes", "enable or disable TLS on requests")
252
+
200
253
pflag.StringVarP(&opts.Host, "host", "h", "", "database server host or socket directory")
201
254
pflag.IntVarP(&opts.Port, "port", "p", 0, "database server port number")
202
255
pflag.StringVarP(&opts.Username, "username", "U", "", "connect as specified database user")
@@ -323,6 +376,33 @@ func parseCli(args []string) (options, []string, error) {
323
376
}
324
377
}
325
378
379
+
// Validate upload option
380
+
stores := []string{"none", "s3"}
381
+
if err := validateEnum(opts.Upload, stores); err != nil {
382
+
return opts, changed, fmt.Errorf("invalid value for --upload: %s", err)
383
+
}
384
+
385
+
opts.PurgeRemote, err = validateYesNoOption(*purgeRemote)
386
+
if err != nil {
387
+
return opts, changed, fmt.Errorf("invalid value for --purge-remote: %s", err)
388
+
}
389
+
390
+
// Validate S3 options
391
+
opts.S3ForcePath, err = validateYesNoOption(*S3ForcePath)
392
+
if err != nil {
393
+
return opts, changed, fmt.Errorf("invalid value for --s3-force-path: %s", err)
394
+
}
395
+
396
+
S3WithTLS, err := validateYesNoOption(*S3UseTLS)
397
+
if err != nil {
398
+
return opts, changed, fmt.Errorf("invalid value for --s3-tls: %s", err)
399
+
}
400
+
opts.S3DisableTLS = !S3WithTLS
401
+
402
+
if opts.Upload == "s3" && opts.S3Bucket == "" {
403
+
return opts, changed, fmt.Errorf("option --s3-bucket is mandatory when --upload=s3")
404
+
}
405
+
326
406
return opts, changed, nil
327
407
}
328
408
@@ -365,6 +445,18 @@ func loadConfigurationFile(path string) (options, error) {
365
445
opts.CipherPassphrase = s.Key("cipher_passphrase").MustString("")
366
446
opts.EncryptKeepSrc = s.Key("encrypt_keep_source").MustBool(false)
367
447
448
+
opts.Upload = s.Key("upload").MustString("none")
449
+
opts.PurgeRemote = s.Key("purge_remote").MustBool(false)
450
+
451
+
opts.S3Region = s.Key("s3_region").MustString("")
452
+
opts.S3Bucket = s.Key("s3_bucket").MustString("")
453
+
opts.S3EndPoint = s.Key("s3_endpoint").MustString("")
454
+
opts.S3Profile = s.Key("s3_profile").MustString("")
455
+
opts.S3KeyID = s.Key("s3_key_id").MustString("")
456
+
opts.S3Secret = s.Key("s3_secret").MustString("")
457
+
opts.S3ForcePath = s.Key("s3_force_path").MustBool(false)
458
+
opts.S3DisableTLS = !s.Key("s3_tls").MustBool(true)
459
+
368
460
// Validate purge keep and time limit
369
461
keep, err := validatePurgeKeepValue(purgeKeep)
370
462
if err != nil {
@@ -395,6 +487,16 @@ func loadConfigurationFile(path string) (options, error) {
395
487
return opts, fmt.Errorf("cannot use an empty passphrase for encryption")
396
488
}
397
489
490
+
// Validate upload option
491
+
stores := []string{"none", "s3"}
492
+
if err := validateEnum(opts.Upload, stores); err != nil {
493
+
return opts, fmt.Errorf("invalid value for upload: %s", err)
494
+
}
495
+
496
+
if opts.Upload == "s3" && opts.S3Bucket == "" {
497
+
return opts, fmt.Errorf("option s3_bucket is mandatory when upload is s3")
498
+
}
499
+
398
500
// Validate the value of the timestamp format. Force the use of legacy
399
501
// on windows to avoid failure when creating filenames with the
400
502
// timestamp
@@ -563,6 +665,29 @@ func mergeCliAndConfigOptions(cliOpts options, configOpts options, onCli []strin
563
665
opts.CipherPassphrase = cliOpts.CipherPassphrase
564
666
case "decrypt":
565
667
opts.Decrypt = cliOpts.Decrypt
668
+
669
+
case "upload":
670
+
opts.Upload = cliOpts.Upload
671
+
case "purge-remote":
672
+
opts.PurgeRemote = cliOpts.PurgeRemote
673
+
674
+
case "s3-region":
675
+
opts.S3Region = cliOpts.S3Region
676
+
case "s3-bucket":
677
+
opts.S3Bucket = cliOpts.S3Bucket
678
+
case "s3-profile":
679
+
opts.S3Profile = cliOpts.S3Profile
680
+
case "s3-key-id":
681
+
opts.S3KeyID = cliOpts.S3KeyID
682
+
case "s3-secret":
683
+
opts.S3Secret = cliOpts.S3Secret
684
+
case "s3-endpoint":
685
+
opts.S3EndPoint = cliOpts.S3EndPoint
686
+
case "s3-force-path":
687
+
opts.S3ForcePath = cliOpts.S3ForcePath
688
+
case "s3-tls":
689
+
opts.S3DisableTLS = cliOpts.S3DisableTLS
690
+
566
691
case "host":
567
692
opts.Host = cliOpts.Host
568
693
case "port":
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4