diff --git a/README.md b/README.md index 2f40b98..1d62811 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,9 @@ For Kubernetes, you don't need to run it in scheduled mode. You can deploy it as apiVersion: batch/v1 kind: Job metadata: - name: backup + name: backup-job spec: + ttlSecondsAfterFinished: 100 template: spec: containers: @@ -109,38 +110,27 @@ spec: command: - /bin/sh - -c - - bkup - - backup - - --storage - - s3 + - backup -d dbname resources: limits: memory: "128Mi" cpu: "500m" env: - - name: DB_PORT - value: "5432" - name: DB_HOST - value: "" - - name: DB_NAME - value: "" + value: "postgres" - name: DB_USERNAME - value: "" - # Please use secret! + value: "postgres" - name: DB_PASSWORD - value: "" - - name: AWS_S3_ENDPOINT - value: "https://s3.amazonaws.com" - - name: AWS_S3_BUCKET_NAME - value: "xxx" - - name: AWS_REGION - value: "us-west-2" - - name: AWS_ACCESS_KEY - value: "xxxx" - - name: AWS_SECRET_KEY - value: "xxxx" - - name: AWS_DISABLE_SSL - value: "false" + value: "password" + volumeMounts: + - mountPath: /backup + name: backup + volumes: + - name: backup + hostPath: + path: /home/toto/backup # directory location on host + type: Directory # this field is optional + restartPolicy: Never ``` ## Available image registries diff --git a/cmd/backup.go b/cmd/backup.go index 5d48819..fc5f76b 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -21,6 +21,8 @@ var BackupCmd = &cobra.Command{ func init() { //Backup + BackupCmd.PersistentFlags().StringP("storage", "s", "local", "Storage. local or s3") + BackupCmd.PersistentFlags().StringP("path", "P", "", "AWS S3 path without file name. eg: /custom_path or ssh remote path `/home/foo/backup`") BackupCmd.PersistentFlags().StringP("mode", "m", "default", "Execution mode. default or scheduled") BackupCmd.PersistentFlags().StringP("period", "", "0 1 * * *", "Schedule period time") BackupCmd.PersistentFlags().BoolP("prune", "", false, "Delete old backup, default disabled") diff --git a/cmd/migrate.go b/cmd/migrate.go new file mode 100644 index 0000000..70af8b6 --- /dev/null +++ b/cmd/migrate.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "github.com/jkaninda/pg-bkup/pkg" + "github.com/jkaninda/pg-bkup/utils" + "github.com/spf13/cobra" +) + +var MigrateCmd = &cobra.Command{ + Use: "migrate", + Short: "Migrate database from a source database to a target database", + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + pkg.StartMigration(cmd) + } else { + utils.Fatal("Error, no argument required") + + } + + }, +} diff --git a/cmd/restore.go b/cmd/restore.go index 4e275ef..b81da31 100644 --- a/cmd/restore.go +++ b/cmd/restore.go @@ -24,5 +24,7 @@ var RestoreCmd = &cobra.Command{ func init() { //Restore RestoreCmd.PersistentFlags().StringP("file", "f", "", "File name of database") + RestoreCmd.PersistentFlags().StringP("storage", "s", "local", "Storage. local or s3") + RestoreCmd.PersistentFlags().StringP("path", "P", "", "AWS S3 path without file name. eg: /custom_path or ssh remote path `/home/foo/backup`") } diff --git a/cmd/root.go b/cmd/root.go index 613a335..13de869 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,7 +18,6 @@ var rootCmd = &cobra.Command{ Example: utils.MainExample, Version: appVersion, } -var operation = "" // 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,12 +29,10 @@ func Execute() { } func init() { - rootCmd.PersistentFlags().StringP("storage", "s", "local", "Storage. local or s3") - rootCmd.PersistentFlags().StringP("path", "P", "", "AWS S3 path without file name. eg: /custom_path or ssh remote path `/home/foo/backup`") rootCmd.PersistentFlags().StringP("dbname", "d", "", "Database name") rootCmd.PersistentFlags().IntP("port", "p", 5432, "Database port") - rootCmd.PersistentFlags().StringVarP(&operation, "operation", "o", "", "Set operation, for old version only") rootCmd.AddCommand(VersionCmd) rootCmd.AddCommand(BackupCmd) rootCmd.AddCommand(RestoreCmd) + rootCmd.AddCommand(MigrateCmd) } diff --git a/docker/Dockerfile b/docker/Dockerfile index 7c81f8c..0c9cb0e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -14,7 +14,7 @@ ENV DB_HOST="" ENV DB_NAME="" ENV DB_USERNAME="" ENV DB_PASSWORD="" -ENV DB_PORT="5432" +ENV DB_PORT=5432 ENV STORAGE=local ENV AWS_S3_ENDPOINT="" ENV AWS_S3_BUCKET_NAME="" @@ -30,11 +30,15 @@ ENV SSH_PASSWORD="" ENV SSH_HOST_NAME="" ENV SSH_IDENTIFY_FILE="" ENV SSH_PORT="22" +ENV SOURCE_DB_HOST="" +ENV SOURCE_DB_PORT=5432 +ENV SOURCE_DB_NAME="" +ENV SOURCE_DB_USERNAME="" +ENV SOURCE_DB_PASSWORD="" ARG DEBIAN_FRONTEND=noninteractive -ENV VERSION="v1.2.2" +ENV VERSION="v1.2.3" ENV BACKUP_CRON_EXPRESSION="" -ENV GNUPGHOME="/tmp/gnupg" -ARG WORKDIR="/app" +ARG WORKDIR="/config" ARG BACKUPDIR="/backup" ARG BACKUP_TMP_DIR="/tmp/backup" ARG BACKUP_CRON="/etc/cron.d/backup_cron" @@ -50,37 +54,32 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* RUN mkdir $WORKDIR RUN mkdir $BACKUPDIR -RUN mkdir -p $BACKUP_TMP_DIR && \ - mkdir -p $GNUPGHOME +RUN mkdir -p $BACKUP_TMP_DIR RUN chmod 777 $WORKDIR RUN chmod 777 $BACKUPDIR RUN chmod 777 $BACKUP_TMP_DIR RUN touch $BACKUP_CRON && \ touch $BACKUP_CRON_SCRIPT && \ + chmod 777 $WORKDIR && \ chmod 777 $BACKUP_CRON && \ - chmod 777 $BACKUP_CRON_SCRIPT && \ - chmod 777 $GNUPGHOME - + chmod 777 $BACKUP_CRON_SCRIPT COPY --from=build /app/pg-bkup /usr/local/bin/pg-bkup RUN chmod +x /usr/local/bin/pg-bkup RUN ln -s /usr/local/bin/pg-bkup /usr/local/bin/bkup ADD docker/supervisord.conf /etc/supervisor/supervisord.conf +# Create the backup script and make it executable +RUN echo '#!/bin/sh\n/usr/local/bin/pg-bkup backup "$@"' > /usr/local/bin/backup && \ + chmod +x /usr/local/bin/backup + +# Create the restore script and make it executable +RUN echo '#!/bin/sh\n/usr/local/bin/pg-bkup restore "$@"' > /usr/local/bin/restore && \ + chmod +x /usr/local/bin/restore +# Create the migrate script and make it executable +RUN echo '#!/bin/sh\n/usr/local/bin/pg-bkup migrate "$@"' > /usr/local/bin/migrate && \ + chmod +x /usr/local/bin/migrate WORKDIR $WORKDIR -# Create backup shell script -COPY < -* @link https://github.com/jkaninda/mysql-bkup +* @link https://github.com/jkaninda/pg-bkup **/ import ( - "bytes" "fmt" "github.com/spf13/cobra" "io" "io/fs" "os" - "os/exec" ) func FileExists(filename string) bool { @@ -90,49 +88,6 @@ func IsDirEmpty(name string) (bool, error) { return true, nil } -// TestDatabaseConnection tests the database connection -func TestDatabaseConnection() { - 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") - - if os.Getenv("DB_HOST") == "" || os.Getenv("DB_NAME") == "" || os.Getenv("DB_USERNAME") == "" || os.Getenv("DB_PASSWORD") == "" { - Fatal("Please make sure all required database environment variables are set") - } else { - Info("Connecting to database ...") - // Test database connection - query := "SELECT version();" - - // Set the environment variable for the database password - err := os.Setenv("PGPASSWORD", dbPassword) - if err != nil { - return - } - // Prepare the psql command - cmd := exec.Command("psql", - "-U", dbUserName, // database user - "-d", dbName, // database name - "-h", dbHost, // host - "-p", dbPort, // port - "-c", query, // SQL command to execute - ) - // Capture the output - var out bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &out - - // Run the command and capture any errors - err = cmd.Run() - if err != nil { - Error("Error running psql command: %v\nOutput: %s\n", err, out.String()) - return - } - Info("Successfully connected to database") - - } -} func GetEnv(cmd *cobra.Command, flagName, envName string) string { value, _ := cmd.Flags().GetString(flagName) if value != "" { @@ -194,3 +149,21 @@ func CheckEnvVars(vars []string) error { return nil } + +// MakeDir create directory +func MakeDir(dirPath string) error { + err := os.Mkdir(dirPath, 0700) + if err != nil { + return err + } + return nil +} + +// MakeDirAll create directory +func MakeDirAll(dirPath string) error { + err := os.MkdirAll(dirPath, 0700) + if err != nil { + return err + } + return nil +}