From 20fd9f31269d317e630be24203ac3a06eb2f4fae Mon Sep 17 00:00:00 2001 From: Frank Jimenez Date: Tue, 26 Mar 2024 21:25:27 +0000 Subject: [PATCH] allow flag added --- cli.go | 85 +++++++++++++++++++++++++++++++++++++++++++------------- utils.go | 6 +++- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/cli.go b/cli.go index 94ef80d..109546f 100644 --- a/cli.go +++ b/cli.go @@ -2,36 +2,46 @@ package main import ( "fmt" - "github.com/gernest/wow" - "github.com/gernest/wow/spin" "log" "os" - "syscall" "os/signal" + "syscall" + + "github.com/gernest/wow" + "github.com/gernest/wow/spin" "github.com/urfave/cli/v2" ) // Cleans up a database if user ctrl+c func init() { - c := make(chan os.Signal) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - go func() { - <-c + c := make(chan os.Signal) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + go func() { + <-c cleanup() - os.Exit(1) - }() + os.Exit(1) + }() } func main() { + // Version Flag + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", + Aliases: []string{"V"}, + Usage: "Print out version", + } + + // Main CLI app := &cli.App{ - Name: "Yeo", - Usage: "Backup utilities for PostgreSQL databases", + Name: "Yeo!", + Version: "v0.2.0", + Usage: "Backup utilities for PostgreSQL databases", Commands: []*cli.Command{ { Name: "backup", - Usage: "Creates a backup of a database. This is also known as 'dump'.", - UsageText: fmt.Sprintf("backup [database] [filename]\n\nExample: yeo backup my_db my_db_backup.dump"), + Usage: "creates a backup of a database. This is also known as 'dump'.", + UsageText: "yeo backup [database] [filename]\n\nExample: yeo backup my_db my_db_backup.dump", Action: func(cCtx *cli.Context) error { database := cCtx.Args().Get(0) filename := cCtx.Args().Get(1) @@ -50,19 +60,35 @@ func main() { }, { Name: "revive", - Usage: "Revives a database from a backup. This is also known as 'restore'.", - UsageText: "revive [database] [filename]\n\nExample: yeo revive my_new_db my_db_backup.dump", + Usage: "revives a database from a backup. This is also known as 'restore'.", + UsageText: "yeo revive [options] [database] [filename]\n\nExample 1: yeo revive local_db db_backup.dump\n\nExample 2: yeo revive --allow prod db_backup.dump", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "allow", + Usage: "allows to revive into non-local databases", + }, + }, Action: func(cCtx *cli.Context) error { database := cCtx.Args().Get(0) filename := cCtx.Args().Get(1) + + // Checks '.dump' filename provided is valid if err := validateFilename(filename); err != nil { fmt.Println(err) os.Exit(1) } + // Checks the target database is allowed + isUnlocked := cCtx.Bool("allow") + if err := validateTargetDb(database, isUnlocked); err != nil { + fmt.Println(err) + os.Exit(1) + } + // Prepares database by dropping and creating a new database if err := prepareDb(database); err != nil { fmt.Println(err) os.Exit(1) } + // Restores a database if err := revive(database, filename, false); err != nil { fmt.Println(err) os.Exit(1) @@ -72,33 +98,53 @@ func main() { }, { Name: "clone", - Usage: "Clones a database into another database. This is also known as 'dump' and 'restore'.", - UsageText: "clone [database] [filename]\n\nExample: yeo revive my_new_db my_db_backup.dump", + Usage: "clones a database into another database. This is also known as 'dump' and 'restore'.", + UsageText: "yeo clone [options] [database] [filename]\n\nExample 1: yeo clone prod local_db\n\nExample 2: yeo clone --allow local_db prod", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "allow", + Usage: "allows to clone into non-local databases", + }, + }, Action: func(cCtx *cli.Context) error { + // Cloning doesn't need specific filename and so a temporal name is given temp_filename := "temp.dump" + // This is set for the 'cleanup' function os.Setenv("FILENAME", temp_filename) + + // User args og_database := cCtx.Args().Get(0) target_database := cCtx.Args().Get(1) - if err := validateTargetDb(target_database); err != nil { + isUnlocked := cCtx.Bool("allow") + + // Checks the target database is allowed + if err := validateTargetDb(target_database, isUnlocked); err != nil { fmt.Println(err) os.Exit(1) } - fmt.Println() + fmt.Println() // Used for padding + // Spin wheel w := wow.New(os.Stdout, spin.Get(spin.Dots), fmt.Sprintf(" Cloning %s database", og_database)) w.Start() + + // Dumps a database err := backup(og_database, temp_filename, true) if err != nil { fmt.Println(err) os.Exit(1) } + // Prepares database by dropping and creating a new database if err := prepareDb(target_database); err != nil { fmt.Println(err) os.Exit(1) } + + // Restores a database if err = revive(target_database, temp_filename, false); err != nil { fmt.Println(err) os.Exit(1) } + // Removes the 'temp.dump' file generated during the process cleanup() return nil @@ -107,6 +153,7 @@ func main() { }, } + // Allows suggestions if mispellings app.Suggest = true if err := app.Run(os.Args); err != nil { diff --git a/utils.go b/utils.go index a320e30..c6406a6 100644 --- a/utils.go +++ b/utils.go @@ -50,13 +50,17 @@ func validateFilename(fn string) error { return nil } -func validateTargetDb(targetDb string) error { +func validateTargetDb(targetDb string, unlock bool) error { configs, err := openConfigs(targetDb) if err != nil { return err } + if unlock { + return nil + } + if !strings.Contains(configs.Host, "localhost") { return fmt.Errorf(`Your target database isn't local.`) }