mirror of
https://github.com/jkaninda/mysql-bkup.git
synced 2025-12-06 21:49:40 +01:00
chore: fix infinity calling Fatal, add a backup reference
This commit is contained in:
@@ -4,10 +4,10 @@ layout: default
|
||||
parent: How Tos
|
||||
nav_order: 12
|
||||
---
|
||||
Send Email or Telegram notifications on success or failed backup.
|
||||
Send Email or Telegram notifications on successfully or failed backup.
|
||||
|
||||
### Email
|
||||
To send out email notifications on failed backup runs, provide SMTP credentials, a sender and a recipient:
|
||||
To send out email notifications on failed or successfully backup runs, provide SMTP credentials, a sender and a recipient:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -27,9 +27,13 @@ services:
|
||||
- MAIL_PORT=587
|
||||
- MAIL_USERNAME=
|
||||
- MAIL_PASSWORD=!
|
||||
- MAIL_FROM=sender@example.com
|
||||
- MAIL_FROM=
|
||||
- MAIL_TO=me@example.com,team@example.com,manager@example.com
|
||||
- MAIL_SKIP_TLS=false
|
||||
## Time format for notification
|
||||
- TIME_FORMAT=2006-01-02 at 15:04:05
|
||||
## Backup reference, in case you want to identifier every backup instance
|
||||
- BACKUP_REFERENCE=database/Paris cluster
|
||||
networks:
|
||||
- web
|
||||
networks:
|
||||
@@ -54,6 +58,10 @@ services:
|
||||
- DB_PASSWORD=password
|
||||
- TG_TOKEN=[BOT ID]:[BOT TOKEN]
|
||||
- TG_CHAT_ID=
|
||||
## Time format for notification
|
||||
- TIME_FORMAT=2006-01-02 at 15:04:05
|
||||
## Backup reference, in case you want to identifier every backup instance
|
||||
- BACKUP_REFERENCE=database/Paris cluster
|
||||
networks:
|
||||
- web
|
||||
networks:
|
||||
@@ -62,12 +70,13 @@ networks:
|
||||
|
||||
### Customize notifications
|
||||
|
||||
The body of the notifications can be tailored to your needs using Go templates.
|
||||
The title and body of the notifications can be tailored to your needs using Go templates.
|
||||
Template sources must be mounted inside the container in /config/templates:
|
||||
|
||||
- email.template: Email notification template
|
||||
- telegram.template: Telegram notification template
|
||||
- error.template: Error notification template
|
||||
- email-error.template: Error notification template
|
||||
- telegram-error.template: Error notification template
|
||||
|
||||
### Data
|
||||
|
||||
@@ -78,7 +87,7 @@ Here is a list of all data passed to the template:
|
||||
- `Storage`: Backup storage
|
||||
- `BackupLocation`: Backup location
|
||||
- `BackupSize`: Backup size
|
||||
|
||||
- `BackupReference`: Backup reference(eg: database/cluster name or server name)
|
||||
|
||||
> email.template:
|
||||
|
||||
@@ -88,19 +97,20 @@ Here is a list of all data passed to the template:
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>[✅ Database Backup Notification – {{.Database}}</title>
|
||||
<title>✅ Database Backup Notification – {{.Database}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hi,</h2>
|
||||
<p>Backup of the {{.Database}} database has been successfully completed on {{.EndTime}}.</p>
|
||||
<h3>Backup Details:</h3>
|
||||
<ul>
|
||||
<li>Database Name: {{.Database}}</li>
|
||||
<li>Backup Start Time: {{.StartTime}}</li>
|
||||
<li>Backup End Time: {{.EndTime}}</li>
|
||||
<li>Backup Storage: {{.Storage}}</li>
|
||||
<li>Backup Location: {{.BackupLocation}}</li>
|
||||
<li>Backup Size: {{.BackupSize}} bytes</li>
|
||||
<li>Database Name: {{.Database}}</li>
|
||||
<li>Backup Start Time: {{.StartTime}}</li>
|
||||
<li>Backup End Time: {{.EndTime}}</li>
|
||||
<li>Backup Storage: {{.Storage}}</li>
|
||||
<li>Backup Location: {{.BackupLocation}}</li>
|
||||
<li>Backup Size: {{.BackupSize}} bytes</li>
|
||||
<li>Backup Reference: {{.BackupReference}} </li>
|
||||
</ul>
|
||||
<p>Best regards,</p>
|
||||
</body>
|
||||
@@ -110,7 +120,7 @@ Here is a list of all data passed to the template:
|
||||
> telegram.template
|
||||
|
||||
```html
|
||||
[✅ Database Backup Notification – {{.Database}}
|
||||
✅ Database Backup Notification – {{.Database}}
|
||||
Hi,
|
||||
Backup of the {{.Database}} database has been successfully completed on {{.EndTime}}.
|
||||
|
||||
@@ -121,9 +131,32 @@ Backup Details:
|
||||
- Backup Storage: {{.Storage}}
|
||||
- Backup Location: {{.BackupLocation}}
|
||||
- Backup Size: {{.BackupSize}} bytes
|
||||
- Backup Reference: {{.BackupReference}}
|
||||
```
|
||||
|
||||
> error.template
|
||||
> email-error.template
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>🔴 Urgent: Database Backup Failure Notification</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Hi,</h2>
|
||||
<p>An error occurred during database backup.</p>
|
||||
<h3>Failure Details:</h3>
|
||||
<ul>
|
||||
<li>Error Message: {{.Error}}</li>
|
||||
<li>Date: {{.EndTime}}</li>
|
||||
<li>Backup Reference: {{.BackupReference}} </li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
> telegram-error.template
|
||||
|
||||
|
||||
```html
|
||||
|
||||
@@ -218,7 +218,7 @@ func BackupDatabase(db *dbConfig, backupFileName string, disableCompression bool
|
||||
}
|
||||
func localBackup(db *dbConfig, config *BackupConfig) {
|
||||
utils.Info("Backup database to local storage")
|
||||
startTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
startTime = time.Now().Format(utils.TimeFormat())
|
||||
BackupDatabase(db, config.backupFileName, disableCompression)
|
||||
finalFileName := config.backupFileName
|
||||
if config.encryption {
|
||||
@@ -241,7 +241,7 @@ func localBackup(db *dbConfig, config *BackupConfig) {
|
||||
Storage: config.storage,
|
||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||
StartTime: startTime,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
EndTime: time.Now().Format(utils.TimeFormat()),
|
||||
})
|
||||
//Delete old backup
|
||||
if config.prune {
|
||||
@@ -256,7 +256,7 @@ func s3Backup(db *dbConfig, config *BackupConfig) {
|
||||
bucket := utils.GetEnvVariable("AWS_S3_BUCKET_NAME", "BUCKET_NAME")
|
||||
s3Path := utils.GetEnvVariable("AWS_S3_PATH", "S3_PATH")
|
||||
utils.Info("Backup database to s3 storage")
|
||||
startTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
startTime = time.Now().Format(utils.TimeFormat())
|
||||
|
||||
//Backup database
|
||||
BackupDatabase(db, config.backupFileName, disableCompression)
|
||||
@@ -301,7 +301,7 @@ func s3Backup(db *dbConfig, config *BackupConfig) {
|
||||
Storage: config.storage,
|
||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||
StartTime: startTime,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
EndTime: time.Now().Format(utils.TimeFormat()),
|
||||
})
|
||||
//Delete temp
|
||||
deleteTemp()
|
||||
@@ -310,7 +310,7 @@ func s3Backup(db *dbConfig, config *BackupConfig) {
|
||||
}
|
||||
func sshBackup(db *dbConfig, config *BackupConfig) {
|
||||
utils.Info("Backup database to Remote server")
|
||||
startTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
startTime = time.Now().Format(utils.TimeFormat())
|
||||
|
||||
//Backup database
|
||||
BackupDatabase(db, config.backupFileName, disableCompression)
|
||||
@@ -353,7 +353,7 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
|
||||
Storage: config.storage,
|
||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||
StartTime: startTime,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
EndTime: time.Now().Format(utils.TimeFormat()),
|
||||
})
|
||||
//Delete temp
|
||||
deleteTemp()
|
||||
@@ -362,7 +362,7 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
|
||||
}
|
||||
func ftpBackup(db *dbConfig, config *BackupConfig) {
|
||||
utils.Info("Backup database to the remote FTP server")
|
||||
startTime = time.Now().Format("2006-01-02 15:04:05")
|
||||
startTime = time.Now().Format(utils.TimeFormat())
|
||||
|
||||
//Backup database
|
||||
BackupDatabase(db, config.backupFileName, disableCompression)
|
||||
@@ -405,7 +405,7 @@ func ftpBackup(db *dbConfig, config *BackupConfig) {
|
||||
Storage: config.storage,
|
||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||
StartTime: startTime,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
EndTime: time.Now().Format(utils.TimeFormat()),
|
||||
})
|
||||
//Delete temp
|
||||
deleteTemp()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<ul>
|
||||
<li>Error Message: {{.Error}}</li>
|
||||
<li>Date: {{.EndTime}}</li>
|
||||
<li>Backup Reference: {{.BackupReference}} </li>
|
||||
</ul>
|
||||
<p>©2024 <a href="github.com/jkaninda/mysql-bkup">mysql-bkup</a></p>
|
||||
</body>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<li>Backup Storage: {{.Storage}}</li>
|
||||
<li>Backup Location: {{.BackupLocation}}</li>
|
||||
<li>Backup Size: {{.BackupSize}} bytes</li>
|
||||
<li>Backup Reference: {{.BackupReference}} </li>
|
||||
</ul>
|
||||
<p>Best regards,</p>
|
||||
<p>©2024 <a href="github.com/jkaninda/mysql-bkup">mysql-bkup</a></p>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Hi,
|
||||
An error occurred during database backup.
|
||||
Failure Details:
|
||||
Date: {{.EndTime}}
|
||||
Error Message: {{.Error}}
|
||||
- Date: {{.EndTime}}
|
||||
- Backup Reference: {{.BackupReference}}
|
||||
- Error Message: {{.Error}}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
✅ Database Backup Notification – {{.Database}}
|
||||
[✅ Database Backup Notification – {{.Database}}
|
||||
Hi,
|
||||
Backup of the {{.Database}} database has been successfully completed on {{.EndTime}}.
|
||||
|
||||
@@ -8,4 +8,5 @@ Backup Details:
|
||||
- Backup EndTime: {{.EndTime}}
|
||||
- Backup Storage: {{.Storage}}
|
||||
- Backup Location: {{.BackupLocation}}
|
||||
- Backup Size: {{.BackupSize}} bytes
|
||||
- Backup Size: {{.BackupSize}} bytes
|
||||
- Backup Reference: {{.BackupReference}}
|
||||
|
||||
@@ -12,20 +12,23 @@ type MailConfig struct {
|
||||
SkipTls bool
|
||||
}
|
||||
type NotificationData struct {
|
||||
File string
|
||||
BackupSize int64
|
||||
Database string
|
||||
StartTime string
|
||||
EndTime string
|
||||
Storage string
|
||||
BackupLocation string
|
||||
File string
|
||||
BackupSize int64
|
||||
Database string
|
||||
StartTime string
|
||||
EndTime string
|
||||
Storage string
|
||||
BackupLocation string
|
||||
BackupReference string
|
||||
}
|
||||
type ErrorMessage struct {
|
||||
Database string
|
||||
EndTime string
|
||||
Error string
|
||||
Database string
|
||||
EndTime string
|
||||
Error string
|
||||
BackupReference string
|
||||
}
|
||||
|
||||
// loadMailConfig gets mail environment variables and returns MailConfig
|
||||
func loadMailConfig() *MailConfig {
|
||||
return &MailConfig{
|
||||
MailHost: os.Getenv("MAIL_HOST"),
|
||||
@@ -39,4 +42,18 @@ func loadMailConfig() *MailConfig {
|
||||
|
||||
}
|
||||
|
||||
// TimeFormat returns the format of the time
|
||||
func TimeFormat() string {
|
||||
format := os.Getenv("TIME_FORMAT")
|
||||
if format == "" {
|
||||
return "2006-01-02 at 15:04:05"
|
||||
|
||||
}
|
||||
return format
|
||||
}
|
||||
|
||||
func backupReference() string {
|
||||
return os.Getenv("BACKUP_REFERENCE")
|
||||
}
|
||||
|
||||
const templatePath = "/config/templates"
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
**/
|
||||
package utils
|
||||
|
||||
const RestoreExample = "mysql-bkup restore --dbname database --file db_20231219_022941.sql.gz\n" +
|
||||
const RestoreExample = "restore --dbname database --file db_20231219_022941.sql.gz\n" +
|
||||
"restore --dbname database --storage s3 --path /custom-path --file db_20231219_022941.sql.gz"
|
||||
const BackupExample = "mysql-bkup backup --dbname database --disable-compression\n" +
|
||||
const BackupExample = "backup --dbname database --disable-compression\n" +
|
||||
"backup --dbname database --storage s3 --path /custom-path --disable-compression"
|
||||
|
||||
const MainExample = "mysql-bkup backup --dbname database --disable-compression\n" +
|
||||
|
||||
@@ -31,8 +31,8 @@ func parseTemplate[T any](data T, fileName string) (string, error) {
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func SendEmail(subject, body string) {
|
||||
Info("Start sending email....")
|
||||
func SendEmail(subject, body string) error {
|
||||
Info("Start sending email notification....")
|
||||
config := loadMailConfig()
|
||||
emails := strings.Split(config.MailTo, ",")
|
||||
m := mail.NewMessage()
|
||||
@@ -44,14 +44,16 @@ func SendEmail(subject, body string) {
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: config.SkipTls}
|
||||
|
||||
if err := d.DialAndSend(m); err != nil {
|
||||
Fatal("Error could not send email : %v", err)
|
||||
Error("Error could not send email : %v", err)
|
||||
return err
|
||||
}
|
||||
Info("Email has been sent")
|
||||
Info("Email notification has been sent")
|
||||
return nil
|
||||
|
||||
}
|
||||
func sendMessage(msg string) {
|
||||
func sendMessage(msg string) error {
|
||||
|
||||
Info("Sending notification... ")
|
||||
Info("Sending Telegram notification... ")
|
||||
chatId := os.Getenv("TG_CHAT_ID")
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"chat_id": chatId,
|
||||
@@ -67,18 +69,21 @@ func sendMessage(msg string) {
|
||||
client := &http.Client{}
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
code := response.StatusCode
|
||||
if code == 200 {
|
||||
Info("Notification has been sent")
|
||||
Info("Telegram notification has been sent")
|
||||
return nil
|
||||
} else {
|
||||
body, _ := ioutil.ReadAll(response.Body)
|
||||
Fatal("Error could not send message, error: %s", string(body))
|
||||
Error("Error could not send message, error: %s", string(body))
|
||||
return fmt.Errorf("error could not send message %s", string(body))
|
||||
}
|
||||
|
||||
}
|
||||
func NotifySuccess(notificationData *NotificationData) {
|
||||
notificationData.BackupReference = backupReference()
|
||||
var vars = []string{
|
||||
"TG_TOKEN",
|
||||
"TG_CHAT_ID",
|
||||
@@ -99,17 +104,23 @@ func NotifySuccess(notificationData *NotificationData) {
|
||||
if err != nil {
|
||||
Error("Could not parse email template: %v", err)
|
||||
}
|
||||
SendEmail(fmt.Sprintf("✅ Database Backup Notification – %s", notificationData.Database), body)
|
||||
err = SendEmail(fmt.Sprintf("✅ Database Backup Notification – %s", notificationData.Database), body)
|
||||
if err != nil {
|
||||
Error("Could not send email: %v", err)
|
||||
}
|
||||
}
|
||||
//Telegram notification
|
||||
err = CheckEnvVars(vars)
|
||||
if err == nil {
|
||||
message, err := parseTemplate(*notificationData, "telegram.template")
|
||||
if err != nil {
|
||||
Error("Could not parse email template: %v", err)
|
||||
Error("Could not parse telegram template: %v", err)
|
||||
}
|
||||
|
||||
sendMessage(message)
|
||||
err = sendMessage(message)
|
||||
if err != nil {
|
||||
Error("Could not send Telegram message: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func NotifyError(error string) {
|
||||
@@ -130,26 +141,35 @@ func NotifyError(error string) {
|
||||
err := CheckEnvVars(mailVars)
|
||||
if err == nil {
|
||||
body, err := parseTemplate(ErrorMessage{
|
||||
Error: error,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
Error: error,
|
||||
EndTime: time.Now().Format(TimeFormat()),
|
||||
BackupReference: os.Getenv("BACKUP_REFERENCE"),
|
||||
}, "email-error.template")
|
||||
if err != nil {
|
||||
Error("Could not parse email template: %v", err)
|
||||
Error("Could not parse error template: %v", err)
|
||||
}
|
||||
err = SendEmail(fmt.Sprintf("🔴 Urgent: Database Backup Failure Notification"), body)
|
||||
if err != nil {
|
||||
Error("Could not send email: %v", err)
|
||||
}
|
||||
SendEmail(fmt.Sprintf("🔴 Urgent: Database Backup Failure Notification"), body)
|
||||
}
|
||||
//Telegram notification
|
||||
err = CheckEnvVars(vars)
|
||||
if err == nil {
|
||||
message, err := parseTemplate(ErrorMessage{
|
||||
Error: error,
|
||||
EndTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
Error: error,
|
||||
EndTime: time.Now().Format(TimeFormat()),
|
||||
BackupReference: os.Getenv("BACKUP_REFERENCE"),
|
||||
}, "telegram-error.template")
|
||||
if err != nil {
|
||||
Error("Could not parse email template: %v", err)
|
||||
Error("Could not parse error template: %v", err)
|
||||
|
||||
}
|
||||
|
||||
sendMessage(message)
|
||||
err = sendMessage(message)
|
||||
if err != nil {
|
||||
Error("Could not send telegram message: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user