@@ -72,13 +72,50 @@ func main() {
72
72
{
73
73
Name : "list" ,
74
74
Usage : "Print list of backups and exit" ,
75
- UsageText : "clickhouse-backup list" ,
75
+ UsageText : "clickhouse-backup list [all|local|s3] [latest|penult] " ,
76
76
Action : func (c * cli.Context ) error {
77
77
config := getConfig (c )
78
- fmt .Println ("Local backups:" )
79
- printLocalBackups (* config )
80
- fmt .Println ("Backups on S3:" )
81
- printS3Backups (* config )
78
+ switch c .Args ().Get (0 ) {
79
+ case "local" :
80
+ return printLocalBackups (* config , c .Args ().Get (1 ))
81
+ case "s3" :
82
+ return printS3Backups (* config , c .Args ().Get (1 ))
83
+ case "all" , "" :
84
+ fmt .Println ("Local backups:" )
85
+ if err := printLocalBackups (* config , c .Args ().Get (1 )); err != nil {
86
+ return err
87
+ }
88
+ fmt .Println ("Backups on S3:" )
89
+ if err := printS3Backups (* config , c .Args ().Get (1 )); err != nil {
90
+ return err
91
+ }
92
+ default :
93
+ fmt .Fprintf (os .Stderr , "Unknown command '%s'\n " , c .Args ().Get (0 ))
94
+ cli .ShowCommandHelpAndExit (c , c .Command .Name , 1 )
95
+ }
96
+ return nil
97
+ },
98
+ Flags : cliapp .Flags ,
99
+ },
100
+ {
101
+ Name : "delete" ,
102
+ Usage : "Delete specific backup" ,
103
+ UsageText : "clickhouse-backup delete <local|s3> <backup_name>" ,
104
+ Action : func (c * cli.Context ) error {
105
+ config := getConfig (c )
106
+ if c .Args ().Get (1 ) == "" {
107
+ fmt .Fprintln (os .Stderr , "Backup name must be defined" )
108
+ cli .ShowCommandHelpAndExit (c , c .Command .Name , 1 )
109
+ }
110
+ switch c .Args ().Get (0 ) {
111
+ case "local" :
112
+ return removeBackupLocal (* config , c .Args ().Get (1 ))
113
+ case "s3" :
114
+ return removeBackupS3 (* config , c .Args ().Get (1 ))
115
+ default :
116
+ fmt .Fprintf (os .Stderr , "Unknown command '%s'\n " , c .Args ().Get (0 ))
117
+ cli .ShowCommandHelpAndExit (c , c .Command .Name , 1 )
118
+ }
82
119
return nil
83
120
},
84
121
Flags : cliapp .Flags ,
@@ -283,7 +320,7 @@ func restoreSchema(config Config, backupName string, tablePattern string, dryRun
283
320
}
284
321
if backupName == "" {
285
322
fmt .Println ("Select backup for restore:" )
286
- printLocalBackups (config )
323
+ printLocalBackups (config , "all" )
287
324
os .Exit (1 )
288
325
}
289
326
dataPath := getDataPath (config )
@@ -326,18 +363,37 @@ func restoreSchema(config Config, backupName string, tablePattern string, dryRun
326
363
return nil
327
364
}
328
365
329
- func printLocalBackups (config Config ) error {
366
+ func printBackups (backupList []Backup , format string ) error {
367
+ switch format {
368
+ case "latest" , "last" , "l" :
369
+ if len (backupList ) < 1 {
370
+ return fmt .Errorf ("No backups found" )
371
+ }
372
+ fmt .Println (backupList [len (backupList )- 1 ].Name )
373
+ case "penult" , "prev" , "previous" , "p" :
374
+ if len (backupList ) < 2 {
375
+ return fmt .Errorf ("No penult backup is found" )
376
+ }
377
+ fmt .Println (backupList [len (backupList )- 2 ].Name )
378
+ case "all" , "" :
379
+ if len (backupList ) == 0 {
380
+ fmt .Println ("No backups found" )
381
+ }
382
+ for _ , backup := range backupList {
383
+ fmt .Printf ("- '%s' (created at %s)\n " , backup .Name , backup .Date .Format ("02-01-2006 15:04:05" ))
384
+ }
385
+ default :
386
+ return fmt .Errorf ("'%s' undefined" , format )
387
+ }
388
+ return nil
389
+ }
390
+
391
+ func printLocalBackups (config Config , format string ) error {
330
392
backupList , err := listLocalBackups (config )
331
393
if err != nil && ! os .IsNotExist (err ) {
332
394
return err
333
395
}
334
- if len (backupList ) == 0 {
335
- fmt .Println ("No backups found" )
336
- }
337
- for _ , backup := range backupList {
338
- fmt .Printf ("- '%s' (created at %s)\n " , backup .Name , backup .Date .Format ("02-01-2006 15:04:05" ))
339
- }
340
- return nil
396
+ return printBackups (backupList , format )
341
397
}
342
398
343
399
func listLocalBackups (config Config ) ([]Backup , error ) {
@@ -375,7 +431,7 @@ func listLocalBackups(config Config) ([]Backup, error) {
375
431
return result , nil
376
432
}
377
433
378
- func printS3Backups (config Config ) error {
434
+ func printS3Backups (config Config , format string ) error {
379
435
s3 := & S3 {Config : & config .S3 }
380
436
if err := s3 .Connect (); err != nil {
381
437
return fmt .Errorf ("can't connect to s3 with %v" , err )
@@ -384,13 +440,7 @@ func printS3Backups(config Config) error {
384
440
if err != nil {
385
441
return err
386
442
}
387
- if len (backupList ) == 0 {
388
- fmt .Println ("No backups found" )
389
- }
390
- for _ , backup := range backupList {
391
- fmt .Printf ("- '%s' (uploaded at %s)\n " , backup .Name , backup .Date .Format ("02-01-2006 15:04:05" ))
392
- }
393
- return nil
443
+ return printBackups (backupList , format )
394
444
}
395
445
396
446
func freeze (config Config , tablePattern string , dryRun bool ) error {
@@ -503,7 +553,7 @@ func restoreData(config Config, backupName string, tablePattern string, dryRun b
503
553
}
504
554
if backupName == "" {
505
555
fmt .Println ("Select backup for restore:" )
506
- printLocalBackups (config )
556
+ printLocalBackups (config , "all" )
507
557
os .Exit (1 )
508
558
}
509
559
dataPath := getDataPath (config )
@@ -579,7 +629,7 @@ func upload(config Config, backupName string, diffFrom string, dryRun bool) erro
579
629
}
580
630
if backupName == "" {
581
631
fmt .Println ("Select backup for upload:" )
582
- printLocalBackups (config )
632
+ printLocalBackups (config , "all" )
583
633
os .Exit (1 )
584
634
}
585
635
dataPath := getDataPath (config )
@@ -627,7 +677,7 @@ func download(config Config, backupName string, dryRun bool) error {
627
677
}
628
678
if backupName == "" {
629
679
fmt .Println ("Select backup for download:" )
630
- printS3Backups (config )
680
+ printS3Backups (config , "all" )
631
681
os .Exit (1 )
632
682
}
633
683
dataPath := getDataPath (config )
@@ -696,6 +746,45 @@ func removeOldBackupsLocal(config Config, dryRun bool) error {
696
746
return nil
697
747
}
698
748
749
+ func removeBackupLocal (config Config , backupName string ) error {
750
+ backupList , err := listLocalBackups (config )
751
+ if err != nil {
752
+ return err
753
+ }
754
+ dataPath := getDataPath (config )
755
+ if dataPath == "" {
756
+ return ErrUnknownClickhouseDataPath
757
+ }
758
+ for _ , backup := range backupList {
759
+ if backup .Name == backupName {
760
+ return os .RemoveAll (path .Join (dataPath , "backup" , backupName ))
761
+ }
762
+ }
763
+ return fmt .Errorf ("backup '%s' not found" , backupName )
764
+ }
765
+
766
+ func removeBackupS3 (config Config , backupName string ) error {
767
+ dataPath := getDataPath (config )
768
+ if dataPath == "" {
769
+ return ErrUnknownClickhouseDataPath
770
+ }
771
+ s3 := & S3 {Config : & config .S3 }
772
+ if err := s3 .Connect (); err != nil {
773
+ return fmt .Errorf ("can't connect to s3 with: %v" , err )
774
+ }
775
+ backupList , err := s3 .BackupList ()
776
+ if err != nil {
777
+ return err
778
+ }
779
+ for _ , backup := range backupList {
780
+ if backup .Name == backupName {
781
+ return s3 .RemoveBackup (backupName )
782
+ }
783
+ }
784
+ return fmt .Errorf ("backup '%s' not found on s3" , backupName )
785
+ }
786
+
787
+
699
788
func getConfig (ctx * cli.Context ) * Config {
700
789
configPath := ctx .String ("config" )
701
790
if configPath == defaultConfigPath {
0 commit comments