Compare commits

...

8 Commits

Author SHA1 Message Date
0df14f37b4 Merge pull request #159 from jkaninda/refactor
chore: add convert bytes to a human-readable string with the appropri…
2024-12-12 13:29:22 +01:00
1b60ca6fd2 chore: add convert bytes to a human-readable string with the appropriate unit (bytes, MiB, or GiB) 2024-12-12 13:28:09 +01:00
d880f40108 Merge pull request #158 from jkaninda/dependabot/docker/golang-1.23.4
chore(deps): bump golang from 1.23.3 to 1.23.4
2024-12-10 10:20:27 +01:00
dependabot[bot]
c845b36797 chore(deps): bump golang from 1.23.3 to 1.23.4
Bumps golang from 1.23.3 to 1.23.4.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 09:53:21 +00:00
63d615f838 Merge pull request #157 from jkaninda/refactor
docs: add azure configuration reference
2024-12-08 13:36:26 +01:00
6f31d35df2 docs: add azure configuration reference 2024-12-08 13:35:49 +01:00
f36d01cc96 Merge pull request #156 from jkaninda/refactor
Fix grammar issues in azure.go
2024-12-08 00:01:13 +01:00
07b7f54a75 Fix grammar issues in azure.go 2024-12-08 00:00:24 +01:00
13 changed files with 79 additions and 58 deletions

View File

@@ -1,4 +1,4 @@
FROM golang:1.23.3 AS build FROM golang:1.23.4 AS build
WORKDIR /app WORKDIR /app
ARG appVersion="" ARG appVersion=""

View File

@@ -32,44 +32,46 @@ Backup, restore and migrate targets, schedule and retention are configured using
## Environment variables ## Environment variables
| Name | Requirement | Description | | Name | Requirement | Description |
|------------------------|---------------------------------------------------------------|-----------------------------------------------------------------| |------------------------------|---------------------------------------------------------------|-----------------------------------------------------------------|
| DB_PORT | Optional, default 3306 | Database port number | | DB_PORT | Optional, default 3306 | Database port number |
| DB_HOST | Required | Database host | | DB_HOST | Required | Database host |
| DB_NAME | Optional if it was provided from the -d flag | Database name | | DB_NAME | Optional if it was provided from the -d flag | Database name |
| DB_USERNAME | Required | Database user name | | DB_USERNAME | Required | Database user name |
| DB_PASSWORD | Required | Database password | | DB_PASSWORD | Required | Database password |
| AWS_ACCESS_KEY | Optional, required for S3 storage | AWS S3 Access Key | | AWS_ACCESS_KEY | Optional, required for S3 storage | AWS S3 Access Key |
| AWS_SECRET_KEY | Optional, required for S3 storage | AWS S3 Secret Key | | AWS_SECRET_KEY | Optional, required for S3 storage | AWS S3 Secret Key |
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name | | AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name | | AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
| AWS_REGION | Optional, required for S3 storage | AWS Region | | AWS_REGION | Optional, required for S3 storage | AWS Region |
| AWS_DISABLE_SSL | Optional, required for S3 storage | Disable SSL | | AWS_DISABLE_SSL | Optional, required for S3 storage | Disable SSL |
| AWS_FORCE_PATH_STYLE | Optional, required for S3 storage | Force path style | | AWS_FORCE_PATH_STYLE | Optional, required for S3 storage | Force path style |
| FILE_NAME | Optional if it was provided from the --file flag | Database file to restore (extensions: .sql, .sql.gz) | | FILE_NAME | Optional if it was provided from the --file flag | Database file to restore (extensions: .sql, .sql.gz) |
| GPG_PASSPHRASE | Optional, required to encrypt and restore backup | GPG passphrase | | GPG_PASSPHRASE | Optional, required to encrypt and restore backup | GPG passphrase |
| GPG_PUBLIC_KEY | Optional, required to encrypt backup | GPG public key, used to encrypt backup (/config/public_key.asc) | | GPG_PUBLIC_KEY | Optional, required to encrypt backup | GPG public key, used to encrypt backup (/config/public_key.asc) |
| BACKUP_CRON_EXPRESSION | Optional if it was provided from the `--cron-expression` flag | Backup cron expression for docker in scheduled mode | | BACKUP_CRON_EXPRESSION | Optional if it was provided from the `--cron-expression` flag | Backup cron expression for docker in scheduled mode |
| BACKUP_RETENTION_DAYS | Optional | Delete old backup created more than specified days ago | | BACKUP_RETENTION_DAYS | Optional | Delete old backup created more than specified days ago |
| SSH_HOST | Optional, required for SSH storage | ssh remote hostname or ip | | SSH_HOST | Optional, required for SSH storage | ssh remote hostname or ip |
| SSH_USER | Optional, required for SSH storage | ssh remote user | | SSH_USER | Optional, required for SSH storage | ssh remote user |
| SSH_PASSWORD | Optional, required for SSH storage | ssh remote user's password | | SSH_PASSWORD | Optional, required for SSH storage | ssh remote user's password |
| SSH_IDENTIFY_FILE | Optional, required for SSH storage | ssh remote user's private key | | SSH_IDENTIFY_FILE | Optional, required for SSH storage | ssh remote user's private key |
| SSH_PORT | Optional, required for SSH storage | ssh remote server port | | SSH_PORT | Optional, required for SSH storage | ssh remote server port |
| REMOTE_PATH | Optional, required for SSH or FTP storage | remote path (/home/toto/backup) | | REMOTE_PATH | Optional, required for SSH or FTP storage | remote path (/home/toto/backup) |
| FTP_HOST | Optional, required for FTP storage | FTP host name | | FTP_HOST | Optional, required for FTP storage | FTP host name |
| FTP_PORT | Optional, required for FTP storage | FTP server port number | | FTP_PORT | Optional, required for FTP storage | FTP server port number |
| FTP_USER | Optional, required for FTP storage | FTP user | | FTP_USER | Optional, required for FTP storage | FTP user |
| FTP_PASSWORD | Optional, required for FTP storage | FTP user password | | FTP_PASSWORD | Optional, required for FTP storage | FTP user password |
| TARGET_DB_HOST | Optional, required for database migration | Target database host | | TARGET_DB_HOST | Optional, required for database migration | Target database host |
| TARGET_DB_PORT | Optional, required for database migration | Target database port | | TARGET_DB_PORT | Optional, required for database migration | Target database port |
| TARGET_DB_NAME | Optional, required for database migration | Target database name | | TARGET_DB_NAME | Optional, required for database migration | Target database name |
| TARGET_DB_USERNAME | Optional, required for database migration | Target database username | | TARGET_DB_USERNAME | Optional, required for database migration | Target database username |
| TARGET_DB_PASSWORD | Optional, required for database migration | Target database password | | TARGET_DB_PASSWORD | Optional, required for database migration | Target database password |
| TG_TOKEN | Optional, required for Telegram notification | Telegram token (`BOT-ID:BOT-TOKEN`) | | TG_TOKEN | Optional, required for Telegram notification | Telegram token (`BOT-ID:BOT-TOKEN`) |
| TG_CHAT_ID | Optional, required for Telegram notification | Telegram Chat ID | | TG_CHAT_ID | Optional, required for Telegram notification | Telegram Chat ID |
| TZ | Optional | Time Zone | | TZ | Optional | Time Zone |
| AZURE_STORAGE_CONTAINER_NAME | Optional, required for Azure Blob Storage storage | Azure storage container name |
| AZURE_STORAGE_ACCOUNT_NAME | Optional, required for Azure Blob Storage storage | Azure storage account name |
| AZURE_STORAGE_ACCOUNT_KEY | Optional, required for Azure Blob Storage storage | Azure storage account key |
--- ---
## Run in Scheduled mode ## Run in Scheduled mode

