2016-03-24 14:11:56 +00:00
/ *
Copyright 2016 GitHub Inc .
See https : //github.com/github/gh-osc/blob/master/LICENSE
* /
2016-03-21 14:57:01 +00:00
package main
import (
"flag"
"fmt"
"os"
2016-04-04 10:27:51 +00:00
"github.com/github/gh-osc/go/base"
"github.com/github/gh-osc/go/logic"
2016-03-21 14:57:01 +00:00
"github.com/outbrain/golib/log"
)
// main is the application's entry point. It will either spawn a CLI or HTTP itnerfaces.
func main ( ) {
2016-04-04 10:27:51 +00:00
migrationContext := base . GetMigrationContext ( )
2016-03-30 13:43:40 +00:00
2016-04-04 13:29:02 +00:00
flag . StringVar ( & migrationContext . InspectorConnectionConfig . Key . Hostname , "host" , "127.0.0.1" , "MySQL hostname (preferably a replica, not the master)" )
flag . IntVar ( & migrationContext . InspectorConnectionConfig . Key . Port , "port" , 3306 , "MySQL port (preferably a replica, not the master)" )
flag . StringVar ( & migrationContext . InspectorConnectionConfig . User , "user" , "root" , "MySQL user" )
flag . StringVar ( & migrationContext . InspectorConnectionConfig . Password , "password" , "" , "MySQL password" )
2016-03-30 13:43:40 +00:00
2016-04-04 10:27:51 +00:00
flag . StringVar ( & migrationContext . DatabaseName , "database" , "" , "database name (mandatory)" )
flag . StringVar ( & migrationContext . OriginalTableName , "table" , "" , "table name (mandatory)" )
flag . StringVar ( & migrationContext . AlterStatement , "alter" , "" , "alter statement (mandatory)" )
flag . BoolVar ( & migrationContext . CountTableRows , "exact-rowcount" , false , "actually count table rows as opposed to estimate them (results in more accurate progress estimation)" )
2016-04-04 13:29:02 +00:00
flag . BoolVar ( & migrationContext . AllowedRunningOnMaster , "allow-on-master" , false , "allow this migration to run directly on master. Preferably it would run on a replica" )
2016-04-04 10:27:51 +00:00
2016-04-14 11:37:56 +00:00
executeFlag := flag . Bool ( "execute" , false , "actually execute the alter & migrate the table. Default is noop: do some tests and exit" )
flag . BoolVar ( & migrationContext . TestOnReplica , "test-on-replica" , false , "Have the migration run on a replica, not on the master. At the end of migration tables are not swapped; gh-osc issues `STOP SLAVE` and you can compare the two tables for building trust" )
2016-04-08 12:35:06 +00:00
flag . Int64Var ( & migrationContext . ChunkSize , "chunk-size" , 1000 , "amount of rows to handle in each iteration (allowed range: 100-100,000)" )
if migrationContext . ChunkSize < 100 {
migrationContext . ChunkSize = 100
}
if migrationContext . ChunkSize > 100000 {
migrationContext . ChunkSize = 100000
}
2016-04-14 11:37:56 +00:00
flag . Int64Var ( & migrationContext . MaxLagMillisecondsThrottleThreshold , "max-lag-millis" , 1500 , "replication lag at which to throttle operation" )
2016-04-11 15:27:16 +00:00
flag . StringVar ( & migrationContext . ThrottleFlagFile , "throttle-flag-file" , "" , "operation pauses when this file exists; hint: use a file that is specific to the table being altered" )
flag . StringVar ( & migrationContext . ThrottleAdditionalFlagFile , "throttle-additional-flag-file" , "/tmp/gh-osc.throttle" , "operation pauses when this file exists; hint: keep default, use for throttling multiple gh-osc operations" )
2016-04-08 12:35:06 +00:00
maxLoad := flag . String ( "max-load" , "" , "Comma delimited status-name=threshold. e.g: 'Threads_running=100,Threads_connected=500'" )
2016-03-21 14:57:01 +00:00
quiet := flag . Bool ( "quiet" , false , "quiet" )
verbose := flag . Bool ( "verbose" , false , "verbose" )
debug := flag . Bool ( "debug" , false , "debug mode (very verbose)" )
stack := flag . Bool ( "stack" , false , "add stack trace upon error" )
help := flag . Bool ( "help" , false , "Display usage" )
flag . Parse ( )
if * help {
fmt . Fprintf ( os . Stderr , "Usage of gh-osc:\n" )
flag . PrintDefaults ( )
return
}
log . SetLevel ( log . ERROR )
if * verbose {
log . SetLevel ( log . INFO )
}
if * debug {
log . SetLevel ( log . DEBUG )
}
if * stack {
log . SetPrintStackTrace ( * stack )
}
if * quiet {
// Override!!
log . SetLevel ( log . ERROR )
}
2016-04-04 10:27:51 +00:00
if migrationContext . DatabaseName == "" {
log . Fatalf ( "--database must be provided and database name must not be empty" )
}
if migrationContext . OriginalTableName == "" {
log . Fatalf ( "--table must be provided and table name must not be empty" )
}
if migrationContext . AlterStatement == "" {
log . Fatalf ( "--alter must be provided and statement must not be empty" )
}
2016-04-14 11:37:56 +00:00
migrationContext . Noop = ! ( * executeFlag )
if migrationContext . AllowedRunningOnMaster && migrationContext . TestOnReplica {
log . Fatalf ( "--allow-on-master and --test-on-replica are mutually exclusive" )
}
2016-04-08 12:35:06 +00:00
if err := migrationContext . ReadMaxLoad ( * maxLoad ) ; err != nil {
log . Fatale ( err )
}
2016-04-04 10:27:51 +00:00
2016-03-21 14:57:01 +00:00
log . Info ( "starting gh-osc" )
2016-03-23 11:40:17 +00:00
2016-04-04 13:29:02 +00:00
migrator := logic . NewMigrator ( )
2016-04-04 10:27:51 +00:00
err := migrator . Migrate ( )
if err != nil {
log . Fatale ( err )
2016-03-23 11:40:17 +00:00
}
2016-04-04 10:27:51 +00:00
log . Info ( "Done" )
2016-03-21 14:57:01 +00:00
}