Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mysql backup and restore #361

Merged
merged 5 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ temporal*
.DS*
get.sh
.vscode
staging.civo.json
112 changes: 70 additions & 42 deletions README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions cmd/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,7 @@ func init() {
dbUpdateCmd.Flags().StringVarP(&updatedName, "name", "n", "", "the new name for the database")

dbRestoreCmd.Flags().StringVarP(&backup, "backup", "b", "", "the backup name which you can restore database")
dbRestoreCmd.Flags().StringVarP(&restoreName, "name", "n", "", "name of the restore")
dbRestoreCmd.MarkFlagRequired("backup")
dbRestoreCmd.MarkFlagRequired("name")
}
3 changes: 0 additions & 3 deletions cmd/database/database_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
)

var name, schedule, backupType string
var count int

// dbBackupCmd is the root command for the db backup subcommand
var dbBackupCmd = &cobra.Command{
Expand All @@ -32,13 +31,11 @@ func init() {
// Create cmd options
dbBackupCreateCmd.Flags().StringVarP(&name, "name", "n", "", "name of the database backup")
dbBackupCreateCmd.Flags().StringVarP(&schedule, "schedule", "s", "", "schedule of the database backup in the form of cronjob")
dbBackupCreateCmd.Flags().IntVarP(&count, "count", "c", 1, "number of backups to keep")
dbBackupCreateCmd.Flags().StringVarP(&backupType, "type", "t", "scheduled", "set the type of database backup manual/scheduled")

dbBackupCreateCmd.MarkFlagRequired("name")

// Update cmd options
dbBackupUpdateCmd.Flags().StringVarP(&name, "name", "n", "", "name of the database backup")
dbBackupUpdateCmd.Flags().StringVarP(&schedule, "schedule", "s", "", "schedule of the database backup in the form of cronjob")
dbBackupUpdateCmd.Flags().IntVarP(&count, "count", "c", 0, "number of backups to keep")
RealHarshThakur marked this conversation as resolved.
Show resolved Hide resolved
}
14 changes: 3 additions & 11 deletions cmd/database/database_backup_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
var dbBackupCreateCmd = &cobra.Command{
Use: "create",
Aliases: []string{"new", "add"},
Example: `Scheduled: civo database backup create <DATABASE-NAME/ID> --name <BACKUP_NAME> --schedule <SCHEDULE> --count <COUNT>\n
Example: `Scheduled: civo database backup create <DATABASE-NAME/ID> --name <BACKUP_NAME> --schedule <SCHEDULE>\n
Manual: civo database backup create <DATABASE-NAME/ID> --name <BACKUP_NAME> --type manual`,
Short: "Create a new database backup",
Args: cobra.MinimumNArgs(1),
Expand Down Expand Up @@ -51,11 +51,6 @@ var dbBackupCreateCmd = &cobra.Command{
client.Region = common.RegionSet
}

if count <= 0 {
utility.Error("Count must be greater than zero, you have given: %d", count)
os.Exit(1)
}

if schedule == "" {
utility.Error("Schedule must be specified")
os.Exit(1)
Expand All @@ -69,8 +64,6 @@ var dbBackupCreateCmd = &cobra.Command{

backupCreateConfig.Name = name
backupCreateConfig.Schedule = schedule
backupCreateConfig.Count = int32(count)

} else {
backupCreateConfig.Name = name
backupCreateConfig.Type = backupType
Expand All @@ -89,9 +82,8 @@ var dbBackupCreateCmd = &cobra.Command{
"database_id": bk.DatabaseID,
"database_name": bk.DatabaseName,
"software": bk.Software,
"name": bk.Scheduled.Name,
"schedule": bk.Scheduled.Schedule,
"count": fmt.Sprintf("%d", count),
"name": bk.Name,
"schedule": bk.Schedule,
})
} else {
ow = utility.NewOutputWriterWithMap(map[string]string{
Expand Down
159 changes: 102 additions & 57 deletions cmd/database/database_backup_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package database
import (
"fmt"
"os"
"strings"

"github.com/civo/civogo"
"github.com/civo/cli/common"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
Expand Down Expand Up @@ -42,70 +42,115 @@ var dbBackupListCmd = &cobra.Command{
os.Exit(1)
}

if backups.DatabaseID == "" {
return
switch db.Software {
case "PostgreSQL":
postgresScheduledBackups(backups)
postgresManualBackups(backups)
case "MySQL":
mysqlBackups(backups)
}
},
}

func postgresScheduledBackups(backups *civogo.PaginatedDatabaseBackup) {
ow := utility.NewOutputWriter()
printMsg := false
for _, bk := range backups.Items {
if !bk.IsScheduled {
continue
}
printMsg = true
ow.StartLine()
ow.AppendDataWithLabel("database_id", utility.TrimID(bk.DatabaseID), "Database ID")
ow.AppendDataWithLabel("database_name", bk.DatabaseName, "Database Name")

ow.AppendDataWithLabel("software", bk.Software, "Software")
ow.AppendDataWithLabel("schedule", bk.Schedule, "Schedule")
ow.AppendDataWithLabel("backup_name", bk.Name, "Backup Name")

ow.AppendDataWithLabel("backup", bk.Backup, "Backup")

if common.OutputFormat == "json" || common.OutputFormat == "custom" {
ow.AppendDataWithLabel("database_id", bk.DatabaseID, "Database ID")
}
}

switch common.OutputFormat {
case "json":
ow.WriteMultipleObjectsJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
if printMsg {
fmt.Println("Scheduled backup")
}
ow.WriteTable()
}
}

func postgresManualBackups(backups *civogo.PaginatedDatabaseBackup) {
ow := utility.NewOutputWriter()
printMsg := false
for _, bk := range backups.Items {
if bk.IsScheduled {
continue
}
printMsg = true
ow.StartLine()
ow.AppendDataWithLabel("database_id", utility.TrimID(bk.DatabaseID), "Database ID")
ow.AppendDataWithLabel("database_name", bk.DatabaseName, "Database Name")

ow.AppendDataWithLabel("software", bk.Software, "Software")
ow.AppendDataWithLabel("backup", bk.Backup, "Backup")

odb := utility.NewOutputWriter()
ombk := utility.NewOutputWriter()
osbk := utility.NewOutputWriter()
mbk := ""
sbk := ""
isConfiguredScheduled := false
isConfiguredManual := false

odb.StartLine()
odb.AppendDataWithLabel("database_id", utility.TrimID(backups.DatabaseID), "Database ID")
odb.AppendDataWithLabel("database_name", backups.DatabaseName, "Database Name")
odb.AppendDataWithLabel("software", backups.Software, "Software")

if backups.Scheduled != nil {
isConfiguredScheduled = true
osbk.AppendDataWithLabel("name", backups.Scheduled.Name, "Backup Name")
osbk.AppendDataWithLabel("schedule", backups.Scheduled.Schedule, "Schedule")
osbk.AppendDataWithLabel("count", fmt.Sprintf("%d", backups.Scheduled.Count), "Count")

sbk = strings.TrimSuffix(strings.Join(backups.Scheduled.Backups, ","), ",")
osbk.AppendDataWithLabel("backups", sbk, "Backups")
if common.OutputFormat == "json" || common.OutputFormat == "custom" {
ow.AppendDataWithLabel("database_id", bk.DatabaseID, "Database ID")
}
}

if backups.Manual != nil {
isConfiguredManual = true
for i, m := range backups.Manual {
if i < len(backups.Manual)-1 {
mbk += m.Backup + ", "
} else {
mbk += m.Backup
}
}
ombk.AppendDataWithLabel("backups", mbk, "Backups")
switch common.OutputFormat {
case "json":
ow.WriteMultipleObjectsJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
if printMsg {
fmt.Println("Manual backups")
}
ow.WriteTable()
}
}

func mysqlBackups(backups *civogo.PaginatedDatabaseBackup) {
ow := utility.NewOutputWriter()
printMsg := false
for _, bk := range backups.Items {
printMsg = true
ow.StartLine()
ow.AppendDataWithLabel("database_id", utility.TrimID(bk.DatabaseID), "Database ID")
ow.AppendDataWithLabel("database_name", bk.DatabaseName, "Database Name")

ow.AppendDataWithLabel("backup_id", utility.TrimID(bk.ID), "Backup ID")
ow.AppendDataWithLabel("backup_name", bk.Name, "Backup Name")
ow.AppendDataWithLabel("software", bk.Software, "Software")
ow.AppendDataWithLabel("status", bk.Status, "Status")

if common.OutputFormat == "json" || common.OutputFormat == "custom" {
odb.AppendDataWithLabel("database_id", utility.TrimID(backups.DatabaseID), "Database ID")
odb.AppendDataWithLabel("database_name", backups.DatabaseName, "Database Name")
odb.AppendDataWithLabel("software", backups.Software, "Software")
odb.AppendDataWithLabel("schedule_backup_name", backups.Scheduled.Name, "Schedule Backup Name")
odb.AppendDataWithLabel("schedule", backups.Scheduled.Schedule, "Schedule")
odb.AppendDataWithLabel("count", fmt.Sprintf("%d", backups.Scheduled.Count), "Count")
odb.AppendDataWithLabel("scheduled_backups", sbk, "Schedule Backups")
odb.AppendDataWithLabel("manual_backups", mbk, "Manual Backups")
ow.AppendDataWithLabel("id", bk.ID, "ID")
ow.AppendDataWithLabel("database_id", bk.DatabaseID, "Database ID")
ow.AppendDataWithLabel("database_name", bk.DatabaseName, "Database Name")
}
}

switch common.OutputFormat {
case "json":
odb.WriteMultipleObjectsJSON(common.PrettySet)
case "custom":
odb.WriteCustomOutput(common.OutputFields)
default:
if isConfiguredScheduled {
fmt.Println("Scheduled Backups:")
}
osbk.WriteTable()
if isConfiguredManual {
fmt.Println("Manual Backups:")
}
ombk.WriteTable()
switch common.OutputFormat {
case "json":
ow.WriteMultipleObjectsJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
if printMsg {
fmt.Println("Manual backups")
}
},
ow.WriteTable()
}
}
16 changes: 6 additions & 10 deletions cmd/database/database_backup_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var dbBackupUpdateCmd = &cobra.Command{
Use: "update",
Aliases: []string{"modify", "change"},
Short: "Update a scheduled database backup",
Example: "civo database backup update <DATABASE-NAME/ID> --name <NEW_BACKUP-NAME> --schedule <SCHEDULE> --count <COUNT>",
Example: "civo database backup update <DATABASE-NAME/ID> --name <NEW_BACKUP-NAME> --schedule <SCHEDULE>",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
utility.EnsureCurrentRegion()
Expand All @@ -30,8 +30,8 @@ var dbBackupUpdateCmd = &cobra.Command{
client.Region = common.RegionSet
}

if schedule == "" && count == 0 && name == "" {
utility.Error("Schedule, name or count must be specified")
if schedule == "" && name == "" {
utility.Error("Schedule, name must be specified")
os.Exit(1)
}

Expand All @@ -48,9 +48,6 @@ var dbBackupUpdateCmd = &cobra.Command{
if schedule != "" {
backupUpdateConfig.Schedule = schedule
}
if count >= 0 {
backupUpdateConfig.Count = int32(count)
}
if name != "" {
backupUpdateConfig.Name = name
}
Expand All @@ -69,17 +66,16 @@ var dbBackupUpdateCmd = &cobra.Command{
"database_id": bk.DatabaseID,
"database_name": bk.DatabaseName,
"software": bk.Software,
"name": bk.Scheduled.Name,
"schedule": bk.Scheduled.Schedule,
"count": fmt.Sprintf("%d", count),
"backup_name": bk.Name,
"schedule": bk.Schedule,
})
switch common.OutputFormat {
case "json":
ow.WriteSingleObjectJSON(common.PrettySet)
case "custom":
ow.WriteCustomOutput(common.OutputFields)
default:
fmt.Printf("Database backup (%s) for database %s has been update\n", utility.Green(bk.Scheduled.Name), utility.Green(bk.DatabaseName))
fmt.Printf("Database backup (%s) for database %s has been update\n", utility.Green(bk.Name), utility.Green(bk.DatabaseName))
}
},
}
8 changes: 6 additions & 2 deletions cmd/database/database_restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ import (
"github.com/spf13/cobra"
)

var backup string
var (
backup string
restoreName string
)

var dbRestoreCmd = &cobra.Command{
Use: "restore",
Aliases: []string{"reset", "restores"},
Short: "Restore a database",
Example: "civo db restore <DATABASE-NAME/ID> --backup <BACKUP-NAME>",
Example: "civo db restore <DATABASE-NAME/ID> --name <RESTORE-NAME> --backup <BACKUP-NAME>",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
utility.EnsureCurrentRegion()
Expand All @@ -43,6 +46,7 @@ var dbRestoreCmd = &cobra.Command{
if utility.UserConfirmedRestore(db.Name, common.DefaultYes, backup) {
config := &civogo.RestoreDatabaseRequest{
Software: db.Software,
Name: restoreName,
Backup: backup,
Region: client.Region,
}
Expand Down
Loading
Loading