feat: Add Telegram notification
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
// Package cmd /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package cmd /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package cmd /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
10
cmd/root.go
10
cmd/root.go
@@ -1,7 +1,9 @@
|
|||||||
// Package cmd /*
|
// Package cmd /
|
||||||
/*
|
/*****
|
||||||
Copyright © 2024 Jonas Kaninda
|
@author Jonas Kaninda
|
||||||
*/
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
// Package cmd /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright © 2024 Jonas Kaninda
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ ENV TARGET_DB_NAME=""
|
|||||||
ENV TARGET_DB_USERNAME=""
|
ENV TARGET_DB_USERNAME=""
|
||||||
ENV TARGET_DB_PASSWORD=""
|
ENV TARGET_DB_PASSWORD=""
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ENV VERSION="v1.2.4"
|
ENV VERSION="v1.2.5"
|
||||||
ENV BACKUP_CRON_EXPRESSION=""
|
ENV BACKUP_CRON_EXPRESSION=""
|
||||||
ARG WORKDIR="/config"
|
ARG WORKDIR="/config"
|
||||||
ARG BACKUPDIR="/backup"
|
ARG BACKUPDIR="/backup"
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ Backup, restore and migrate targets, schedule and retention are configured using
|
|||||||
| 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 |
|
||||||
|
| TG_CHAT_ID | Optional, required for Telegram notification | Telegram Chat ID |
|
||||||
|
|
||||||
---
|
---
|
||||||
## Run in Scheduled mode
|
## Run in Scheduled mode
|
||||||
|
|||||||
13
main.go
13
main.go
@@ -1,12 +1,11 @@
|
|||||||
|
// Package main /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
//main
|
|
||||||
/*****
|
|
||||||
* MySQL Backup & Restore
|
|
||||||
* @author Jonas Kaninda
|
|
||||||
* @license MIT License <https://opensource.org/licenses/MIT>
|
|
||||||
* @link https://github.com/jkaninda/pg-bkup
|
|
||||||
**/
|
|
||||||
import "github.com/jkaninda/pg-bkup/cmd"
|
import "github.com/jkaninda/pg-bkup/cmd"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
// Package pkg /*
|
// Package pkg /
|
||||||
/*
|
/*****
|
||||||
Copyright © 2024 Jonas Kaninda
|
@author Jonas Kaninda
|
||||||
*/
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -17,6 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartBackup(cmd *cobra.Command) {
|
func StartBackup(cmd *cobra.Command) {
|
||||||
|
utils.Welcome()
|
||||||
//Set env
|
//Set env
|
||||||
utils.SetEnv("STORAGE_PATH", storagePath)
|
utils.SetEnv("STORAGE_PATH", storagePath)
|
||||||
utils.GetEnv(cmd, "period", "BACKUP_CRON_EXPRESSION")
|
utils.GetEnv(cmd, "period", "BACKUP_CRON_EXPRESSION")
|
||||||
@@ -198,6 +201,8 @@ func localBackup(db *dbConfig, backupFileName string, disableCompression bool, p
|
|||||||
}
|
}
|
||||||
utils.Info("Backup name is %s", finalFileName)
|
utils.Info("Backup name is %s", finalFileName)
|
||||||
moveToBackup(finalFileName, storagePath)
|
moveToBackup(finalFileName, storagePath)
|
||||||
|
//Send notification
|
||||||
|
utils.NotifySuccess(finalFileName)
|
||||||
//Delete old backup
|
//Delete old backup
|
||||||
if prune {
|
if prune {
|
||||||
deleteOldBackup(backupRetention)
|
deleteOldBackup(backupRetention)
|
||||||
@@ -240,6 +245,8 @@ func s3Backup(db *dbConfig, backupFileName string, disableCompression bool, prun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils.Done("Uploading backup archive to remote storage S3 ... done ")
|
utils.Done("Uploading backup archive to remote storage S3 ... done ")
|
||||||
|
//Send notification
|
||||||
|
utils.NotifySuccess(finalFileName)
|
||||||
//Delete temp
|
//Delete temp
|
||||||
deleteTemp()
|
deleteTemp()
|
||||||
}
|
}
|
||||||
@@ -273,6 +280,8 @@ func sshBackup(db *dbConfig, backupFileName, remotePath string, disableCompressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils.Done("Uploading backup archive to remote storage ... done ")
|
utils.Done("Uploading backup archive to remote storage ... done ")
|
||||||
|
//Send notification
|
||||||
|
utils.NotifySuccess(finalFileName)
|
||||||
//Delete temp
|
//Delete temp
|
||||||
deleteTemp()
|
deleteTemp()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -23,6 +29,10 @@ type targetDbConfig struct {
|
|||||||
targetDbPassword string
|
targetDbPassword string
|
||||||
targetDbName string
|
targetDbName string
|
||||||
}
|
}
|
||||||
|
type TgConfig struct {
|
||||||
|
Token string
|
||||||
|
ChatId string
|
||||||
|
}
|
||||||
|
|
||||||
func getDbConfig(cmd *cobra.Command) *dbConfig {
|
func getDbConfig(cmd *cobra.Command) *dbConfig {
|
||||||
//Set env
|
//Set env
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -125,7 +131,7 @@ func testDatabaseConnection(db *dbConfig) {
|
|||||||
// Run the command and capture any errors
|
// Run the command and capture any errors
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Error("Error running psql command: %v\nOutput: %s\n", err, out.String())
|
utils.Fatal("Error running psql command: %v\nOutput: %s\n", err, out.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
utils.Info("Successfully connected to %s database", db.dbName)
|
utils.Info("Successfully connected to %s database", db.dbName)
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,6 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartMigration(cmd *cobra.Command) {
|
func StartMigration(cmd *cobra.Command) {
|
||||||
|
utils.Welcome()
|
||||||
utils.Info("Starting database migration...")
|
utils.Info("Starting database migration...")
|
||||||
//Get DB config
|
//Get DB config
|
||||||
dbConf = getDbConfig(cmd)
|
dbConf = getDbConfig(cmd)
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartRestore(cmd *cobra.Command) {
|
func StartRestore(cmd *cobra.Command) {
|
||||||
|
utils.Welcome()
|
||||||
//Set env
|
//Set env
|
||||||
utils.SetEnv("STORAGE_PATH", storagePath)
|
utils.SetEnv("STORAGE_PATH", storagePath)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
// Package pkg /*
|
// Package pkg /
|
||||||
/*
|
/*****
|
||||||
Copyright © 2024 Jonas Kaninda
|
@author Jonas Kaninda
|
||||||
*/
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jkaninda/pg-bkup/utils"
|
"github.com/jkaninda/pg-bkup/utils"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package pkg /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
const cronLogFile = "/var/log/pg-bkup.log"
|
const cronLogFile = "/var/log/pg-bkup.log"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package utils /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
const RestoreExample = "pg-bkup restore --dbname database --file db_20231219_022941.sql.gz\n" +
|
const RestoreExample = "pg-bkup restore --dbname database --file db_20231219_022941.sql.gz\n" +
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package utils /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -51,9 +57,13 @@ func Fatal(msg string, args ...any) {
|
|||||||
formattedMessage := fmt.Sprintf(msg, args...)
|
formattedMessage := fmt.Sprintf(msg, args...)
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
fmt.Printf("%s ERROR: %s\n", currentTime, msg)
|
fmt.Printf("%s ERROR: %s\n", currentTime, msg)
|
||||||
|
NotifyError(msg)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s ERROR: %s\n", currentTime, formattedMessage)
|
fmt.Printf("%s ERROR: %s\n", currentTime, formattedMessage)
|
||||||
|
NotifyError(formattedMessage)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
os.Kill.Signal()
|
os.Kill.Signal()
|
||||||
}
|
}
|
||||||
|
|||||||
75
utils/notification.go
Normal file
75
utils/notification.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sendMessage(msg string) {
|
||||||
|
|
||||||
|
Info("Sending notification... ")
|
||||||
|
chatId := os.Getenv("TG_CHAT_ID")
|
||||||
|
body, _ := json.Marshal(map[string]string{
|
||||||
|
"chat_id": chatId,
|
||||||
|
"text": msg,
|
||||||
|
})
|
||||||
|
url := fmt.Sprintf("%s/sendMessage", getTgUrl())
|
||||||
|
// Create an HTTP post request
|
||||||
|
request, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
request.Header.Add("Content-Type", "application/json")
|
||||||
|
client := &http.Client{}
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
code := response.StatusCode
|
||||||
|
if code == 200 {
|
||||||
|
Info("Notification has been sent")
|
||||||
|
} else {
|
||||||
|
body, _ := ioutil.ReadAll(response.Body)
|
||||||
|
Error("Message not sent, error: %s", string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func NotifySuccess(fileName string) {
|
||||||
|
var vars = []string{
|
||||||
|
"TG_TOKEN",
|
||||||
|
"TG_CHAT_ID",
|
||||||
|
}
|
||||||
|
|
||||||
|
//Telegram notification
|
||||||
|
err := CheckEnvVars(vars)
|
||||||
|
if err == nil {
|
||||||
|
message := "PostgreSQL Backup \n" +
|
||||||
|
"Database has been backed up \n" +
|
||||||
|
"Backup name is " + fileName
|
||||||
|
sendMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func NotifyError(error string) {
|
||||||
|
var vars = []string{
|
||||||
|
"TG_TOKEN",
|
||||||
|
"TG_CHAT_ID",
|
||||||
|
}
|
||||||
|
|
||||||
|
//Telegram notification
|
||||||
|
err := CheckEnvVars(vars)
|
||||||
|
if err == nil {
|
||||||
|
message := "PostgreSQL Backup \n" +
|
||||||
|
"An error occurred during database backup \n" +
|
||||||
|
"Error: " + error
|
||||||
|
sendMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTgUrl() string {
|
||||||
|
return fmt.Sprintf("https://api.telegram.org/bot%s", os.Getenv("TG_TOKEN"))
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Package utils /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
|
// Package utils /
|
||||||
|
/*****
|
||||||
|
@author Jonas Kaninda
|
||||||
|
@license MIT License <https://opensource.org/licenses/MIT>
|
||||||
|
@Copyright © 2024 Jonas Kaninda
|
||||||
|
**/
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
/*****
|
|
||||||
* PostgreSQL Backup & Restore
|
|
||||||
* @author Jonas Kaninda
|
|
||||||
* @license MIT License <https://opensource.org/licenses/MIT>
|
|
||||||
* @link https://github.com/jkaninda/pg-bkup
|
|
||||||
**/
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FileExists(filename string) bool {
|
func FileExists(filename string) bool {
|
||||||
@@ -149,6 +150,13 @@ func CheckEnvVars(vars []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func Welcome() {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("**********************************")
|
||||||
|
fmt.Println(" PostgreSQL Backup ")
|
||||||
|
fmt.Println(" @Copyright © 2024 jkaninda ")
|
||||||
|
fmt.Println("***********************************")
|
||||||
|
}
|
||||||
|
|
||||||
// MakeDir create directory
|
// MakeDir create directory
|
||||||
func MakeDir(dirPath string) error {
|
func MakeDir(dirPath string) error {
|
||||||
@@ -167,3 +175,14 @@ func MakeDirAll(dirPath string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func GetIntEnv(envName string) int {
|
||||||
|
val := os.Getenv(envName)
|
||||||
|
if val == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
ret, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
Error("Error: %v", err)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user