migrator

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2021 License: MIT Imports: 7 Imported by: 0

README

mongo-migrator

Mongo migrator is a library that provides migration management operations.

Contents

  1. Installation
  2. Usage
    1. Migrations package
    2. Global slice variable example
    3. Migrations functions example
  3. Commands
    1. Initialization (init)
    2. Applying (up)
    3. Roll back (down)
    4. Reset (reset)
    5. Current version (version)
    6. Version changing (set_version)
  4. Direct commands calls
  5. License

Installation

go get -v github.com/Devoter/mongo-migrator

Usage

The following instructions are only recommendations, of course, you can use the library as like as you wish.

Migrations package

To use the library you should create migrations functions. It is intuitive to declare migrations package in your project. All your migrations should be placed in one slice of type []migration.Migration.

Global slice variable example

There is a simple way to declare the migrations slice:

// migrations/migrations.go
package migrations

import "github.com/Devoter/mongo-migrator/migration"

// Migrations is a list of all available migrations.
var Migrations = []migration.Migration{}
Migrations functions example

It is recommended to put all migrations functions in separate files named like <number>.<name>.go. Each migration file should contain init function that appends current migration to the global migrations slice. Every migration must have two functions: up and down that applies or rolls back the migration respectively.

// migrations/1.init.go
package migrations

import (
	"context"

	"go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migration"
)

func init() {

	Migrations = append(Migrations, migration.Migration{
		Version: 1,
		Name:    "init",
		Up:      migration.DummyUpDown, // built-in dummy migration function
		Down:    Down1,
	})
}

// Down1 applies `down` migration.
func Down1(db *mongo.Database) (err error) {
	majOpts := migration.MajorityOpts()

	collections := []string{"groups", "rules", "templates", "users"}

	for _, collection := range collections {
		if err = db.Collection(collection, majOpts).Drop(context.TODO()); err != nil {
			return
		}
	}

	return
}

As you can see up and down functions use an official MongoDB Go driver. It is a good practice to create idempotent migrations.

Commands

The migrator supports six commands: init, up, down, reset, version, and set_version.

Initialization (init)

The current migration version must be saved in the database migrations collection. You don't have to create it manually, just call the init command of the migrator:

package usage_example

import (
    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// InitializeMigrations initializes the database migrations collection.
func InitializeMigrations(client *mongo.Client, dbName string, migrations []migration.Migration) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Creating the `migrations` collection and initialing it with the zero database structure version.
    if _, _, err := migrator.Run(dbName, "init"); err != nil {
        panic(err)
    }
}
Applying (up)

It is so easy to apply all migrations:

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// UpAuto applies all unapplied migrations.
func UpAuto(client *mongo.Client, dbName string, migrations []migration.Migration) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Applying all unapplied migrations.
    old, current, err := migrator.Run(dbName, "up")
    if err != nil {
        panic(err)
    }

    // Printing old and current versions. If there are no unapplied migrations `old` and `current` are equal.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}

Certainly you may want to set the targe version of the database structure. It is pretty simple: just add an additional parameter with the target version.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// UpTo applyies all unapplied migrations to the target.
func UpTo(client *mongo.Client, dbName string, migrations []migration.Migration, target string) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Applying all unapplied migrations up to the target.
    old, current, err := migrator.Run(dbName, "up", target)
    if err != nil {
        panic(err)
    }

    // Printing old and current versions. If there are no unapplied migrations `old` and `current` are equal.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}
Roll back (down)

The down command removes the last migration (calls the migration down function). This command does not support any additional parameters. It is very similar to the up command.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// Down reverts the last applied migration.
func Down(client *mongo.Client, dbName string, migrations []migration.Migration) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Reverting the last applied migration.
    old, current, err := migrator.Run(dbName, "down")
    if err != nil {
        panic(err)
    }

    // Printing old and current versions. If there are no applied migrations `old` and `current` are equal.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}
Reset (reset)

This command reverts all applied migrations and sets the database structure version to zero.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// Reset reverts all applied migrations.
func Reset(client *mongo.Client, dbName string, migrations []migration.Migration) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Reverting all applied migrations.
    old, current, err := migrator.Run(dbName, "reset")
    if err != nil {
        panic(err)
    }

    // Printing old and current versions. If there are no applied migrations `old` and `current` are equal.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}
Current version (version)

This command returns the current database structure version.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// Version outputs the current database structure version.
func Version(client *mongo.Client, dbName string, migrations []migration.Migration) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Getting the current database structure version.
    _, current, err := migrator.Run(dbName, "version")
    if err != nil {
        panic(err)
    }

    // Printing the current version.
    fmt.Printf("Current version: %d\n", current)
}
Version changing (set_version)

The set_version command changes the current version without applying migrations.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

// SetVersion changes the current database structure version number to the target.
func SetVersion(client *mongo.Client, dbName string, migrations []migration.Migration, target string) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Changing the database structure version.
    old, current, err := migrator.Run(dbName, "set_version", target)
    if err != nil {
        panic(err)
    }

    // Printing old and current versions.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}

Direct commands calls

In contrast, you can call commands functions directly. Be careful, direct calls receives target argument of type int64 instead of string and mongo.Database pointer instead of database name.

