diff --git a/README.md b/README.md index f958e46..82fa7b5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ # MongoBackup 🍃 Fast and efficient tool to backup Mongo databases using a Discord webhook. +
Important: you need `mongodb-database-tools` installed. -## It's fast ⚡ -Totally written in Go, you benefit from all the advantages of this languages, which is optimized for performance. This application also uses the super-fast official Mongo driver. +### It's fast ⚡ +Totally written in Go, you benefit from all the advantages of these languages, optimized for performance. This program also uses the official Mongo drivers. -## It's simple 🤓 +### It's simple 🤓 All you have to do is download the application binaries, fill in a configuration file and create a cron job. Simple, isn't it? ``` curl -L https://github.com/Romitou/MongoBackup/releases/latest/download/mongobackup-linux -o mongobackup diff --git a/main.go b/main.go index 72a0d44..10c04c7 100644 --- a/main.go +++ b/main.go @@ -2,23 +2,19 @@ package main import ( "context" - "encoding/json" "flag" + "fmt" "github.com/alexmullins/zip" "github.com/andersfylling/snowflake" "github.com/nickname32/discordhook" "github.com/spf13/viper" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" "io" "log" "os" - "strings" + "os/exec" "time" ) -var backupData string var backupName = time.Now().Format("2006-01-02T150405") func main() { @@ -44,39 +40,8 @@ func main() { log.SetFlags(log.Ltime) log.SetOutput(io.MultiWriter(file, os.Stdout)) - // prepare mongo context - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() + runMongoDump() - // create a mongo client - mongoUri := viper.GetString("mongoUri") - client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoUri)) - if err != nil { - log.Fatal("an error occurred while creating the mongo client: ", err) - } - - databaseNames, err := client.ListDatabaseNames(ctx, bson.D{}, options.ListDatabases()) - if err != nil { - log.Fatal("an error occurred while reading databases names: ", err) - } - - for _, databaseName := range databaseNames { - database := client.Database(databaseName) - collectionNames, err := database.ListCollectionNames(ctx, bson.D{}, options.ListCollections()) - if err != nil { - log.Fatal("an error occurred while reading collection names of "+databaseName+" database: ", err) - } - backupData += "// database " + databaseName + "\n" - for _, collectionName := range collectionNames { - collection := database.Collection(collectionName) - cursor, err := collection.Find(ctx, bson.D{}, options.Find()) - if err != nil { - log.Fatal("an error occurred while reading documents of "+collectionName+" collection: ", err) - } - backupData += "// collection " + collectionName + "\n" - backupCollection(cursor, ctx) - } - } webhookID := viper.GetString("webhook.id") webhookToken := viper.GetString("webhook.token") zipPassword := viper.GetString("zipPassword") @@ -85,27 +50,10 @@ func main() { sendToDiscord(webhookID, webhookToken) } -func backupCollection(cursor *mongo.Cursor, ctx context.Context) { - defer func(cursor *mongo.Cursor, ctx context.Context) { - err := cursor.Close(ctx) - if err != nil { - log.Fatal("an error occurred while closing mongo cursor: ", err) - } - }(cursor, ctx) - for cursor.Next(ctx) { - var document bson.M - err := cursor.Decode(&document) - if err != nil { - log.Fatal("an error occurred while decoding a mongo document: ", err) - } - marshal, err := json.Marshal(document) - if err != nil { - return - } - backupData += string(marshal) + "\n" - } - if err := cursor.Err(); err != nil { - log.Fatal("an error occurred with the mongo cursor: ", err) +func runMongoDump() { + subProcess := exec.Command("mongodump", "--uri=\""+viper.GetString("mongoUri")+"\"", "--archive=dump."+backupName+".archive") + if err := subProcess.Run(); err != nil { + fmt.Println("An error occured: ", err) } } @@ -114,19 +62,34 @@ func createZipFile(zipPassword string) { if err != nil { log.Fatal("an error occurred while creating the archive: ", err) } - defer archive.Close() + defer func(archive *os.File) { + err = archive.Close() + if err != nil { + log.Println(err) + } + }(archive) zipWriter := zip.NewWriter(archive) - writer, err := zipWriter.Encrypt(backupName+".json", zipPassword) + writer, err := zipWriter.Encrypt("backups/dump."+backupName+".archive", zipPassword) if err != nil { log.Fatal("an error occurred while creating the archive: ", err) } - _, err = io.Copy(writer, strings.NewReader(backupData)) + file, err := os.Open("backups/dump." + backupName + ".archive") + if err != nil { + return + } + + _, err = io.Copy(writer, file) if err != nil { log.Fatal("an error occurred while creating the archive: ", err) } - defer zipWriter.Close() + defer func(zipWriter *zip.Writer) { + err = zipWriter.Close() + if err != nil { + log.Println(err) + } + }(zipWriter) } func sendToDiscord(webhookID string, webhookToken string) {