View File

@@ -35,7 +35,7 @@ import (
) )
func azureBackup(db *dbConfig, config *BackupConfig) { func azureBackup(db *dbConfig, config *BackupConfig) {
utils.Info("Backup database to the remote FTP server") utils.Info("Backup database to Azure Blob Storage")
startTime = time.Now().Format(utils.TimeFormat()) startTime = time.Now().Format(utils.TimeFormat())
// Backup database // Backup database
@@ -83,12 +83,14 @@ func azureBackup(db *dbConfig, config *BackupConfig) {
} }
utils.Info("Backup name is %s", finalFileName)
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
utils.Info("Uploading backup archive to Azure Blob storage ... done ") utils.Info("Uploading backup archive to Azure Blob storage ... done ")
// Send notification // Send notification
utils.NotifySuccess(&utils.NotificationData{ utils.NotifySuccess(&utils.NotificationData{
File: finalFileName, File: finalFileName,
BackupSize: backupSize, BackupSize: utils.ConvertBytes(uint64(backupSize)),
Database: db.dbName, Database: db.dbName,
Storage: config.storage, Storage: config.storage,
BackupLocation: filepath.Join(config.remotePath, finalFileName), BackupLocation: filepath.Join(config.remotePath, finalFileName),

View File

@@ -268,7 +268,6 @@ func localBackup(db *dbConfig, config *BackupConfig) {
utils.Error("Error: %s", err) utils.Error("Error: %s", err)
} }
backupSize = fileInfo.Size() backupSize = fileInfo.Size()
utils.Info("Backup name is %s", finalFileName)
localStorage := local.NewStorage(local.Config{ localStorage := local.NewStorage(local.Config{
LocalPath: tmpPath, LocalPath: tmpPath,
RemotePath: storagePath, RemotePath: storagePath,
@@ -277,11 +276,13 @@ func localBackup(db *dbConfig, config *BackupConfig) {
if err != nil { if err != nil {
utils.Fatal("Error copying backup file: %s", err) utils.Fatal("Error copying backup file: %s", err)
} }
utils.Info("Backup name is %s", finalFileName)
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
utils.Info("Backup saved in %s", filepath.Join(storagePath, finalFileName)) utils.Info("Backup saved in %s", filepath.Join(storagePath, finalFileName))
// Send notification // Send notification
utils.NotifySuccess(&utils.NotificationData{ utils.NotifySuccess(&utils.NotificationData{
File: finalFileName, File: finalFileName,
BackupSize: backupSize, BackupSize: utils.ConvertBytes(uint64(backupSize)),
Database: db.dbName, Database: db.dbName,
Storage: config.storage, Storage: config.storage,
BackupLocation: filepath.Join(storagePath, finalFileName), BackupLocation: filepath.Join(storagePath, finalFileName),

View File

@@ -46,7 +46,6 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
finalFileName = fmt.Sprintf("%s.%s", config.backupFileName, "gpg") finalFileName = fmt.Sprintf("%s.%s", config.backupFileName, "gpg")
} }
utils.Info("Uploading backup archive to remote storage ... ") utils.Info("Uploading backup archive to remote storage ... ")
utils.Info("Backup name is %s", finalFileName)
sshConfig, err := loadSSHConfig() sshConfig, err := loadSSHConfig()
if err != nil { if err != nil {
utils.Fatal("Error loading ssh config: %s", err) utils.Fatal("Error loading ssh config: %s", err)
@@ -74,6 +73,8 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
utils.Error("Error: %s", err) utils.Error("Error: %s", err)
} }
backupSize = fileInfo.Size() backupSize = fileInfo.Size()
utils.Info("Backup name is %s", finalFileName)
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
utils.Info("Backup saved in %s", filepath.Join(config.remotePath, finalFileName)) utils.Info("Backup saved in %s", filepath.Join(config.remotePath, finalFileName))
// Delete backup file from tmp folder // Delete backup file from tmp folder
@@ -93,7 +94,7 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
// Send notification // Send notification
utils.NotifySuccess(&utils.NotificationData{ utils.NotifySuccess(&utils.NotificationData{
File: finalFileName, File: finalFileName,
BackupSize: backupSize, BackupSize: utils.ConvertBytes(uint64(backupSize)),
Database: db.dbName, Database: db.dbName,
Storage: config.storage, Storage: config.storage,
BackupLocation: filepath.Join(config.remotePath, finalFileName), BackupLocation: filepath.Join(config.remotePath, finalFileName),
@@ -199,13 +200,14 @@ func ftpBackup(db *dbConfig, config *BackupConfig) {
} }
} }
utils.Info("Backup name is %s", finalFileName)
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
utils.Info("Uploading backup archive to the remote FTP server ... done ") utils.Info("Uploading backup archive to the remote FTP server ... done ")
// Send notification // Send notification
utils.NotifySuccess(&utils.NotificationData{ utils.NotifySuccess(&utils.NotificationData{
File: finalFileName, File: finalFileName,
BackupSize: backupSize, BackupSize: utils.ConvertBytes(uint64(backupSize)),
Database: db.dbName, Database: db.dbName,
Storage: config.storage, Storage: config.storage,
BackupLocation: filepath.Join(config.remotePath, finalFileName), BackupLocation: filepath.Join(config.remotePath, finalFileName),

View File

@@ -94,7 +94,7 @@ func s3Backup(db *dbConfig, config *BackupConfig) {
// Send notification // Send notification
utils.NotifySuccess(&utils.NotificationData{ utils.NotifySuccess(&utils.NotificationData{
File: finalFileName, File: finalFileName,
BackupSize: backupSize, BackupSize: utils.ConvertBytes(uint64(backupSize)),
Database: db.dbName, Database: db.dbName,
Storage: config.storage, Storage: config.storage,
BackupLocation: filepath.Join(config.remotePath, finalFileName), BackupLocation: filepath.Join(config.remotePath, finalFileName),

View File

@@ -45,14 +45,12 @@ var (
// dbHVars Required environment variables for database // dbHVars Required environment variables for database
var dbHVars = []string{ var dbHVars = []string{
"DB_HOST", "DB_HOST",
"DB_PORT",
"DB_PASSWORD", "DB_PASSWORD",
"DB_USERNAME", "DB_USERNAME",
"DB_NAME", "DB_NAME",
} }
var tdbRVars = []string{ var tdbRVars = []string{
"TARGET_DB_HOST", "TARGET_DB_HOST",
"TARGET_DB_PORT",
"TARGET_DB_NAME", "TARGET_DB_NAME",
"TARGET_DB_USERNAME", "TARGET_DB_USERNAME",
"TARGET_DB_PASSWORD", "TARGET_DB_PASSWORD",

View File

@@ -45,16 +45,16 @@
</head> </head>
<body> <body>
<h2>🔴 Urgent: Database Backup Failure Notification</h2> <h2>🔴 Urgent: Database Backup Failure Notification</h2>
<p>Dear Team,</p> <p>Hi,</p>
<p>An error occurred during the database backup process. Please review the details below and take the necessary actions:</p> <p>An error occurred during the database backup process. Please review the details below and take the necessary actions:</p>
<div class="details"> <div class="details">
<h3>Failure Details:</h3> <h3>Failure Details:</h3>
<ul> <ul>
<li><strong>Database Name:</strong> {{.DatabaseName}}</li> <li><strong>Database Name:</strong> {{.DatabaseName}}</li>
<li><strong>Error Message:</strong> {{.Error}}</li>
<li><strong>Date:</strong> {{.EndTime}}</li> <li><strong>Date:</strong> {{.EndTime}}</li>
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li> <li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
<li><strong>Error Message:</strong> {{.Error}}</li>
</ul> </ul>
</div> </div>

View File

@@ -45,7 +45,7 @@
</head> </head>
<body> <body>
<h2>✅ Database Backup Successful</h2> <h2>✅ Database Backup Successful</h2>
<p>Dear Team,</p> <p>Hi,</p>
<p>The backup process for the <strong>{{.Database}}</strong> database was successfully completed. Please find the details below:</p> <p>The backup process for the <strong>{{.Database}}</strong> database was successfully completed. Please find the details below:</p>
<div class="details"> <div class="details">
@@ -56,7 +56,7 @@
<li><strong>Backup End Time:</strong> {{.EndTime}}</li> <li><strong>Backup End Time:</strong> {{.EndTime}}</li>
<li><strong>Backup Storage:</strong> {{.Storage}}</li> <li><strong>Backup Storage:</strong> {{.Storage}}</li>
<li><strong>Backup Location:</strong> {{.BackupLocation}}</li> <li><strong>Backup Location:</strong> {{.BackupLocation}}</li>
<li><strong>Backup Size:</strong> {{.BackupSize}} bytes</li> <li><strong>Backup Size:</strong> {{.BackupSize}}</li>
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li> <li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
</ul> </ul>
</div> </div>

View File

@@ -1,6 +1,6 @@
🔴 Urgent: Database Backup Failure Notification 🔴 Urgent: Database Backup Failure Notification
Dear Team, Hi,
An error occurred during the database backup process. An error occurred during the database backup process.
Please review the details below and take the necessary actions: Please review the details below and take the necessary actions:
Failure Details: Failure Details:

View File

@@ -1,6 +1,6 @@
✅ Database Backup Successful ✅ Database Backup Successful
Dear Team, Hi,
The backup process for the {{.Database}} database was successfully completed. The backup process for the {{.Database}} database was successfully completed.
Please find the details below: Please find the details below:
@@ -10,7 +10,7 @@ Backup Details:
- Backup EndTime: {{.EndTime}} - Backup EndTime: {{.EndTime}}
- Backup Storage: {{.Storage}} - Backup Storage: {{.Storage}}
- Backup Location: {{.BackupLocation}} - Backup Location: {{.BackupLocation}}
- Backup Size: {{.BackupSize}} bytes - Backup Size: {{.BackupSize}}
- Backup Reference: {{.BackupReference}} - Backup Reference: {{.BackupReference}}
You can access the backup at the specified location if needed. You can access the backup at the specified location if needed.

View File

@@ -37,7 +37,7 @@ type MailConfig struct {
} }
type NotificationData struct { type NotificationData struct {
File string File string
BackupSize int64 BackupSize string
Database string Database string
StartTime string StartTime string
EndTime string EndTime string

View File

@@ -254,3 +254,19 @@ func CronNextTime(cronExpr string) time.Time {
next := schedule.Next(now) next := schedule.Next(now)
return next return next
} }
// ConvertBytes converts bytes to a human-readable string with the appropriate unit (bytes, MiB, or GiB).
func ConvertBytes(bytes uint64) string {
const (
MiB = 1024 * 1024
GiB = MiB * 1024
)
switch {
case bytes >= GiB:
return fmt.Sprintf("%.2f GiB", float64(bytes)/float64(GiB))
case bytes >= MiB:
return fmt.Sprintf("%.2f MiB", float64(bytes)/float64(MiB))
default:
return fmt.Sprintf("%d bytes", bytes)
}
}