tools/migration/rdbms/main.go (88 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. package main import ( "bytes" "flag" "fmt" "os" "path/filepath" // Import migration packages so that golang migrations can register themselves _ "github.com/facebookincubator/contest/db/rdbms/migration" "github.com/facebookincubator/contest/pkg/xcontext/bundles/logrusctx" "github.com/facebookincubator/contest/pkg/xcontext/logger" "github.com/facebookincubator/contest/tools/migration/rdbms/migrate" _ "github.com/go-sql-driver/mysql" "github.com/pressly/goose" "github.com/sirupsen/logrus" ) var ( flags = flag.NewFlagSet("migrate", flag.ExitOnError) flagDBDriver = flags.String("dbDriver", "mysql", "DB Driver") flagDBURI = flags.String("dbURI", "contest:contest@tcp(localhost:3306)/contest?parseTime=true", "Database URI") flagDir = flags.String("dir", "", "Directory containing migration scripts") flagDebug = flags.Bool("debug", false, "Enabled debug logging") ) var usageHeader = `Usage: migrate [OPTIONS] COMMAND` var commandsUsage = ` Commands: up Migrate the DB to the most recent version available up-by-one Migrate the DB up by 1 up-to VERSION Migrate the DB to a specific VERSION down Roll back the version by 1 down-to VERSION Roll back to a specific VERSION redo Re-run the latest migration reset Roll back all migrations status Dump the migration status for the current DB version Print the current version of the database create NAME [sql|go] Creates new migration file with the current timestamp fix Apply sequential ordering to migrations ` func usage() { buf := new(bytes.Buffer) flags.SetOutput(buf) flags.PrintDefaults() fmt.Fprintf(os.Stderr, "%s", usageHeader) fmt.Fprintf(os.Stderr, "%s", "\n") fmt.Fprintf(os.Stderr, "%s", buf.String()) fmt.Fprintf(os.Stderr, "%s", commandsUsage) } func main() { if len(os.Args) < 2 { flags.Usage() return } flags.Usage = usage err := flags.Parse(os.Args[1:]) if err != nil { flags.Usage() panic(err) } logLevel := logger.LevelInfo if *flagDebug { logLevel = logger.LevelDebug } var ctx = logrusctx.NewContext(logLevel) ctx.Logger().OriginalLogger().(*logrus.Entry).Logger.SetOutput(os.Stdout) if *flagDir == "" { flags.Usage() ctx.Logger().Fatalf("migration directory was not specified") } for _, m := range migrate.Migrations { migration := m.Factory(ctx.WithField("migration", filepath.Base(m.Name))) goose.AddNamedMigration(m.Name, migration.Up, migration.Down) } command := os.Args[len(os.Args)-1] db, err := goose.OpenDBWithDriver(*flagDBDriver, *flagDBURI) if err != nil { ctx.Logger().Fatalf("failed to open DB: %v", err) } if err := db.Ping(); err != nil { ctx.Logger().Fatalf("db not reachable: %v", err) } defer func() { if err := db.Close(); err != nil { ctx.Logger().Fatalf("failed to close DB: %v", err) } }() if err := goose.Run(command, db, *flagDir, flags.Args()...); err != nil { ctx.Logger().Fatalf("could not run command %v for migration: %v", command, err) } }