package usage_example

import (
    "fmt"

    "go.mongodb.org/mongo-driver/mongo"

    "github.com/Devoter/mongo-migrator/migrator"
    "github.com/Devoter/mongo-migrator/migration"
)

func DirectCalls(client *mongo.Client, dbName string, migrations []migration.Migration, target int64) {
    // Creating a migrator instance. The constructor sorts the migrations slice automatically
    // and appends the `zero` migration.
    migrator := migrator.NewMigrator(client, migrations)

    // Getting a database pointer.
    base := m.client.Database(dbName)

    // Creating the `migrations` collection and initialing it with the zero database structure version.
    if _, _, err := migrator.Init(base); err != nil {
        panic(err)
    }

    // Applying all unapplied migrations up to the target.
    old, current, err := migrator.Up(base, target)
    if err != nil {
        panic(err)
    }
    // Printing old and current versions.
    fmt.Printf("Old version: %d, current version: %d\n", old, current)

    // Applying all unapplied migrations.
    old, current, err = migrator.Up(base, -1)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Old version: %d, current version: %d\n", old, current)

    // Reverting the last applied migration.
    old, current, err = migrator.Down(base)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Old version: %d, current version: %d\n", old, current)

    // Reverting all applied migrations.
    old, current, err = migrator.Reset(base)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Old version: %d, current version: %d\n", old, current)

    // Changing the database structure version to target.
    old, current, err = migrator.SetVersion(base, target)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Old version: %d, current version: %d\n", old, current)

    // Getting the current database structure version.
    _, current, err = migrator.Version(base)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Current version: %d\n", current)

    // Changing the database structure version to zero.
    old, current, err = migrator.SetVersion(base, 0)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Old version: %d, current version: %d\n", old, current)
}

License

MIT

Documentation

Index

Constants

View Source
const ErrorCommandRequired = Error("Command required")

ErrorCommandRequired means that no command was specified.

View Source
const ErrorInvalidVersionArgumentFormat = Error("Invalid version argument format")

ErrorInvalidVersionArgumentFormat means that the format of an argument named `version` does not correspond to int64.

View Source
const ErrorMigrationsAreNotInitialized = Error("Migrations are not initialized, try to call `init` at first")

ErrorMigrationsAreNotInitialized means that migrations collection is empty.

View Source
const ErrorMigrationsCollectionAlreadyExists = Error("Migrations collection already exists")

ErrorMigrationsCollectionAlreadyExists means that `migrations` collection already in the database.

View Source
const ErrorNoMigrations = Error("No migrations")

ErrorNoMigrations means that no migrations ware found at the specified path.

View Source
const ErrorSomeMigrationsAreAbsent = Error("Some migrations are absent")

ErrorSomeMigrationsAreAbsent means that some migrations files are absent.

View Source
const ErrorTargetVersionNotFound = Error("Target migration version was not found")

ErrorTargetVersionNotFound means that the target migration version was not found in migrations list.

View Source
const ErrorUnequalCountsOfMigrations = Error("Unequal counts of `up` and `down` migrations")

ErrorUnequalCountsOfMigrations means that the count of `up` migrations is not equal to the count of `down` migrations.

View Source
const ErrorUnexpectedCommand = Error("Unexpected command")

ErrorUnexpectedCommand means that command name is unknown.

View Source
const ErrorVersionNumberRequired = Error("Version number required")

ErrorVersionNumberRequired means that no version number was specified via command line.

Variables

This section is empty.

Functions

This section is empty.

Types

type Error

type Error string

Error declares constant error type.

func (Error) Error

func (e Error) Error() string

type Migrator

type Migrator struct {
	// contains filtered or unexported fields
}

Migrator declares MongoDB migrations manager.

func NewMigrator

func NewMigrator(client *mongo.Client, migrations []migration.Migration) *Migrator

NewMigrator returns a new instance of `Migrator`.

func (*Migrator) Down

func (m *Migrator) Down(db *mongo.Database) (oldVersion int64, newVersion int64, err error)

Down downgrades database revision to the previous version.

func (*Migrator) Init

func (m *Migrator) Init(db *mongo.Database) (oldVersion int64, newVersion int64, err error)

Init creates `migrations` collection if it does not exist and records the initial zero-migration.

func (*Migrator) Reset

func (m *Migrator) Reset(db *mongo.Database) (oldVersion int64, newVersion int64, err error)

Reset resets database to the zero-revision.

func (*Migrator) Run

func (m *Migrator) Run(db string, args ...string) (oldVersion int64, newVersion int64, err error)

Run interprets commands.

func (*Migrator) SetVersion

func (m *Migrator) SetVersion(db *mongo.Database, target int64) (oldVersion int64, newVersion int64, err error)

SetVersion forces database revisiton version.

func (*Migrator) Up

func (m *Migrator) Up(db *mongo.Database, target int64) (oldVersion int64, newVersion int64, err error)

Up upgrades database revision to the target or next version.

func (*Migrator) Version

func (m *Migrator) Version(db *mongo.Database) (oldVersion int64, newVersion int64, err error)

Version returns current database revision version.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL