279 lines
9.3 KiB
Go
279 lines
9.3 KiB
Go
package pilgrim_conf
|
|
|
|
import (
|
|
"flag"
|
|
"sync"
|
|
)
|
|
|
|
const (
|
|
Flag_Url string = "url"
|
|
Flag_Driver string = "driver"
|
|
Flag_Username string = "username"
|
|
Flag_Password string = "password"
|
|
Flag_Host string = "host"
|
|
Flag_Port string = "port"
|
|
Flag_Segments string = "segments"
|
|
Flag_Args string = "args"
|
|
Flag_Directory string = "dir"
|
|
Flag_Up string = "up"
|
|
Flag_Down string = "down"
|
|
Flag_Script string = "script"
|
|
Flag_Schema string = "schema"
|
|
Flag_Table string = "table"
|
|
Flag_DisableChecksumValidation string = "disable_checksum_validation"
|
|
Flag_StrictOrdering string = "strict_ordering"
|
|
Flag_ValidateMigrationOrder string = "validate_migration_order"
|
|
Flag_ValidateLatest string = "validate_latest"
|
|
Flag_ValidateChecksums string = "validate_checksums"
|
|
)
|
|
|
|
type CliFlagRetriever interface {
|
|
Url() (value string, isProvided bool)
|
|
Driver() (value DbDriver, isProvided bool)
|
|
Username() (value string, isProvided bool)
|
|
Password() (value string, isProvided bool)
|
|
Host() (value string, isProvided bool)
|
|
Port() (value string, isProvided bool)
|
|
Segments() (value []string, isProvided bool)
|
|
Args() (value map[string]string, isProvided bool)
|
|
Directory() (value string, isProvided bool)
|
|
IsUp() (value bool, isProvided bool)
|
|
IsDown() (value bool, isProvided bool)
|
|
// Can be a script name, or "latest"
|
|
Script() (value string, isProvided bool)
|
|
MigrationTable() (value string, isProvided bool)
|
|
MigrationTableSchema() (value string, isProvided bool)
|
|
IsChecksumValidationEnabled() (value bool, isProvided bool)
|
|
IsStrictOrderingEnabled() (value bool, isProvided bool)
|
|
IsValidatingMigrationOrder() (value bool, isProvided bool)
|
|
IsValidatingLatest() (value bool, isProvided bool)
|
|
IsValidatingChecksums() (value bool, isProvided bool)
|
|
|
|
ParseFlags()
|
|
}
|
|
|
|
var ctxSingleton *cliContext
|
|
var once sync.Once
|
|
|
|
type cliContext struct {
|
|
isProvided map[string]bool
|
|
|
|
url,
|
|
driver,
|
|
username,
|
|
password,
|
|
host,
|
|
port,
|
|
segments,
|
|
args,
|
|
directory,
|
|
script,
|
|
migrationTable,
|
|
migrationTableSchema *string
|
|
|
|
up,
|
|
down,
|
|
strictOrdering,
|
|
disableChecksumValidation,
|
|
validateChecksums,
|
|
validateMigrationOrder,
|
|
validateLatest *bool
|
|
}
|
|
|
|
// Creates the cliContext singleton
|
|
// Using any of the flags here requires a call to `ParseFlags`
|
|
func CliContext() *cliContext {
|
|
once.Do(func() {
|
|
ctxSingleton = &cliContext{
|
|
url: flag.String(Flag_Url, EmptyString, "<driver>://[[username]:[password]@]<host>:<port>[/database[?arg1=value[&arg2=value ...]]]"),
|
|
driver: flag.String(Flag_Driver, EmptyString, "The database driver ( mysql, postgres, sqlite, mariadb, oracle, mssql )"),
|
|
username: flag.String(Flag_Username, EmptyString, "The user"),
|
|
password: flag.String(Flag_Password, EmptyString, "Password for user"),
|
|
host: flag.String(Flag_Host, EmptyString, "The database host"),
|
|
port: flag.String(Flag_Port, EmptyString, "The database port"),
|
|
segments: flag.String(Flag_Segments, EmptyString, "The segments ( often the database name, in format \"segment1/segment2\" )"),
|
|
args: flag.String(Flag_Args, EmptyString, "Additional arguments to provide the database connection ( in format 'arg1=value&arg2=value' )"),
|
|
directory: flag.String(Flag_Directory, "./migrations", "The migration directory"),
|
|
script: flag.String(Flag_Script, "latest", "The script to upgrade/downgrade to."),
|
|
migrationTable: flag.String(Flag_Table, "pilgrim_migrations", "The database table to store migration information. WARNING: Changing this after running migrations once WILL NOT automagically move migration metadata from one table to another and will run all migrations from scratch."),
|
|
migrationTableSchema: flag.String(Flag_Schema, "", "The schema the database table belongs to. Default depends on driver. See WARNING of migration table."),
|
|
|
|
up: flag.Bool(Flag_Up, false, "Upgrade the database."),
|
|
down: flag.Bool(Flag_Down, false, "Upgrade the database."),
|
|
strictOrdering: flag.Bool(Flag_StrictOrdering, false, "Enforce strict ordering, pilgrim will run a validation of migration execution order before running the migrations"),
|
|
disableChecksumValidation: flag.Bool(Flag_DisableChecksumValidation, false, "Disable checksum validation when running database migration"),
|
|
|
|
validateChecksums: flag.Bool(Flag_ValidateChecksums, false, "(Special) Validate that all current checksums of migration files match the ones stored in the migration table"),
|
|
validateMigrationOrder: flag.Bool(Flag_ValidateMigrationOrder, false, "(Special) Runs a validation of the migration directory to ensure there is no uncertainty in migration order of execution."),
|
|
validateLatest: flag.Bool(Flag_ValidateLatest, false, "(Special) Validate that the provided database contains all migrations in the migration directory"),
|
|
|
|
isProvided: make(map[string]bool),
|
|
}
|
|
})
|
|
|
|
return ctxSingleton
|
|
}
|
|
|
|
func (cli *cliContext) ParseFlags() {
|
|
flag.Parse()
|
|
|
|
flag.Visit(func(f *flag.Flag) {
|
|
cli.isProvided[f.Name] = true
|
|
})
|
|
}
|
|
|
|
func (cli *cliContext) Url() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Url)
|
|
}
|
|
|
|
func (cli *cliContext) Driver() (value DbDriver, isProvided bool) {
|
|
val, provided := cli.fetchStringFlagValue(Flag_Driver)
|
|
|
|
return DbDriver(val), provided
|
|
}
|
|
|
|
func (cli *cliContext) Username() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Username)
|
|
}
|
|
|
|
func (cli *cliContext) Password() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Password)
|
|
}
|
|
|
|
func (cli *cliContext) Host() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Host)
|
|
}
|
|
|
|
func (cli *cliContext) Port() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Port)
|
|
}
|
|
|
|
func (cli *cliContext) Segments() (value []string, isProvided bool) {
|
|
rawVal, provided := cli.fetchStringFlagValue(Flag_Segments)
|
|
|
|
if rawVal == EmptyString {
|
|
return []string{}, false
|
|
}
|
|
|
|
return ParseSegments(rawVal), provided
|
|
}
|
|
|
|
func (cli *cliContext) Args() (value map[string]string, isProvided bool) {
|
|
rawVal, provided := cli.fetchStringFlagValue(Flag_Args)
|
|
|
|
if rawVal == EmptyString {
|
|
return make(map[string]string), false
|
|
}
|
|
|
|
return ParseArguments(rawVal), provided
|
|
}
|
|
|
|
func (cli *cliContext) Directory() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Directory)
|
|
}
|
|
|
|
func (cli *cliContext) IsUp() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_Up)
|
|
}
|
|
|
|
func (cli *cliContext) IsDown() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_Down)
|
|
}
|
|
|
|
// Can be a script name, or "latest"
|
|
func (cli *cliContext) Script() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Script)
|
|
}
|
|
|
|
func (cli *cliContext) MigrationTable() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Table)
|
|
}
|
|
|
|
func (cli *cliContext) MigrationTableSchema() (value string, isProvided bool) {
|
|
return cli.fetchStringFlagValue(Flag_Schema)
|
|
}
|
|
|
|
func (cli *cliContext) IsChecksumValidationEnabled() (value bool, isProvided bool) {
|
|
disabled, provided := cli.fetchBoolFlagValue(Flag_DisableChecksumValidation)
|
|
return !disabled, provided
|
|
}
|
|
|
|
func (cli *cliContext) IsStrictOrderingEnabled() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_StrictOrdering)
|
|
}
|
|
|
|
func (cli *cliContext) IsValidatingMigrationOrder() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_ValidateMigrationOrder)
|
|
}
|
|
|
|
func (cli *cliContext) IsValidatingLatest() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_ValidateLatest)
|
|
}
|
|
|
|
func (cli *cliContext) IsValidatingChecksums() (value bool, isProvided bool) {
|
|
return cli.fetchBoolFlagValue(Flag_ValidateChecksums)
|
|
}
|
|
|
|
func (cli *cliContext) fetchStringFlagValue(f string) (value string, isProvided bool) {
|
|
var valPtr *string = nil
|
|
|
|
switch f {
|
|
case Flag_Url:
|
|
valPtr = cli.url
|
|
case Flag_Driver:
|
|
valPtr = cli.driver
|
|
case Flag_Username:
|
|
valPtr = cli.username
|
|
case Flag_Password:
|
|
valPtr = cli.password
|
|
case Flag_Host:
|
|
valPtr = cli.host
|
|
case Flag_Port:
|
|
valPtr = cli.port
|
|
case Flag_Segments:
|
|
valPtr = cli.segments
|
|
case Flag_Args:
|
|
valPtr = cli.args
|
|
case Flag_Directory:
|
|
valPtr = cli.directory
|
|
case Flag_Script:
|
|
valPtr = cli.script
|
|
case Flag_Schema:
|
|
valPtr = cli.migrationTableSchema
|
|
case Flag_Table:
|
|
valPtr = cli.migrationTable
|
|
}
|
|
|
|
if valPtr == nil {
|
|
return EmptyString, cli.isProvided[f]
|
|
}
|
|
|
|
return *valPtr, cli.isProvided[f]
|
|
}
|
|
|
|
func (cli *cliContext) fetchBoolFlagValue(f string) (value bool, isProvided bool) {
|
|
var valPtr *bool = nil
|
|
|
|
switch f {
|
|
case Flag_Up:
|
|
valPtr = cli.up
|
|
case Flag_Down:
|
|
valPtr = cli.down
|
|
case Flag_StrictOrdering:
|
|
valPtr = cli.strictOrdering
|
|
case Flag_DisableChecksumValidation:
|
|
valPtr = cli.disableChecksumValidation
|
|
case Flag_ValidateChecksums:
|
|
valPtr = cli.validateChecksums
|
|
case Flag_ValidateMigrationOrder:
|
|
valPtr = cli.validateMigrationOrder
|
|
case Flag_ValidateLatest:
|
|
valPtr = cli.validateLatest
|
|
}
|
|
|
|
if valPtr == nil {
|
|
return false, cli.isProvided[f]
|
|
}
|
|
|
|
return *valPtr, cli.isProvided[f]
|
|
}
|