diff --git a/README.md b/README.md index ea91443..e85f0b3 100644 --- a/README.md +++ b/README.md @@ -38,21 +38,23 @@ MySQL Backup and Restoration tool. Backup database to AWS S3 storage or any S3 A ## Usage -| Options | Shorts | Usage | -|-----------------------|--------|------------------------------------| -| mysql-bkup | bkup | CLI utility | -| --operation | -o | Set operation. backup or restore (default: backup) | -| --storage | -s | Set storage. local or s3 (default: local) | -| --file | -f | Set file name for restoration | -| --path | | Set s3 path without file name. eg: /custom_path | -| --dbname | -d | Set database name | -| --port | -p | Set database port (default: 3306) | +| Options | Shorts | Usage | +|-----------------------|--------|--------------------------------------------------------------------| +| mysql-bkup | bkup | CLI utility | +| backup | | Backup database operation | +| restore | | Restore database operation | +| --operation | -o | Set operation. backup or restore (default: backup) | +| --storage | -s | Set storage. local or s3 (default: local) | +| --file | -f | Set file name for restoration | +| --path | | Set s3 path without file name. eg: /custom_path | +| --dbname | -d | Set database name | +| --port | -p | Set database port (default: 3306) | | --mode | -m | Set execution mode. default or scheduled (default: default) | -| --disable-compression | | Disable database backup compression | -| --period | | Set crontab period for scheduled mode only. (default: "0 1 * * *") | -| --timeout | -t | Set timeout (default: 60s) | -| --help | -h | Print this help message and exit | -| --version | -V | Print version information and exit | +| --disable-compression | | Disable database backup compression | +| --period | | Set crontab period for scheduled mode only. (default: "0 1 * * *") | +| --timeout | -t | Set timeout (default: 60s) | +| --help | -h | Print this help message and exit | +| --version | -V | Print version information and exit | ## Note: @@ -81,20 +83,20 @@ FLUSH PRIVILEGES; Simple backup usage ```sh -bkup --operation backup --dbname database_name +bkup backup --dbname database_name ``` ```sh -bkup -o backup -d database_name +bkup backup -d database_name ``` ### S3 ```sh -bkup --operation backup --storage s3 --dbname database_name +bkup backup --storage s3 --dbname database_name ``` ## Docker run: ```sh -docker run --rm --network your_network_name --name mysql-bkup -v $PWD/backup:/backup/ -e "DB_HOST=database_host_name" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" jkaninda/mysql-bkup:latest bkup -o backup -d database_name +docker run --rm --network your_network_name --name mysql-bkup -v $PWD/backup:/backup/ -e "DB_HOST=database_host_name" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" jkaninda/mysql-bkup:latest bkup backup -d database_name ``` ## Docker compose file: @@ -115,7 +117,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup -d database_name + - bkup backup -d database_name volumes: - ./backup:/backup environment: @@ -129,22 +131,22 @@ services: Simple database restore operation usage ```sh -bkup --operation restore --dbname database_name --file database_20231217_115621.sql +bkup restore --dbname database_name --file database_20231217_115621.sql ``` ```sh -bkup -o restore -f database_20231217_115621.sql +bkup restore -f database_20231217_115621.sql ``` ### S3 ```sh -bkup --operation restore --storage s3 --file database_20231217_115621.sql +bkup restore --storage s3 --file database_20231217_115621.sql ``` ## Docker run: ```sh -docker run --rm --network your_network_name --name mysql-bkup -v $PWD/backup:/backup/ -e "DB_HOST=database_host_name" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" jkaninda/mysql-bkup bkup -o backup -d database_name -f mydb_20231219_022941.sql.gz +docker run --rm --network your_network_name --name mysql-bkup -v $PWD/backup:/backup/ -e "DB_HOST=database_host_name" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" jkaninda/mysql-bkup bkup backup -d database_name -f db_20231219_022941.sql.gz ``` ## Docker compose file: @@ -166,7 +168,7 @@ services: command: - /bin/sh - -c - - bkup --operation restore --file database_20231217_115621.sql --dbname database_name + - bkup restore --file database_20231217_115621.sql --dbname database_name volumes: - ./backup:/backup environment: @@ -185,14 +187,14 @@ docker-compose up -d ## Backup to S3 ```sh -docker run --rm --privileged --device /dev/fuse --name mysql-bkup -e "DB_HOST=db_hostname" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" -e "ACCESS_KEY=your_access_key" -e "SECRET_KEY=your_secret_key" -e "BUCKETNAME=your_bucket_name" -e "S3_ENDPOINT=https://s3.us-west-2.amazonaws.com" jkaninda/mysql-bkup bkup -o backup -s s3 -d database_name +docker run --rm --privileged --device /dev/fuse --name mysql-bkup -e "DB_HOST=db_hostname" -e "DB_USERNAME=username" -e "DB_PASSWORD=password" -e "ACCESS_KEY=your_access_key" -e "SECRET_KEY=your_secret_key" -e "BUCKETNAME=your_bucket_name" -e "S3_ENDPOINT=https://s3.us-west-2.amazonaws.com" jkaninda/mysql-bkup bkup backup -s s3 -d database_name ``` > To change s3 backup path add this flag : --path /myPath . default path is /mysql_bkup Simple S3 backup usage ```sh -bkup --operation backup --storage s3 --dbname mydatabase +bkup backup --storage s3 --dbname mydatabase ``` ```yaml version: '3' @@ -206,7 +208,7 @@ services: command: - /bin/sh - -c - - mysql-bkup --operation restore --storage s3 -f database_20231217_115621.sql.gz + - mysql-bkup restore --storage s3 -f database_20231217_115621.sql.gz environment: - DB_PORT=3306 - DB_HOST=mysql @@ -273,7 +275,7 @@ Easy to remember format: > Docker run : ```sh -docker run --rm --name mysql-bkup -v $BACKUP_DIR:/backup/ -e "DB_HOST=$DB_HOST" -e "DB_USERNAME=$DB_USERNAME" -e "DB_PASSWORD=$DB_PASSWORD" jkaninda/mysql-bkup bkup --operation backup --dbname $DB_NAME --mode scheduled --period "0 1 * * *" +docker run --rm --name mysql-bkup -v $BACKUP_DIR:/backup/ -e "DB_HOST=$DB_HOST" -e "DB_USERNAME=$DB_USERNAME" -e "DB_PASSWORD=$DB_PASSWORD" jkaninda/mysql-bkup bkup backup --dbname $DB_NAME --mode scheduled --period "0 1 * * *" ``` > With Docker compose @@ -290,7 +292,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup --storage s3 --path /mys3_custome_path --dbname database_name --mode scheduled --period "*/30 * * * *" + - bkup backup --storage s3 --path /mys3_custome_path --dbname database_name --mode scheduled --period "*/30 * * * *" environment: - DB_PORT=3306 - DB_HOST=mysqlhost @@ -327,7 +329,7 @@ spec: command: - /bin/sh - -c - - bkup -o backup -s s3 --path /custom_path + - bkup backup -s s3 --path /custom_path env: - name: DB_PORT value: "3306" diff --git a/cmd/backup.go b/cmd/backup.go new file mode 100644 index 0000000..b536401 --- /dev/null +++ b/cmd/backup.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "github.com/jkaninda/mysql-bkup/pkg" + "github.com/jkaninda/mysql-bkup/utils" + "github.com/spf13/cobra" +) + +var BackupCmd = &cobra.Command{ + Use: "backup ", + Short: "Backup database operation", + Example: utils.BackupExample, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + pkg.StartBackup(cmd) + } else { + utils.Fatal("Error, no argument required") + } + }, +} + +func init() { + //Backup + BackupCmd.PersistentFlags().StringP("mode", "m", "default", "Set execution mode. default or scheduled") + BackupCmd.PersistentFlags().StringP("period", "", "0 1 * * *", "Set schedule period time") + BackupCmd.PersistentFlags().BoolP("disable-compression", "", false, "Disable backup compression") + +} diff --git a/cmd/history.go b/cmd/history.go new file mode 100644 index 0000000..2f4c67e --- /dev/null +++ b/cmd/history.go @@ -0,0 +1,14 @@ +package cmd + +import ( + "github.com/jkaninda/mysql-bkup/utils" + "github.com/spf13/cobra" +) + +var HistoryCmd = &cobra.Command{ + Use: "history", + Short: "Show the history of backup", + Run: func(cmd *cobra.Command, args []string) { + utils.ShowHistory() + }, +} diff --git a/cmd/restore.go b/cmd/restore.go new file mode 100644 index 0000000..53f57d0 --- /dev/null +++ b/cmd/restore.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "github.com/jkaninda/mysql-bkup/pkg" + "github.com/jkaninda/mysql-bkup/utils" + "github.com/spf13/cobra" +) + +var RestoreCmd = &cobra.Command{ + Use: "restore", + Short: "Restore database operation", + Example: utils.RestoreExample, + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + pkg.StartRestore(cmd) + } else { + utils.Fatal("Error, no argument required") + + } + + }, +} + +func init() { + //Restore + RestoreCmd.PersistentFlags().StringP("file", "f", "", "File name of database") + +} diff --git a/cmd/root.go b/cmd/root.go index d9079bd..20cc0f0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,20 +5,32 @@ Copyright © 2024 Jonas Kaninda package cmd import ( - "os" - + "fmt" + "github.com/jkaninda/mysql-bkup/utils" "github.com/spf13/cobra" + "os" ) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: "mysql-bkup", - Short: "MySQL Backup tool, backup database to S3 or Object Storage", - Long: `MySQL Database backup and restoration tool. Backup database to AWS S3 storage or any S3 Alternatives for Object Storage.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + Use: "mysql-bkup [Command]", + Short: "MySQL Backup tool, backup database to S3 or Object Storage", + Long: `MySQL Database backup and restoration tool. Backup database to AWS S3 storage or any S3 Alternatives for Object Storage.`, + Example: utils.MainExample, + Version: appVersion, + //TODO: To remove + //For old user || To remove + Run: func(cmd *cobra.Command, args []string) { + if operation != "" { + if operation == "backup" || operation == "restore" { + fmt.Println(utils.Notice) + utils.Fatal("New config required, please check --help") + } + } + }, } +var operation = "" +var s3Path = "/mysql-bkup" // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. @@ -30,22 +42,16 @@ func Execute() { } func init() { - - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.mysql-bkup.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.PersistentFlags().StringP("operation", "o", "backup", "Set operation") rootCmd.PersistentFlags().StringP("storage", "s", "local", "Set storage. local or s3") - rootCmd.PersistentFlags().StringP("file", "f", "", "Set file name") - rootCmd.PersistentFlags().StringP("path", "P", "/mysql-bkup", "Set s3 path, without file name") + rootCmd.PersistentFlags().StringP("path", "P", s3Path, "Set s3 path, without file name. for S3 storage only") rootCmd.PersistentFlags().StringP("dbname", "d", "", "Set database name") - rootCmd.PersistentFlags().StringP("mode", "m", "default", "Set execution mode. default or scheduled") - rootCmd.PersistentFlags().StringP("period", "", "0 1 * * *", "Set schedule period time") rootCmd.PersistentFlags().IntP("timeout", "t", 30, "Set timeout") - rootCmd.PersistentFlags().BoolP("disable-compression", "", false, "Disable backup compression") rootCmd.PersistentFlags().IntP("port", "p", 3306, "Set database port") - rootCmd.PersistentFlags().BoolP("help", "h", false, "Print this help message") - rootCmd.PersistentFlags().BoolP("version", "v", false, "shows version information") + rootCmd.PersistentFlags().StringVarP(&operation, "operation", "o", "", "Set operation, for old version only") + rootCmd.AddCommand(VersionCmd) + rootCmd.AddCommand(BackupCmd) + rootCmd.AddCommand(RestoreCmd) + rootCmd.AddCommand(S3MountCmd) + rootCmd.AddCommand(HistoryCmd) } diff --git a/cmd/s3mount.go b/cmd/s3mount.go new file mode 100644 index 0000000..61f2c00 --- /dev/null +++ b/cmd/s3mount.go @@ -0,0 +1,14 @@ +package cmd + +import ( + "github.com/jkaninda/mysql-bkup/pkg" + "github.com/spf13/cobra" +) + +var S3MountCmd = &cobra.Command{ + Use: "s3mount", + Short: "Mount AWS S3 storage", + Run: func(cmd *cobra.Command, args []string) { + pkg.S3Mount() + }, +} diff --git a/cmd/version.go b/cmd/version.go index f9f7e23..1e734a5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,5 +1,9 @@ package cmd +/* +Copyright © 2024 Jonas Kaninda +*/ + import ( "fmt" "github.com/spf13/cobra" @@ -16,8 +20,7 @@ var VersionCmd = &cobra.Command{ }, } -// Version display application version func Version() { fmt.Printf("Version: %s \n", appVersion) - fmt.Print() + fmt.Println() } diff --git a/docker/Dockerfile b/docker/Dockerfile index bd65a9c..0a27fd2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,7 +21,7 @@ ENV ACCESS_KEY="" ENV SECRET_KEY="" ENV S3_ENDPOINT=https://s3.amazonaws.com ARG DEBIAN_FRONTEND=noninteractive -ENV VERSION="v0.4" +ENV VERSION="v0.5" LABEL authors="Jonas Kaninda" RUN apt-get update -qq diff --git a/examples/docker-compose.s3.yaml b/examples/docker-compose.s3.yaml index 4f3d63f..bedd557 100644 --- a/examples/docker-compose.s3.yaml +++ b/examples/docker-compose.s3.yaml @@ -9,7 +9,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup --storage s3 --path /mys3_custom_path --dbname database_name + - bkup backup --storage s3 --path /mys3_custom_path --dbname database_name environment: - DB_PORT=3306 - DB_HOST=mysqlhost diff --git a/examples/docker-compose.scheduled.local.yaml b/examples/docker-compose.scheduled.local.yaml index b82412c..ecef5d1 100644 --- a/examples/docker-compose.scheduled.local.yaml +++ b/examples/docker-compose.scheduled.local.yaml @@ -6,7 +6,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup --dbname database_name --mode scheduled --period "0 1 * * *" + - bkup backup --dbname database_name --mode scheduled --period "0 1 * * *" volumes: - ./backup:/backup environment: diff --git a/examples/docker-compose.scheduled.s3.yaml b/examples/docker-compose.scheduled.s3.yaml index 355289a..c4b8a3b 100644 --- a/examples/docker-compose.scheduled.s3.yaml +++ b/examples/docker-compose.scheduled.s3.yaml @@ -9,7 +9,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup --storage s3 --path /mys3_custom_path --dbname database_name --mode scheduled --period "0 1 * * *" + - bkup backup --storage s3 --path /mys3_custom_path --dbname database_name --mode scheduled --period "0 1 * * *" environment: - DB_PORT=3306 - DB_HOST=mysqlhost diff --git a/examples/docker-compose.yaml b/examples/docker-compose.yaml index b35bf09..f0bff9f 100644 --- a/examples/docker-compose.yaml +++ b/examples/docker-compose.yaml @@ -6,7 +6,7 @@ services: command: - /bin/sh - -c - - bkup --operation backup --dbname database_name + - bkup backup --dbname database_name volumes: - ./backup:/backup environment: diff --git a/examples/k8s-job.yaml b/examples/k8s-job.yaml index 0dc826c..ba31059 100644 --- a/examples/k8s-job.yaml +++ b/examples/k8s-job.yaml @@ -16,7 +16,7 @@ spec: command: - /bin/sh - -c - - bkup --operation backup --storage s3 --path /custom_path + - bkup backup --storage s3 --path /custom_path env: - name: DB_PORT value: "3306" diff --git a/main.go b/main.go index cb47aba..c0f1b7b 100644 --- a/main.go +++ b/main.go @@ -1,218 +1,16 @@ package main +//main /***** * MySQL Backup & Restore * @author Jonas Kaninda * @license MIT License * @link https://github.com/jkaninda/mysql-bkup **/ -import ( - "fmt" - "github.com/jkaninda/mysql-bkup/cmd" - "github.com/jkaninda/mysql-bkup/pkg" - "github.com/jkaninda/mysql-bkup/utils" - flag "github.com/spf13/pflag" - "os" - "os/exec" -) - -const s3MountPath string = "/s3mnt" - -var ( - operation string = "backup" - storage string = "local" - file string = "" - s3Path string = "/mysql-bkup" - dbName string = "" - dbHost string = "" - dbPort string = "" - dbPassword string = "" - dbUserName string = "" - executionMode string = "default" - storagePath string = "/backup" - accessKey string = "" - secretKey string = "" - bucketName string = "" - s3Endpoint string = "" - s3fsPasswdFile string = "/etc/passwd-s3fs" - disableCompression bool = false - startBackup bool = true - - timeout int = 30 - period string = "0 1 * * *" -) - -func init() { - var ( - operationFlag = flag.StringP("operation", "o", "backup", "Operation") - storageFlag = flag.StringP("storage", "s", "local", "Storage, local or s3") - fileFlag = flag.StringP("file", "f", "", "File name") - pathFlag = flag.StringP("path", "P", "/mysql-bkup", "S3 path, without file name") - dbnameFlag = flag.StringP("dbname", "d", "", "Database name") - modeFlag = flag.StringP("mode", "m", "default", "Execution mode. default or scheduled") - periodFlag = flag.StringP("period", "", "0 1 * * *", "Schedule period time") - timeoutFlag = flag.IntP("timeout", "t", 30, "Timeout (in seconds) to stop database connexion") - disableCompressionFlag = flag.BoolP("disable-compression", "", false, "Disable backup compression") - portFlag = flag.IntP("port", "p", 3306, "Database port") - helpFlag = flag.BoolP("help", "h", false, "Print this help message") - versionFlag = flag.BoolP("version", "v", false, "Version information") - ) - flag.Parse() - - operation = *operationFlag - storage = *storageFlag - file = *fileFlag - s3Path = *pathFlag - dbName = *dbnameFlag - executionMode = *modeFlag - dbPort = fmt.Sprint(*portFlag) - timeout = *timeoutFlag - period = *periodFlag - disableCompression = *disableCompressionFlag - - flag.Usage = func() { - fmt.Print("MySQL Database backup and restoration tool. Backup database to AWS S3 storage or any S3 Alternatives for Object Storage.\n\n") - fmt.Print("Usage: bkup --operation backup -storage s3 --dbname databasename --path /my_path ...\n") - fmt.Print(" bkup -o backup -d databasename --disable-compression ...\n") - fmt.Print(" Restore: bkup -o restore -d databasename -f db_20231217_051339.sql.gz ...\n\n") - flag.PrintDefaults() - } - - if *helpFlag { - startBackup = false - flag.Usage() - os.Exit(0) - } - if *versionFlag { - startBackup = false - cmd.Version() - os.Exit(0) - } - if *dbnameFlag != "" { - err := os.Setenv("DB_NAME", dbName) - if err != nil { - return - } - } - if *pathFlag != "" { - s3Path = *pathFlag - err := os.Setenv("S3_PATH", fmt.Sprint(*pathFlag)) - if err != nil { - return - } - - } - if *fileFlag != "" { - file = *fileFlag - err := os.Setenv("FILE_NAME", fmt.Sprint(*fileFlag)) - if err != nil { - return - } - - } - if *portFlag != 3306 { - err := os.Setenv("DB_PORT", fmt.Sprint(*portFlag)) - if err != nil { - return - } - } - if *periodFlag != "" { - err := os.Setenv("SCHEDULE_PERIOD", fmt.Sprint(*periodFlag)) - if err != nil { - return - } - } - if *storageFlag != "" { - err := os.Setenv("STORAGE", fmt.Sprint(*storageFlag)) - if err != nil { - return - } - } - storage = os.Getenv("STORAGE") - err := os.Setenv("STORAGE_PATH", storagePath) - if err != nil { - return - } - -} +import "github.com/jkaninda/mysql-bkup/cmd" func main() { - err := os.Setenv("STORAGE_PATH", storagePath) - if err != nil { - return - } - if startBackup { - start() - } + cmd.Execute() } -func start() { - - if executionMode == "default" { - if operation != "backup" { - if storage != "s3" { - utils.Info("Restore database from local") - pkg.RestoreDatabase(file) - } else { - //Restore from S3 - utils.Info("Restore database from s3") - s3Restore() - } - } else { - if storage != "s3" { - utils.Info("Backup database to local storage") - pkg.BackupDatabase(disableCompression) - } else { - //Backup to S3 - utils.Info("Backup database to s3 storage") - s3Backup() - } - } - } else if executionMode == "scheduled" { - scheduledMode() - } else { - utils.Fatal("Error, unknown execution mode!") - } -} - -func s3Backup() { - // Backup Database to S3 storage - pkg.MountS3Storage(s3Path) - pkg.BackupDatabase(disableCompression) -} - -// Run in scheduled mode -func scheduledMode() { - // Verify operation - if operation == "backup" { - - fmt.Println() - fmt.Println("**********************************") - fmt.Println(" Starting MySQL Bkup... ") - fmt.Println("***********************************") - utils.Info("Running in Scheduled mode") - utils.Info("Log file in /var/log/mysql-bkup.log") - utils.Info("Execution period ", os.Getenv("SCHEDULE_PERIOD")) - - //Test database connexion - utils.TestDatabaseConnection() - - utils.Info("Creating backup job...") - pkg.CreateCrontabScript(disableCompression, storage) - - //Start Supervisor - supervisordCmd := exec.Command("supervisord", "-c", "/etc/supervisor/supervisord.conf") - if err := supervisordCmd.Run(); err != nil { - utils.Fatalf("Error starting supervisord: %v\n", err) - } - } else { - utils.Fatal("Scheduled mode supports only backup operation") - } -} - -func s3Restore() { - // Restore database from S3 - pkg.MountS3Storage(s3Path) - pkg.RestoreDatabase(file) -} diff --git a/pkg/backup.go b/pkg/backup.go index fdb09a9..396ccfc 100644 --- a/pkg/backup.go +++ b/pkg/backup.go @@ -7,26 +7,75 @@ package pkg import ( "fmt" "github.com/jkaninda/mysql-bkup/utils" + "github.com/spf13/cobra" "log" "os" "os/exec" "time" ) -var ( - dbName = "" - dbHost = "" - dbPort = "" - dbPassword = "" - dbUserName = "" - storagePath = "/backup" -) +func StartBackup(cmd *cobra.Command) { + _, _ = cmd.Flags().GetString("operation") + + //Set env + utils.SetEnv("STORAGE_PATH", storagePath) + utils.GetEnv(cmd, "dbname", "DB_NAME") + utils.GetEnv(cmd, "port", "DB_PORT") + utils.GetEnv(cmd, "period", "SCHEDULE_PERIOD") + + //Get flag value and set env + s3Path = utils.GetEnv(cmd, "path", "S3_PATH") + storage = utils.GetEnv(cmd, "storage", "STORAGE") + file = utils.GetEnv(cmd, "file", "FILE_NAME") + disableCompression, _ = cmd.Flags().GetBool("disable-compression") + executionMode, _ = cmd.Flags().GetString("mode") + + if executionMode == "default" { + if storage == "s3" { + utils.Info("Backup database to s3 storage") + s3Backup(disableCompression, s3Path) + } else { + utils.Info("Backup database to local storage") + BackupDatabase(disableCompression) + + } + } else if executionMode == "scheduled" { + scheduledMode() + } else { + utils.Fatal("Error, unknown execution mode!") + } + +} + +// Run in scheduled mode +func scheduledMode() { + + fmt.Println() + fmt.Println("**********************************") + fmt.Println(" Starting MySQL Bkup... ") + fmt.Println("***********************************") + utils.Info("Running in Scheduled mode") + utils.Info("Log file in /var/log/mysql-bkup.log") + utils.Info("Execution period ", os.Getenv("SCHEDULE_PERIOD")) + + //Test database connexion + utils.TestDatabaseConnection() + + utils.Info("Creating backup job...") + CreateCrontabScript(disableCompression, storage) + + //Start Supervisor + supervisordCmd := exec.Command("supervisord", "-c", "/etc/supervisor/supervisord.conf") + if err := supervisordCmd.Run(); err != nil { + utils.Fatalf("Error starting supervisord: %v\n", err) + } +} // BackupDatabase backup database func BackupDatabase(disableCompression bool) { dbHost = os.Getenv("DB_HOST") - dbPassword = os.Getenv("DB_PASSWORD") - dbUserName = os.Getenv("DB_USERNAME") + dbPassword := os.Getenv("DB_PASSWORD") + dbUserName := os.Getenv("DB_USERNAME") dbName = os.Getenv("DB_NAME") dbPort = os.Getenv("DB_PORT") storagePath = os.Getenv("STORAGE_PATH") @@ -105,3 +154,9 @@ func BackupDatabase(disableCompression bool) { } } + +func s3Backup(disableCompression bool, s3Path string) { + // Backup Database to S3 storage + MountS3Storage(s3Path) + BackupDatabase(disableCompression) +} diff --git a/pkg/restore.go b/pkg/restore.go index 28fd6a4..6731757 100644 --- a/pkg/restore.go +++ b/pkg/restore.go @@ -3,19 +3,44 @@ package pkg import ( "fmt" "github.com/jkaninda/mysql-bkup/utils" + "github.com/spf13/cobra" "os" "os/exec" "path/filepath" ) +func StartRestore(cmd *cobra.Command) { + + //Set env + utils.SetEnv("STORAGE_PATH", storagePath) + utils.GetEnv(cmd, "dbname", "DB_NAME") + utils.GetEnv(cmd, "port", "DB_PORT") + + //Get flag value and set env + s3Path = utils.GetEnv(cmd, "path", "S3_PATH") + storage = utils.GetEnv(cmd, "storage", "STORAGE") + file = utils.GetEnv(cmd, "file", "FILE_NAME") + executionMode, _ = cmd.Flags().GetString("mode") + + if storage == "s3" { + utils.Info("Restore database from s3") + s3Restore(file, s3Path) + } else { + utils.Info("Restore database from local") + RestoreDatabase(file) + + } +} + // RestoreDatabase restore database func RestoreDatabase(file string) { dbHost = os.Getenv("DB_HOST") - dbPassword = os.Getenv("DB_PASSWORD") - dbUserName = os.Getenv("DB_USERNAME") dbName = os.Getenv("DB_NAME") dbPort = os.Getenv("DB_PORT") storagePath = os.Getenv("STORAGE_PATH") + if file == "" { + utils.Fatal("Error required --file") + } if os.Getenv("DB_HOST") == "" || os.Getenv("DB_NAME") == "" || os.Getenv("DB_USERNAME") == "" || os.Getenv("DB_PASSWORD") == "" || file == "" { utils.Fatal("Please make sure all required environment variables are set") @@ -54,3 +79,8 @@ func RestoreDatabase(file string) { } } +func s3Restore(file, s3Path string) { + // Restore database from S3 + MountS3Storage(s3Path) + RestoreDatabase(file) +} diff --git a/pkg/s3fs.go b/pkg/s3fs.go index 8472fc7..33c8811 100644 --- a/pkg/s3fs.go +++ b/pkg/s3fs.go @@ -11,9 +11,6 @@ import ( "os/exec" ) -const s3MountPath string = "/s3mnt" -const s3fsPasswdFile string = "/etc/passwd-s3fs" - var ( accessKey = "" secretKey = "" @@ -21,6 +18,10 @@ var ( s3Endpoint = "" ) +func S3Mount() { + MountS3Storage(s3Path) +} + // MountS3Storage Mount s3 storage using s3fs func MountS3Storage(s3Path string) { accessKey = os.Getenv("ACCESS_KEY") @@ -46,7 +47,7 @@ func MountS3Storage(s3Path string) { utils.ChangePermission(s3fsPasswdFile, 0600) //Mount object storage - utils.Info("Mounting Object storage in", s3MountPath) + utils.Info("Mounting Object storage in ", s3MountPath) if isEmpty, _ := utils.IsDirEmpty(s3MountPath); isEmpty { cmd := exec.Command("s3fs", bucketName, s3MountPath, "-o", "passwd_file="+s3fsPasswdFile, diff --git a/pkg/scripts.go b/pkg/scripts.go index 3250e48..e81d072 100644 --- a/pkg/scripts.go +++ b/pkg/scripts.go @@ -30,12 +30,12 @@ func CreateCrontabScript(disableCompression bool, storage string) { if storage == "s3" { scriptContent = fmt.Sprintf(`#!/usr/bin/env bash set -e -bkup --operation backup --dbname %s --port %s --storage s3 --path %s %v +bkup backup --dbname %s --port %s --storage s3 --path %s %v `, os.Getenv("DB_NAME"), os.Getenv("DB_PORT"), os.Getenv("S3_PATH"), disableC) } else { scriptContent = fmt.Sprintf(`#!/usr/bin/env bash set -e -bkup --operation backup --dbname %s --port %s %v +bkup backup --dbname %s --port %s %v `, os.Getenv("DB_NAME"), os.Getenv("DB_PORT"), disableC) } diff --git a/pkg/var.go b/pkg/var.go new file mode 100644 index 0000000..3f7045e --- /dev/null +++ b/pkg/var.go @@ -0,0 +1,16 @@ +package pkg + +const s3MountPath string = "/s3mnt" +const s3fsPasswdFile string = "/etc/passwd-s3fs" + +var ( + storage = "local" + file = "" + s3Path = "/mysql-bkup" + dbName = "" + dbHost = "" + dbPort = "3306" + executionMode = "default" + storagePath = "/backup" + disableCompression = false +) diff --git a/scripts/backup_script.sh b/scripts/backup_script.sh index 769b55f..a4be9a7 100755 --- a/scripts/backup_script.sh +++ b/scripts/backup_script.sh @@ -5,4 +5,4 @@ DB_HOST='db_hostname' DB_NAME='db_name' BACKUP_DIR="$PWD/backup" -docker run --rm --name mysql-bkup -v $BACKUP_DIR:/backup/ -e "DB_HOST=$DB_HOST" -e "DB_USERNAME=$DB_USERNAME" -e "DB_PASSWORD=$DB_PASSWORD" jkaninda/mysql-bkup:latest bkup -o backup -d $DB_NAME \ No newline at end of file +docker run --rm --name mysql-bkup -v $BACKUP_DIR:/backup/ -e "DB_HOST=$DB_HOST" -e "DB_USERNAME=$DB_USERNAME" -e "DB_PASSWORD=$DB_PASSWORD" jkaninda/mysql-bkup:latest backup -d $DB_NAME \ No newline at end of file diff --git a/utils/constant.go b/utils/constant.go new file mode 100644 index 0000000..c76dbae --- /dev/null +++ b/utils/constant.go @@ -0,0 +1,15 @@ +package utils + +const Notice = "Please remove --operation flag.\n" + + "Use: \n" + + "- backup for backup operation [eg: bkup backup -d database_name ...]\n" + + "- restore for restore operation [eg. bkup restore -d database_name ...]\n" + + "We are sorry for this inconvenient" +const RestoreExample = "mysql-bkup restore --dbname database --file db_20231219_022941.sql.gz\n" + + "bkup restore --dbname database --storage s3 --path /custom-path --file db_20231219_022941.sql.gz" +const BackupExample = "mysql-bkup backup --dbname database --disable-compression\n" + + "mysql-bkup backup --dbname database --storage s3 --path /custom-path --disable-compression" + +const MainExample = "mysql-bkup backup --dbname database --disable-compression\n" + + "mysql-bkup backup --dbname database --storage s3 --path /custom-path\n" + + "mysql-bkup restore --dbname database --file db_20231219_022941.sql.gz" diff --git a/utils/utils.go b/utils/utils.go index a6fc8cf..e17b801 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -8,6 +8,7 @@ package utils **/ import ( "fmt" + "github.com/spf13/cobra" "io/fs" "os" "os/exec" @@ -78,3 +79,36 @@ func TestDatabaseConnection() { } } +func GetEnv(cmd *cobra.Command, flagName, envName string) string { + value, _ := cmd.Flags().GetString(flagName) + if value != "" { + err := os.Setenv(envName, value) + if err != nil { + return value + } + } + return os.Getenv(envName) +} +func FlagGetString(cmd *cobra.Command, flagName string) string { + value, _ := cmd.Flags().GetString(flagName) + if value != "" { + return value + + } + return "" +} +func FlagGetBool(cmd *cobra.Command, flagName string) bool { + value, _ := cmd.Flags().GetBool(flagName) + return value +} + +func SetEnv(key, value string) { + + err := os.Setenv(key, value) + if err != nil { + return + } +} + +func ShowHistory() { +}