Skip to content

Commit

Permalink
Use monodb-database-tools utils to create a dump
Browse files Browse the repository at this point in the history
  • Loading branch information
Romitou committed May 22, 2022
1 parent 612343a commit 12b2495
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 66 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# MongoBackup 🍃
Fast and efficient tool to backup Mongo databases using a Discord webhook.
<br>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.

<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Go_Logo_Aqua.svg/1200px-Go_Logo_Aqua.svg.png" height=40 width=auto>

## 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
Expand Down
89 changes: 26 additions & 63 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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")
Expand All @@ -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)
}
}

Expand All @@ -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) {
Expand Down

0 comments on commit 12b2495

Please sign in to comment.