2025-03-15 19:03:22 +02:00
package pilgrim_conf
2024-10-25 23:57:19 +03:00
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 ]
}