From 3caebd44ccdad64377fa7122c81c204b0cf0a990 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Thu, 23 Jun 2016 21:43:01 +0600 Subject: [PATCH 1/9] fix lock issues --- archive.go | 3 +- command.go | 23 ++++- debug.go | 25 +++++- lock.go | 14 +-- locked_writer.go | 87 +++++++++++++++++++ main.go | 20 ++++- remote_execution.go | 50 ++++++++--- remote_execution_node.go | 8 +- remote_execution_runner.go | 7 +- ...reachable-servers-if-flag-is-given.test.sh | 2 +- ...andle-common-mistakes-in-arguments.test.sh | 4 - ...ate-errors-on-the-end-of-execution.test.sh | 11 +-- ...on-zero-exit-code-if-command-fails.test.sh | 4 +- ...n-lock-failed-if-flag-is-specified.test.sh | 1 - ...-remote-at-verbose-level-to-stderr.test.sh | 4 +- ...-verbose-debug-info-in-json-format.test.sh | 2 +- 16 files changed, 214 insertions(+), 51 deletions(-) create mode 100644 locked_writer.go diff --git a/archive.go b/archive.go index 50c614d..20f5a85 100644 --- a/archive.go +++ b/archive.go @@ -18,6 +18,7 @@ func startArchiveReceivers( cluster *distributedLock, rootDir string, sudo bool, + serial bool, ) (*remoteExecution, error) { var ( command = []string{} @@ -39,7 +40,7 @@ func startArchiveReceivers( logMutex := &sync.Mutex{} - runner := &remoteExecutionRunner{command: command} + runner := &remoteExecutionRunner{command: command, serial: serial} execution, err := runner.run( cluster, diff --git a/command.go b/command.go index e702df7..9f561fb 100644 --- a/command.go +++ b/command.go @@ -32,16 +32,22 @@ func runRemoteExecution( lockedNodes *distributedLock, command string, setupCallback func(*remoteExecutionNode), + serial bool, ) (*remoteExecution, error) { var ( stdins = []io.WriteCloser{} logLock = &sync.Mutex{} stdinsLock = &sync.Mutex{} + outputLock = &sync.Mutex{} nodes = &remoteNodes{&sync.Mutex{}, remoteNodesMap{}} ) + if !serial { + outputLock = nil + } + errors := make(chan error, 0) for _, node := range lockedNodes.nodes { go func(node *distributedLockNode) { @@ -59,6 +65,7 @@ func runRemoteExecution( node, command, logLock, + outputLock, ) if err != nil { errors <- err @@ -115,7 +122,8 @@ func runRemoteExecution( func runRemoteExecutionNode( node *distributedLockNode, command string, - logLock *sync.Mutex, + logLock sync.Locker, + outputLock sync.Locker, ) (*remoteExecutionNode, error) { remoteCommand, err := node.runner.Command(command) if err != nil { @@ -174,7 +182,7 @@ func runRemoteExecutionNode( stdout = lineflushwriter.New( prefixwriter.New( newDebugWriter(logger), - node.String()+" {cmd} ", + "{cmd} "+node.String()+" ", ), logLock, false, @@ -183,18 +191,25 @@ func runRemoteExecutionNode( stderr = lineflushwriter.New( prefixwriter.New( newDebugWriter(logger), - node.String()+" {cmd} ", + "{cmd} "+node.String()+" ", ), logLock, false, ) } + if outputLock != (*sync.Mutex)(nil) { + sharedLock := newSharedLock(outputLock, 2) + + stdout = newLockedWriter(stdout, sharedLock) + stderr = newLockedWriter(stderr, sharedLock) + } + stdin, err := remoteCommand.StdinPipe() if err != nil { return nil, hierr.Errorf( err, - `can't get stdin from archive receiver command`, + `can't get stdin from remote command`, ) } diff --git a/debug.go b/debug.go index e3af256..a3e1de4 100644 --- a/debug.go +++ b/debug.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "strings" "github.com/seletskiy/hierr" ) @@ -61,8 +62,30 @@ func serializeError(err error) string { if hierarchicalError, ok := err.(hierr.Error); ok { serializedError := fmt.Sprint(hierarchicalError.Nested) - if nested, ok := hierarchicalError.Nested.(error); ok { + switch nested := hierarchicalError.Nested.(type) { + case error: serializedError = serializeError(nested) + + case []hierr.NestedError: + serializeErrorParts := []string{} + + for _, nestedPart := range nested { + serializedPart := fmt.Sprint(nestedPart) + switch part := nestedPart.(type) { + case error: + serializedPart = serializeError(part) + + case string: + serializedPart = part + } + + serializeErrorParts = append( + serializeErrorParts, + serializedPart, + ) + } + + serializedError = strings.Join(serializeErrorParts, "; ") } return hierarchicalError.Message + ": " + serializedError diff --git a/lock.go b/lock.go index 2cada6f..a4295fd 100644 --- a/lock.go +++ b/lock.go @@ -56,7 +56,6 @@ func acquireDistributedLock( err = node.lock(lockFile) if err != nil { if noLockFail { - failed = true warningf("%s", err) } else { errors <- err @@ -96,7 +95,7 @@ func acquireDistributedLock( for range addresses { err := <-errors if err != nil { - erronous += 1 + erronous++ topError = hierr.Push(topError, err) } @@ -127,6 +126,9 @@ func connectToNode( go func() { select { + case <-done: + return + case <-time.After(longConnectionWarningTimeout): warningf( "still connecting to address after %s: %s", @@ -134,10 +136,12 @@ func connectToNode( address, ) - case <-done: + <-done } + }() - return + defer func() { + done <- struct{}{} }() runner, err := runnerFactory(address) @@ -149,8 +153,6 @@ func connectToNode( ) } - done <- struct{}{} - return &distributedLockNode{ address: address, runner: runner, diff --git a/locked_writer.go b/locked_writer.go new file mode 100644 index 0000000..b4ae5e3 --- /dev/null +++ b/locked_writer.go @@ -0,0 +1,87 @@ +package main + +import ( + "io" + "sync" +) + +type sharedLock struct { + sync.Locker + + held *struct { + sync.Locker + + clients int + locked bool + } +} + +func newSharedLock(lock sync.Locker, clients int) *sharedLock { + return &sharedLock{ + Locker: lock, + + held: &struct { + sync.Locker + + clients int + locked bool + }{ + Locker: &sync.Mutex{}, + + clients: clients, + locked: false, + }, + } +} + +func (mutex *sharedLock) Lock() { + mutex.held.Lock() + defer mutex.held.Unlock() + + if !mutex.held.locked { + mutex.Locker.Lock() + + mutex.held.locked = true + } +} + +func (mutex *sharedLock) Unlock() { + mutex.held.Lock() + defer mutex.held.Unlock() + + mutex.held.clients-- + + if mutex.held.clients == 0 && mutex.held.locked { + mutex.held.locked = false + + mutex.Locker.Unlock() + } +} + +type lockedWriter struct { + writer io.WriteCloser + + lock sync.Locker +} + +func newLockedWriter( + writer io.WriteCloser, + lock sync.Locker, +) *lockedWriter { + return &lockedWriter{ + writer: writer, + lock: lock, + } +} + +func (writer *lockedWriter) Write(data []byte) (int, error) { + writer.lock.Lock() + + return writer.writer.Write(data) +} + +func (writer *lockedWriter) Close() error { + writer.lock.Unlock() + + return writer.writer.Close() +} diff --git a/main.go b/main.go index a775c54..447ef97 100644 --- a/main.go +++ b/main.go @@ -122,6 +122,10 @@ Options: -u --user Username used for connecting to all hosts by default. [default: $USER] -i --stdin Pass specified file as input for the command. + -l --serial Run commands in serial mode, so they output will not + interleave each other. Only one node is allowed to + output, all other nodes will wait that node to + finish. -q --quiet Be quiet, in command mode do not use prefixes. -v --verbose Print debug information on stderr. -V --version Print program version. @@ -205,7 +209,7 @@ var ( ) func main() { - logger.SetFormat(lorg.NewFormat("* ${time} ${level:[%s]:right} %s")) + logger.SetFormat(lorg.NewFormat("* ${time} ${level:[%s]:right:true} %s")) usage, err := formatUsage(usage) if err != nil { @@ -304,6 +308,7 @@ func handleEvaluate(args map[string]interface{}) error { rootDir, _ = args["--root"].(string) sudo = args["--sudo"].(bool) shell = args["--shell"].(string) + serial = args["--serial"].(bool) command = args[""].([]string) ) @@ -320,6 +325,7 @@ func handleEvaluate(args map[string]interface{}) error { sudo: sudo, command: command, directory: rootDir, + serial: serial, } return run(cluster, runner, stdin) @@ -374,7 +380,9 @@ func run( if err != nil { return hierr.Errorf( err, - `remote execution failed`, + `remote execution failed, because one of `+ + `command has been exited with non-zero exit `+ + `code at least on one node`, ) } @@ -396,7 +404,8 @@ func handleSynchronize(args map[string]interface{}) error { shell = args["--shell"].(string) - sudo = args["--sudo"].(bool) + sudo = args["--sudo"].(bool) + serial = args["--serial"].(bool) fileSources = args[""].([]string) ) @@ -469,6 +478,7 @@ func handleSynchronize(args map[string]interface{}) error { command: command, args: commandArgs, directory: rootDir, + serial: serial, } if isSimpleCommand { @@ -497,6 +507,8 @@ func upload( preserveUID = !args["--no-preserve-uid"].(bool) preserveGID = !args["--no-preserve-gid"].(bool) + + serial = args["--serial"].(bool) ) if rootDir == "" { @@ -505,7 +517,7 @@ func upload( debugf(`file upload started into: '%s'`, rootDir) - receivers, err := startArchiveReceivers(cluster, rootDir, sudo) + receivers, err := startArchiveReceivers(cluster, rootDir, sudo, serial) if err != nil { return hierr.Errorf( err, diff --git a/remote_execution.go b/remote_execution.go index 23c13f8..d7b7a8a 100644 --- a/remote_execution.go +++ b/remote_execution.go @@ -3,6 +3,7 @@ package main import ( "fmt" "io" + "reflect" "github.com/seletskiy/hierr" ) @@ -19,27 +20,29 @@ type remoteExecutionResult struct { } func (execution *remoteExecution) wait() error { - tracef("waiting %d nodes to finish", len(execution.nodes)) + tracef(`waiting %d nodes to finish`, len(execution.nodes)) results := make(chan *remoteExecutionResult, 0) for _, node := range execution.nodes { go func(node *remoteExecutionNode) { - pool.run(func() { - results <- &remoteExecutionResult{node, node.wait()} - }) + results <- &remoteExecutionResult{node, node.wait()} }(node) } executionErrors := fmt.Errorf( - `can't run remote commands on %d nodes`, - len(execution.nodes), + `commands are exited with non-zero code`, ) - erroneous := false + var ( + failures = 0 + exitCodes = map[int]int{} + ) for range execution.nodes { result := <-results if result.err != nil { + exitCodes[result.node.exitCode]++ + executionErrors = hierr.Push( executionErrors, hierr.Errorf( @@ -49,7 +52,7 @@ func (execution *remoteExecution) wait() error { ), ) - erroneous = true + failures++ continue } @@ -60,8 +63,35 @@ func (execution *remoteExecution) wait() error { ) } - if erroneous { - return executionErrors + if failures > 0 { + if failures == len(execution.nodes) { + exitCodesValue := reflect.ValueOf(exitCodes) + + topError := fmt.Errorf( + `commands are exited with non-zero exit code on all %d nodes`, + len(execution.nodes), + ) + + for _, key := range exitCodesValue.MapKeys() { + topError = hierr.Push( + topError, + fmt.Sprintf( + `code %d (%d nodes)`, + key.Int(), + exitCodesValue.MapIndex(key).Int(), + ), + ) + } + + return topError + } + + return hierr.Errorf( + executionErrors, + `commands are exited with non-zero exit code on %d of %d nodes`, + failures, + len(execution.nodes), + ) } return nil diff --git a/remote_execution_node.go b/remote_execution_node.go index 306388c..d550499 100644 --- a/remote_execution_node.go +++ b/remote_execution_node.go @@ -17,6 +17,8 @@ type remoteExecutionNode struct { stdin io.WriteCloser stdout io.WriteCloser stderr io.WriteCloser + + exitCode int } func (node *remoteExecutionNode) wait() error { @@ -24,12 +26,14 @@ func (node *remoteExecutionNode) wait() error { if err != nil { _ = node.stdout.Close() _ = node.stderr.Close() - if sshErr, ok := err.(*ssh.ExitError); ok { + if sshErrors, ok := err.(*ssh.ExitError); ok { + node.exitCode = sshErrors.Waitmsg.ExitStatus() + return fmt.Errorf( `%s had failed to evaluate command, `+ `remote command exited with non-zero code: %d`, node.node.String(), - sshErr.Waitmsg.ExitStatus(), + node.exitCode, ) } diff --git a/remote_execution_runner.go b/remote_execution_runner.go index 6e56ec9..fac8f1f 100644 --- a/remote_execution_runner.go +++ b/remote_execution_runner.go @@ -10,11 +10,12 @@ var ( ) type remoteExecutionRunner struct { - shell string - sudo bool command []string args []string + shell string directory string + sudo bool + serial bool } func (runner *remoteExecutionRunner) run( @@ -38,7 +39,7 @@ func (runner *remoteExecutionRunner) run( command = joinCommand(sudoCommand) + " " + command } - return runRemoteExecution(cluster, command, setupCallback) + return runRemoteExecution(cluster, command, setupCallback, runner.serial) } func wrapCommandIntoShell(command string, shell string, args []string) string { diff --git a/tests/testcases/can-skip-unreachable-servers-if-flag-is-given.test.sh b/tests/testcases/can-skip-unreachable-servers-if-flag-is-given.test.sh index 1bc1f83..cd60e3d 100644 --- a/tests/testcases/can-skip-unreachable-servers-if-flag-is-given.test.sh +++ b/tests/testcases/can-skip-unreachable-servers-if-flag-is-given.test.sh @@ -2,7 +2,7 @@ tests:not tests:ensure :orgalorg:with-key -o example.com -C whoami tests:ensure :orgalorg:with-key -o example.com -w -C whoami -tests:assert-stderr-re "WARNING.*can't connect to address.*example.com" +tests:assert-stderr-re "WARN.*can't connect to address.*example.com" :check-node-output() { local container_ip="$2" diff --git a/tests/testcases/commandline/can-handle-common-mistakes-in-arguments.test.sh b/tests/testcases/commandline/can-handle-common-mistakes-in-arguments.test.sh index 0783fbc..b126d85 100644 --- a/tests/testcases/commandline/can-handle-common-mistakes-in-arguments.test.sh +++ b/tests/testcases/commandline/can-handle-common-mistakes-in-arguments.test.sh @@ -5,10 +5,6 @@ tests:not tests:ensure :orgalorg -o ./blah -C echo blah tests:assert-stderr-re "can't open.*blah" tests:assert-stderr-re "blah.*no such file or directory" -tests:not tests:ensure :orgalorg -p -s -C echo blah -tests:assert-stderr-re "incompatible options" -tests:assert-stderr-re "password authentication is not possible.*stdin" - tests:not tests:ensure :orgalorg -o blah --send-timeout=wazup -C echo dunno tests:assert-stderr-re "send timeout to number" diff --git a/tests/testcases/commands/can-aggregate-errors-on-the-end-of-execution.test.sh b/tests/testcases/commands/can-aggregate-errors-on-the-end-of-execution.test.sh index a81310c..c5fc11c 100644 --- a/tests/testcases/commands/can-aggregate-errors-on-the-end-of-execution.test.sh +++ b/tests/testcases/commands/can-aggregate-errors-on-the-end-of-execution.test.sh @@ -1,10 +1,3 @@ tests:not tests:ensure :orgalorg:with-key -e -C echo 1 '&&' exit 1 - -:check-node-output() { - local container_ip="$2" - - tests:assert-stdout "$container_ip 1" - tests:assert-stderr-re "$container_ip.*non-zero code: 1" -} - -containers:do :check-node-output +tests:assert-stderr-re "exited with non-zero.*all $(containers:count) nodes" +tests:assert-stderr "code 1 ($(containers:count) nodes)" diff --git a/tests/testcases/commands/should-return-non-zero-exit-code-if-command-fails.test.sh b/tests/testcases/commands/should-return-non-zero-exit-code-if-command-fails.test.sh index 23b4d69..e1c3c5b 100644 --- a/tests/testcases/commands/should-return-non-zero-exit-code-if-command-fails.test.sh +++ b/tests/testcases/commands/should-return-non-zero-exit-code-if-command-fails.test.sh @@ -1,4 +1,4 @@ tests:not tests:ensure :orgalorg:with-key -e -C exit 17 -tests:assert-stderr "failed to evaluate" -tests:assert-stderr "non-zero code: 17" +tests:assert-stderr "remote execution failed" +tests:assert-stderr "code 17 ($(containers:count) nodes)" diff --git a/tests/testcases/locking/will-continue-execution-when-lock-failed-if-flag-is-specified.test.sh b/tests/testcases/locking/will-continue-execution-when-lock-failed-if-flag-is-specified.test.sh index 004efb6..24d749c 100644 --- a/tests/testcases/locking/will-continue-execution-when-lock-failed-if-flag-is-specified.test.sh +++ b/tests/testcases/locking/will-continue-execution-when-lock-failed-if-flag-is-specified.test.sh @@ -3,7 +3,6 @@ tests:involve tests/testcases/locking/lock.sh :orgalorg:lock orgalorg_output orgalorg_pid tests:ensure :orgalorg:with-key --no-lock-fail -C -- echo 1 -tests:assert-stderr "proceeding with execution" tests:assert-stdout "1" pkill -INT -P "$orgalorg_pid" diff --git a/tests/testcases/verbosity/can-log-stderr-and-stdout-from-remote-at-verbose-level-to-stderr.test.sh b/tests/testcases/verbosity/can-log-stderr-and-stdout-from-remote-at-verbose-level-to-stderr.test.sh index a75f3c1..1dbaa95 100644 --- a/tests/testcases/verbosity/can-log-stderr-and-stdout-from-remote-at-verbose-level-to-stderr.test.sh +++ b/tests/testcases/verbosity/can-log-stderr-and-stdout-from-remote-at-verbose-level-to-stderr.test.sh @@ -1,5 +1,5 @@ # note! tests:ensure will eat '>&2' if it's passed without prefix tests:ensure :orgalorg:with-key -v -C -- echo 1 \; echo err\>\&2 -tests:assert-stderr " 1" -tests:assert-stderr " err" +tests:assert-stderr-re ' \[.*\] 1' +tests:assert-stderr-re ' \[.*\] err' diff --git a/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh b/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh index dec2926..2ede5dc 100644 --- a/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh +++ b/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh @@ -2,4 +2,4 @@ tests:ensure :orgalorg:with-key --json -vv -C pwd tests:assert-stderr-re '"stream":"stderr"' tests:assert-stderr-re '"body":".*DEBUG.*connection established' -tests:assert-stderr-re '"body":".*DEBUG.*locking node' +tests:assert-stderr-re '"body":".*DEBUG.*running lock command' From e3f2fc8913b592aa1ecadd7f9b50a0ab621aa1a3 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Fri, 24 Jun 2016 01:44:55 +0600 Subject: [PATCH 2/9] coloooors --- command.go | 5 + debug.go | 94 ++++++- distributed_lock_node.go | 9 +- format.go | 236 ++++++++++++++++-- json_output_writer.go | 43 ++++ lock.go | 10 +- main.go | 100 +++++--- remote_execution.go | 4 + remote_execution_runner.go | 6 +- status_bar.go | 120 +++++++++ status_bar_update_writer.go | 23 ++ ...ld-properly-escape-shell-arguments.test.sh | 8 + themes.go | 69 +++++ 13 files changed, 659 insertions(+), 68 deletions(-) create mode 100644 json_output_writer.go create mode 100644 status_bar.go create mode 100644 status_bar_update_writer.go create mode 100644 tests/testcases/commands/should-properly-escape-shell-arguments.test.sh create mode 100644 themes.go diff --git a/command.go b/command.go index 9f561fb..f67ab40 100644 --- a/command.go +++ b/command.go @@ -48,6 +48,8 @@ func runRemoteExecution( outputLock = nil } + status.SetOutputLock(logLock) + errors := make(chan error, 0) for _, node := range lockedNodes.nodes { go func(node *distributedLockNode) { @@ -198,6 +200,9 @@ func runRemoteExecutionNode( ) } + stdout = &statusBarUpdateWriter{stdout} + stderr = &statusBarUpdateWriter{stderr} + if outputLock != (*sync.Mutex)(nil) { sharedLock := newSharedLock(outputLock, 2) diff --git a/debug.go b/debug.go index a3e1de4..1b88425 100644 --- a/debug.go +++ b/debug.go @@ -2,11 +2,59 @@ package main import ( "fmt" + "os" "strings" + "github.com/fatih/color" + + "github.com/kovetskiy/lorg" "github.com/seletskiy/hierr" ) +func setupLogger(format *lorg.Format) { + logger.SetFormat(format) +} + +func setLoggerOutputFormat(format outputFormat, logger *lorg.Log) { + if format == outputFormatJSON { + logger.SetOutput(&jsonOutputWriter{ + stream: `stderr`, + node: ``, + output: os.Stderr, + }) + } +} + +func setLoggerVerbosity(level verbosity, logger *lorg.Log) { + logger.SetLevel(lorg.LevelWarning) + + switch { + case level >= verbosityTrace: + logger.SetLevel(lorg.LevelTrace) + + case level >= verbosityDebug: + logger.SetLevel(lorg.LevelDebug) + + case level >= verbosityNormal: + logger.SetLevel(lorg.LevelInfo) + } +} + +func colorize( + attributes ...color.Attribute, +) string { + if !isColorEnabled { + return "" + } + + sequence := []string{} + for _, attribute := range attributes { + sequence = append(sequence, fmt.Sprint(attribute)) + } + + return fmt.Sprintf("\x1b[%sm", strings.Join(sequence, ";")) +} + func tracef(format string, args ...interface{}) { if verbose < verbosityTrace { return @@ -14,19 +62,25 @@ func tracef(format string, args ...interface{}) { args = serializeErrors(args) - logger.Debugf(format, args...) + logger.Tracef(format, args...) + + drawStatus() } func debugf(format string, args ...interface{}) { args = serializeErrors(args) logger.Debugf(format, args...) + + drawStatus() } func infof(format string, args ...interface{}) { args = serializeErrors(args) logger.Infof(format, args...) + + drawStatus() } func warningf(format string, args ...interface{}) { @@ -37,6 +91,8 @@ func warningf(format string, args ...interface{}) { } logger.Warningf(format, args...) + + drawStatus() } func errorf(format string, args ...interface{}) { @@ -55,6 +111,42 @@ func serializeErrors(args []interface{}) []interface{} { return args } +func shouldDrawStatus() bool { + if !isOutputOnTTY { + return false + } + + if format != outputFormatText { + return false + } + + if verbose <= verbosityQuiet { + return false + } + + if status == nil { + return false + } + + return true +} + +func drawStatus() { + if !shouldDrawStatus() { + return + } + + status.Draw(os.Stderr) +} + +func clearStatus() { + if !shouldDrawStatus() { + return + } + + status.Clear(os.Stderr) +} + func serializeError(err error) string { if format == outputFormatText { return fmt.Sprint(err) diff --git a/distributed_lock_node.go b/distributed_lock_node.go index c76a862..8b84b66 100644 --- a/distributed_lock_node.go +++ b/distributed_lock_node.go @@ -38,10 +38,11 @@ func (node *distributedLockNode) lock( filename string, ) error { lockCommandString := fmt.Sprintf( - `sh -c $'`+ - `flock -nx %s -c \'`+ - `printf "%s\\n" && cat\' || `+ - `printf "%s\\n"'`, + `sh -c "`+ + `flock -nx %s -c '`+ + `printf \"%s\\n\" && cat' || `+ + `printf \"%s\\n\"`+ + `"`, filename, lockAcquiredString, lockLockedString, diff --git a/format.go b/format.go index f8b5917..926be9f 100644 --- a/format.go +++ b/format.go @@ -1,8 +1,17 @@ package main import ( - "encoding/json" - "io" + "fmt" + "os" + "regexp" + "strings" + "text/template" + + "golang.org/x/crypto/ssh/terminal" + + "github.com/kovetskiy/lorg" + "github.com/seletskiy/hierr" + "github.com/seletskiy/tplutil" ) type ( @@ -14,47 +23,224 @@ const ( outputFormatJSON ) -func parseOutputFormat(args map[string]interface{}) outputFormat { - if args["--json"].(bool) { - return outputFormatJSON +const ( + formatEscape = "\x1b" + + formatAttrForeground = "3" + formatAttrBackground = "4" + formatAttrDefault = "9" + + formatAttrReset = "0" + formatAttrReverse = "7" + formatAttrNoReverse = "27" + formatAttrBold = "1" + formatAttrNoBold = "22" + + formatAttrForeground256 = "38;5" + formatAttrBackground256 = "48;5" + + formatResetBlock = "{reset}" +) + +var ( + formatCodeRegexp = regexp.MustCompile(formatEscape + `[^m]+`) +) + +func getResetFormatSequence() string { + return getFormatSequence(formatAttrReset) +} + +func getBackgroundFormatSequence(color int) string { + if color == 0 { + return getFormatSequence( + formatAttrBackground + formatAttrDefault, + ) + } + + return getFormatSequence(formatAttrBackground256, fmt.Sprint(color)) +} + +func getForegroundFormatSequence(color int) string { + if color == 0 { + return getFormatSequence( + formatAttrForeground + formatAttrDefault, + ) + } + + return getFormatSequence(formatAttrForeground256, fmt.Sprint(color)) +} + +func getBoldFormatSequence() string { + return getFormatSequence(formatAttrBold) +} + +func getNoBoldFormatSequence() string { + return getFormatSequence(formatAttrNoBold) +} + +func getReverseFormatSequence() string { + return getFormatSequence(formatAttrReverse) +} + +func getNoReverseFormatSequence() string { + return getFormatSequence(formatAttrNoReverse) +} + +func getFormatSequence(attr ...string) string { + if !isColorEnabled { + return "" + } + + return fmt.Sprintf("%s[%sm", formatEscape, strings.Join(attr, `;`)) +} + +func getLogPlaceholder(placeholder string) string { + return fmt.Sprintf("${%s}", placeholder) +} + +func getLogLevelFormatPlaceholder( + level string, + formatString string, +) (string, error) { + format, err := compileFormat(formatString) + if err != nil { + return "", hierr.Errorf( + err, + `can't compile specified format string: '%s'`, + formatString, + ) } - return outputFormatText + formatCode, err := tplutil.ExecuteToString(format, nil) + if err != nil { + return "", hierr.Errorf( + err, + `can't execute specified format string: '%s'`, + formatString, + ) + } + + return fmt.Sprintf( + "${color:%s:%s}", + level, + strings.Replace(formatCode, ":", "\\:", -1), + ), nil } -type jsonOutputWriter struct { - stream string - node string +func executeLogColorPlaceholder(level lorg.Level, value string) string { + var ( + parts = strings.SplitN(value, ":", 2) + targetLevel = parts[0] + format = "" + ) + + if len(parts) > 1 { + format = parts[1] + } - output io.Writer + if targetLevel == strings.ToLower(level.String()) { + return format + } + + return "" +} + +func compileFormat(format string) (*template.Template, error) { + functions := map[string]interface{}{ + "bg": getBackgroundFormatSequence, + "fg": getForegroundFormatSequence, + "bold": getBoldFormatSequence, + "nobold": getNoBoldFormatSequence, + "reverse": getReverseFormatSequence, + "noreverse": getNoReverseFormatSequence, + "reset": getResetFormatSequence, + + "log": getLogPlaceholder, + "level": getLogLevelFormatPlaceholder, + } + + return template.New("format").Delims("{", "}").Funcs(functions).Parse( + format, + ) } -func (writer *jsonOutputWriter) Write(data []byte) (int, error) { - if len(data) == 0 { - return 0, nil +func parseOutputFormat( + args map[string]interface{}, +) (outputFormat, bool, bool) { + + format := outputFormatText + if args["--json"].(bool) { + format = outputFormatJSON + } + + isOutputOnTTY := terminal.IsTerminal(int(os.Stderr.Fd())) + + isColorEnabled := isOutputOnTTY + + if format != outputFormatText { + isColorEnabled = false } - message := map[string]interface{}{ - "stream": writer.stream, + if args["--no-colors"].(bool) { + isColorEnabled = false } - if writer.node == "" { - message["node"] = nil - } else { - message["node"] = writer.node + return format, isOutputOnTTY, isColorEnabled +} + +func trimFormatCodes(input string) string { + return formatCodeRegexp.ReplaceAllLiteralString(input, ``) +} + +func parseStatusBarFormat( + args map[string]interface{}, +) (*template.Template, error) { + var ( + theme = args["--status-format"].(string) + ) + + statusFormat := getStatusBarTheme(theme) + formatResetBlock + + format, err := compileFormat(statusFormat) + if err != nil { + return nil, hierr.Errorf( + err, + `can't compile status bar format template`, + ) } - message["body"] = string(data) + tracef("using status bar format: '%s'", statusFormat) + + return format, nil +} + +func parseLogFormat(args map[string]interface{}) (*lorg.Format, error) { + var ( + theme = args["--log-format"].(string) + ) + + logFormat := getLogTheme(theme) + formatResetBlock - jsonMessage, err := json.Marshal(message) + format, err := compileFormat(logFormat) if err != nil { - return 0, err + return nil, hierr.Errorf( + err, + `can't compile log format template`, + ) } - _, err = writer.output.Write(append(jsonMessage, '\n')) + formatString, err := tplutil.ExecuteToString(format, nil) if err != nil { - return 0, err + return nil, hierr.Errorf( + err, + `can't execute log format template`, + ) } - return len(data), nil + tracef("using log format: '%#s'", logFormat) + + lorgFormat := lorg.NewFormat(formatString) + lorgFormat.SetPlaceholder("color", executeLogColorPlaceholder) + + return lorgFormat, nil } diff --git a/json_output_writer.go b/json_output_writer.go new file mode 100644 index 0000000..4520422 --- /dev/null +++ b/json_output_writer.go @@ -0,0 +1,43 @@ +package main + +import ( + "encoding/json" + "io" +) + +type jsonOutputWriter struct { + stream string + node string + + output io.Writer +} + +func (writer *jsonOutputWriter) Write(data []byte) (int, error) { + if len(data) == 0 { + return 0, nil + } + + message := map[string]interface{}{ + "stream": writer.stream, + } + + if writer.node == "" { + message["node"] = nil + } else { + message["node"] = writer.node + } + + message["body"] = string(data) + + jsonMessage, err := json.Marshal(message) + if err != nil { + return 0, err + } + + _, err = writer.output.Write(append(jsonMessage, '\n')) + if err != nil { + return 0, err + } + + return len(data), nil +} diff --git a/lock.go b/lock.go index a4295fd..890b1c3 100644 --- a/lock.go +++ b/lock.go @@ -64,10 +64,14 @@ func acquireDistributedLock( } } - status := "established" + textStatus := "established" if failed { - status = "failed" + status.IncFailures() + + textStatus = "failed" } else { + status.IncSuccess() + atomic.AddInt64(&connections, 1) nodeAddMutex.Lock() @@ -81,7 +85,7 @@ func acquireDistributedLock( connections, int64(len(addresses))-failures, failures, - status, + textStatus, nodeAddress, ) diff --git a/main.go b/main.go index 447ef97..018d8ca 100644 --- a/main.go +++ b/main.go @@ -107,7 +107,7 @@ Options: [default: $HOME/.ssh/id_rsa] -p --password Enable password authentication. Exclude '-k' option. - TTY is required for reading password. + Interactive TTY is required for reading password. -x --sudo Obtain root via 'sudo -n'. By default, orgalorg will not obtain root and do all actions from specified user. To change that @@ -157,17 +157,49 @@ Advanced options: shell wrapper will be used. If any args are given using '-g', they will be appended to shell invocation. - [default: bash -c $'{}'] + [default: bash -c '{}'] -d --threads Set threads count which will be used for connection, locking and execution commands. [default: 16]. + --no-preserve-uid Do not preserve UIDs for transferred files. + --no-preserve-gid Do not preserve GIDs for transferred files. + +Output format and colors options: --json Output everything in line-by-line JSON format, printing objects with fields: * 'stream' = 'stdout' | 'stderr'; * 'node' = | null (if internal output); * 'body' = - --no-preserve-uid Do not preserve UIDs for transferred files. - --no-preserve-gid Do not preserve GIDs for transferred files. + --status-format Format for the status bar. + Full Go template syntax is available with delims + of '{' and '}'. Variables available: + * .Phase - either: + * '` + statusBarPhaseConnecting + `'; + * '` + statusBarPhaseExecuting + `'; + * .Total - total amount of connected nodes; + * .Success - number of nodes that successfully done + phase; + * .Failures - number of failed nodes; + Additional functions are available: + * bg - set background color to specified; + * 0 can be used for default bg; + * fg - set foreground color to specified; + * 0 can be used for default fg; + * bold/nobold - set or reset bold mode; + * reverse/noreverse - set or reset reverse mode; + * reset - completely resets mode; + For example, run orgalorg with '-vv' flag. + Two embedded themes are available by their names: + ` + themeDark + ` and ` + themeLight + ` + [default: ` + themeDark + `] + --log-format Format for the logs. + Same, as above, with additional functions: + * log - inserts lorg placeholder + specification; + * level - insert in place specified + format if log level matches specified level. + [default: ` + themeDark + `] + --no-colors Do not use colors. Timeout options: --conn-timeout Remote host connection timeout in milliseconds. @@ -201,7 +233,11 @@ var ( verbose = verbosityNormal format = outputFormatText - pool *threadPool + pool *threadPool + status *statusBar + + isOutputOnTTY = false + isColorEnabled = false ) var ( @@ -209,11 +245,9 @@ var ( ) func main() { - logger.SetFormat(lorg.NewFormat("* ${time} ${level:[%s]:right:true} %s")) - - usage, err := formatUsage(usage) + usage, err := formatUsage(string(usage)) if err != nil { - logger.Error(hierr.Errorf( + errorf("%s", hierr.Errorf( err, `can't format usage`, )) @@ -230,7 +264,16 @@ func main() { setLoggerVerbosity(verbose, logger) - format = parseOutputFormat(args) + format, isOutputOnTTY, isColorEnabled = parseOutputFormat(args) + + logFormat, err := parseLogFormat(args) + if err != nil { + errorf("%s", err) + + exit(1) + } + + setupLogger(logFormat) setLoggerOutputFormat(format, logger) @@ -244,6 +287,10 @@ func main() { pool = newThreadPool(poolSize) + statusFormat, err := parseStatusBarFormat(args) + + status = newStatusBar(statusFormat) + switch { case args["--upload"].(bool): fallthrough @@ -262,27 +309,6 @@ func main() { } } -func setLoggerOutputFormat(format outputFormat, logger *lorg.Log) { - if format == outputFormatJSON { - logger.SetOutput(&jsonOutputWriter{ - stream: `stderr`, - node: ``, - output: os.Stderr, - }) - } -} - -func setLoggerVerbosity(level verbosity, logger *lorg.Log) { - logger.SetLevel(lorg.LevelWarning) - - switch { - case level >= verbosityDebug: - logger.SetLevel(lorg.LevelDebug) - case level >= verbosityNormal: - logger.SetLevel(lorg.LevelInfo) - } -} - func formatUsage(template string) (string, error) { currentUser, err := user.Current() if err != nil { @@ -580,6 +606,8 @@ func connectAndLock( noLockFail = args["--no-lock-fail"].(bool) ) + status.SetPhase(statusBarPhaseConnecting) + addresses, err := parseAddresses(hosts, defaultUser, fromStdin) if err != nil { return nil, hierr.Errorf( @@ -588,6 +616,8 @@ func connectAndLock( ) } + status.SetTotal(len(addresses)) + timeouts, err := makeTimeouts(args) if err != nil { return nil, hierr.Errorf( @@ -746,7 +776,9 @@ func generateRunID() string { } func readPassword(prompt string) (string, error) { - fmt.Fprintf(os.Stderr, sshPasswordPrompt) + if isOutputOnTTY { + fmt.Fprintf(os.Stderr, sshPasswordPrompt) + } tty, err := os.Open("/dev/tty") if err != nil { @@ -765,7 +797,9 @@ func readPassword(prompt string) (string, error) { ) } - fmt.Fprintln(os.Stderr) + if isOutputOnTTY { + fmt.Fprintln(os.Stderr) + } return string(password), nil } diff --git a/remote_execution.go b/remote_execution.go index d7b7a8a..3f40f77 100644 --- a/remote_execution.go +++ b/remote_execution.go @@ -41,6 +41,8 @@ func (execution *remoteExecution) wait() error { for range execution.nodes { result := <-results if result.err != nil { + status.IncFailures() + exitCodes[result.node.exitCode]++ executionErrors = hierr.Push( @@ -57,6 +59,8 @@ func (execution *remoteExecution) wait() error { continue } + status.IncSuccess() + tracef( `%s has successfully finished execution`, result.node.node.String(), diff --git a/remote_execution_runner.go b/remote_execution_runner.go index fac8f1f..1e2dfe1 100644 --- a/remote_execution_runner.go +++ b/remote_execution_runner.go @@ -22,6 +22,8 @@ func (runner *remoteExecutionRunner) run( cluster *distributedLock, setupCallback func(*remoteExecutionNode), ) (*remoteExecution, error) { + status.SetPhase(statusBarPhaseExecuting) + command := joinCommand(runner.command) if runner.directory != "" { @@ -72,8 +74,7 @@ func joinCommand(command []string) string { } func escapeCommandArgument(argument string) string { - argument = strings.Replace(argument, `\`, `\\`, -1) - argument = strings.Replace(argument, ` `, `\ `, -1) + argument = strings.Replace(argument, `'`, `'\''`, -1) return argument } @@ -82,6 +83,7 @@ func escapeCommandArgumentStrict(argument string) string { argument = strings.Replace(argument, `\`, `\\`, -1) argument = strings.Replace(argument, "`", "\\`", -1) argument = strings.Replace(argument, `"`, `\"`, -1) + argument = strings.Replace(argument, `'`, `'\''`, -1) argument = strings.Replace(argument, `$`, `\$`, -1) return `"` + argument + `"` diff --git a/status_bar.go b/status_bar.go new file mode 100644 index 0000000..46a7316 --- /dev/null +++ b/status_bar.go @@ -0,0 +1,120 @@ +package main + +import ( + "bytes" + "fmt" + "io" + "strings" + "sync" + "text/template" + + "github.com/seletskiy/hierr" +) + +type ( + statusBarPhase string +) + +const ( + statusBarPhaseConnecting statusBarPhase = "CONNECTING" + statusBarPhaseExecuting = "EVALUATING" +) + +type statusBar struct { + sync.Mutex + + Phase statusBarPhase + Total int + Failures int + Success int + + format *template.Template + + last string + + lock sync.Locker +} + +func newStatusBar(format *template.Template) *statusBar { + return &statusBar{ + format: format, + } +} + +func (bar *statusBar) SetPhase(phase statusBarPhase) { + bar.Lock() + defer bar.Unlock() + + bar.Phase = phase + + bar.Success = 0 +} + +func (bar *statusBar) SetTotal(total int) { + bar.Lock() + defer bar.Unlock() + + bar.Total = total +} + +func (bar *statusBar) IncSuccess() { + bar.Lock() + defer bar.Unlock() + + bar.Success++ +} + +func (bar *statusBar) IncFailures() { + bar.Lock() + defer bar.Unlock() + + bar.Failures++ +} + +func (bar *statusBar) SetOutputLock(lock sync.Locker) { + bar.lock = lock +} + +func (bar *statusBar) Clear(writer io.Writer) { + bar.Lock() + defer bar.Unlock() + + if bar.lock != nil { + bar.lock.Lock() + defer bar.lock.Unlock() + } + + fmt.Fprint(writer, strings.Repeat(" ", len(bar.last))+"\r") + + bar.last = "" +} + +func (bar *statusBar) Draw(writer io.Writer) { + bar.Lock() + defer bar.Unlock() + + if bar.lock != nil { + bar.lock.Lock() + defer bar.lock.Unlock() + } + + buffer := &bytes.Buffer{} + + if bar.Phase == "" { + return + } + + err := bar.format.Execute(buffer, bar) + if err != nil { + errorf("%s", hierr.Errorf( + err, + `error during rendering status bar`, + )) + } + + fmt.Fprintf(buffer, "\r") + + bar.last = trimFormatCodes(buffer.String()) + + io.Copy(writer, buffer) +} diff --git a/status_bar_update_writer.go b/status_bar_update_writer.go new file mode 100644 index 0000000..6513e4e --- /dev/null +++ b/status_bar_update_writer.go @@ -0,0 +1,23 @@ +package main + +import ( + "io" +) + +type statusBarUpdateWriter struct { + writer io.WriteCloser +} + +func (writer *statusBarUpdateWriter) Write(data []byte) (int, error) { + clearStatus() + + written, err := writer.writer.Write(data) + + drawStatus() + + return written, err +} + +func (writer *statusBarUpdateWriter) Close() error { + return writer.writer.Close() +} diff --git a/tests/testcases/commands/should-properly-escape-shell-arguments.test.sh b/tests/testcases/commands/should-properly-escape-shell-arguments.test.sh new file mode 100644 index 0000000..03f7e13 --- /dev/null +++ b/tests/testcases/commands/should-properly-escape-shell-arguments.test.sh @@ -0,0 +1,8 @@ +tests:ensure echo "'1'" +tests:ensure :orgalorg:with-key -e -C echo "'1'" + +tests:assert-stdout-re "1$" + +tests:ensure :orgalorg:with-key -e -C echo "\\'" + +tests:assert-stdout-re "'$" diff --git a/themes.go b/themes.go new file mode 100644 index 0000000..d957a7a --- /dev/null +++ b/themes.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" +) + +const ( + themeDark = `dark` + themeLight = `light` +) + +var ( + statusBarThemeTemplate = `{" "}{bg %d}{fg %d}` + + `{if eq .Phase "` + statusBarPhaseExecuting + `"}` + + `{bg %d}` + + `{end}` + + ` {bold}{.Phase}{nobold} ` + + `{fg %d}{reverse}{noreverse}{fg %d}{bg %d} ` + + `{fg %d}{printf "%%4d" .Success}{fg %d}/{printf "%%4d" .Total} ` + + `{if .Failures}{fg %d}(failed: {.Failures}){end}{" "}` + + statusBarThemes = map[string]string{ + themeDark: fmt.Sprintf( + statusBarThemeTemplate, + 99, 7, 64, 237, 15, 237, 28, 15, 9, + ), + + themeLight: fmt.Sprintf( + statusBarThemeTemplate, + 99, 7, 64, 254, 16, 254, 106, 16, 9, + ), + } + + logThemeTemplate = `{level "error" "{fg %d}"}` + + `{level "warning" "{fg %d}{bg %d}"}` + + `{level "debug" "{fg %d}"}` + + `{level "trace" "{fg %d}"}` + + `* {log "time"} ` + + `{level "error" "{bg %d}{bold}"}{log "level:[%%s]:right:true"}` + + `{level "error" "{bg %d}"}{nobold} %%s` + + logThemes = map[string]string{ + themeDark: fmt.Sprintf( + logThemeTemplate, + 1, 11, 0, 250, 243, 52, 0, + ), + + themeLight: fmt.Sprintf( + logThemeTemplate, + 199, 172, 230, 240, 248, 220, 0, + ), + } +) + +func getStatusBarTheme(theme string) string { + if format, ok := statusBarThemes[theme]; ok { + return format + } + + return theme +} + +func getLogTheme(theme string) string { + if format, ok := logThemes[theme]; ok { + return format + } + + return theme +} From 231caf7b4c9e4ba29ac812ddbbb888dfa6ff2fb8 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Fri, 24 Jun 2016 18:54:55 +0600 Subject: [PATCH 3/9] refactor styles --- demo.gif | Bin 0 -> 209432 bytes format.go | 206 ------------------------------------------ debug.go => log.go | 14 ++- main.go | 25 ++++-- status_bar.go | 3 +- style.go | 219 +++++++++++++++++++++++++++++++++++++++++++++ themes.go | 9 +- 7 files changed, 249 insertions(+), 227 deletions(-) create mode 100644 demo.gif rename debug.go => log.go (94%) create mode 100644 style.go diff --git a/demo.gif b/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a68197a0e5dfffeb3c8207110817c5c9f051406 GIT binary patch literal 209432 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%0D?cv3G4Zd4rwyGaDCHtS56x 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 z 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 1 { - format = parts[1] - } - - if targetLevel == strings.ToLower(level.String()) { - return format - } - - return "" -} - -func compileFormat(format string) (*template.Template, error) { - functions := map[string]interface{}{ - "bg": getBackgroundFormatSequence, - "fg": getForegroundFormatSequence, - "bold": getBoldFormatSequence, - "nobold": getNoBoldFormatSequence, - "reverse": getReverseFormatSequence, - "noreverse": getNoReverseFormatSequence, - "reset": getResetFormatSequence, - - "log": getLogPlaceholder, - "level": getLogLevelFormatPlaceholder, - } - - return template.New("format").Delims("{", "}").Funcs(functions).Parse( - format, - ) -} - func parseOutputFormat( args map[string]interface{}, ) (outputFormat, bool, bool) { @@ -187,60 +38,3 @@ func parseOutputFormat( return format, isOutputOnTTY, isColorEnabled } - -func trimFormatCodes(input string) string { - return formatCodeRegexp.ReplaceAllLiteralString(input, ``) -} - -func parseStatusBarFormat( - args map[string]interface{}, -) (*template.Template, error) { - var ( - theme = args["--status-format"].(string) - ) - - statusFormat := getStatusBarTheme(theme) + formatResetBlock - - format, err := compileFormat(statusFormat) - if err != nil { - return nil, hierr.Errorf( - err, - `can't compile status bar format template`, - ) - } - - tracef("using status bar format: '%s'", statusFormat) - - return format, nil -} - -func parseLogFormat(args map[string]interface{}) (*lorg.Format, error) { - var ( - theme = args["--log-format"].(string) - ) - - logFormat := getLogTheme(theme) + formatResetBlock - - format, err := compileFormat(logFormat) - if err != nil { - return nil, hierr.Errorf( - err, - `can't compile log format template`, - ) - } - - formatString, err := tplutil.ExecuteToString(format, nil) - if err != nil { - return nil, hierr.Errorf( - err, - `can't execute log format template`, - ) - } - - tracef("using log format: '%#s'", logFormat) - - lorgFormat := lorg.NewFormat(formatString) - lorgFormat.SetPlaceholder("color", executeLogColorPlaceholder) - - return lorgFormat, nil -} diff --git a/debug.go b/log.go similarity index 94% rename from debug.go rename to log.go index 1b88425..9b6a871 100644 --- a/debug.go +++ b/log.go @@ -11,11 +11,7 @@ import ( "github.com/seletskiy/hierr" ) -func setupLogger(format *lorg.Format) { - logger.SetFormat(format) -} - -func setLoggerOutputFormat(format outputFormat, logger *lorg.Log) { +func setLoggerOutputFormat(logger *lorg.Log, format outputFormat) { if format == outputFormatJSON { logger.SetOutput(&jsonOutputWriter{ stream: `stderr`, @@ -40,6 +36,10 @@ func setLoggerVerbosity(level verbosity, logger *lorg.Log) { } } +func setLoggerStyle(logger *lorg.Log, style *lorg.Format) { + logger.SetFormat(style) +} + func colorize( attributes ...color.Attribute, ) string { @@ -56,10 +56,6 @@ func colorize( } func tracef(format string, args ...interface{}) { - if verbose < verbosityTrace { - return - } - args = serializeErrors(args) logger.Tracef(format, args...) diff --git a/main.go b/main.go index 018d8ca..29ed224 100644 --- a/main.go +++ b/main.go @@ -199,6 +199,8 @@ Output format and colors options: * level - insert in place specified format if log level matches specified level. [default: ` + themeDark + `] + --dark Set all available formats to predefined dark theme. + --light Set all available formats to predefined light theme. --no-colors Do not use colors. Timeout options: @@ -266,16 +268,19 @@ func main() { format, isOutputOnTTY, isColorEnabled = parseOutputFormat(args) - logFormat, err := parseLogFormat(args) + setLoggerOutputFormat(logger, format) + + loggerStyle, err := getLoggerStyle(parseTheme("log", args)) if err != nil { - errorf("%s", err) + errorf("%s", hierr.Errorf( + err, + `can't use given logger style`, + )) exit(1) } - setupLogger(logFormat) - - setLoggerOutputFormat(format, logger) + setLoggerStyle(logger, loggerStyle) poolSize, err := parseThreadPoolSize(args) if err != nil { @@ -287,9 +292,15 @@ func main() { pool = newThreadPool(poolSize) - statusFormat, err := parseStatusBarFormat(args) + statusStyle, err := getStatusBarStyle(parseTheme("status", args)) + if err != nil { + errorf("%s", hierr.Errorf( + err, + `can't use given status bar style`, + )) + } - status = newStatusBar(statusFormat) + status = newStatusBar(statusStyle) switch { case args["--upload"].(bool): diff --git a/status_bar.go b/status_bar.go index 46a7316..213d300 100644 --- a/status_bar.go +++ b/status_bar.go @@ -69,6 +69,7 @@ func (bar *statusBar) IncFailures() { defer bar.Unlock() bar.Failures++ + bar.Total-- } func (bar *statusBar) SetOutputLock(lock sync.Locker) { @@ -114,7 +115,7 @@ func (bar *statusBar) Draw(writer io.Writer) { fmt.Fprintf(buffer, "\r") - bar.last = trimFormatCodes(buffer.String()) + bar.last = trimStyleCodes(buffer.String()) io.Copy(writer, buffer) } diff --git a/style.go b/style.go new file mode 100644 index 0000000..5508be9 --- /dev/null +++ b/style.go @@ -0,0 +1,219 @@ +package main + +import ( + "fmt" + "regexp" + "strings" + "text/template" + + "github.com/kovetskiy/lorg" + "github.com/seletskiy/hierr" + "github.com/seletskiy/tplutil" +) + +const ( + styleEscape = "\x1b" + + styleAttrForeground = "3" + styleAttrBackground = "4" + styleAttrDefault = "9" + + styleAttrReset = "0" + styleAttrReverse = "7" + styleAttrNoReverse = "27" + styleAttrBold = "1" + styleAttrNoBold = "22" + + styleAttrForeground256 = "38;5" + styleAttrBackground256 = "48;5" + + styleResetBlock = "{reset}" +) + +var ( + styleCodeRegexp = regexp.MustCompile(styleEscape + `[^m]+`) +) + +func getResetStyleSequence() string { + return getStyleSequence(styleAttrReset) +} + +func getBackgroundStyleSequence(color int) string { + if color == 0 { + return getStyleSequence( + styleAttrBackground + styleAttrDefault, + ) + } + + return getStyleSequence(styleAttrBackground256, fmt.Sprint(color)) +} + +func getForegroundStyleSequence(color int) string { + if color == 0 { + return getStyleSequence( + styleAttrForeground + styleAttrDefault, + ) + } + + return getStyleSequence(styleAttrForeground256, fmt.Sprint(color)) +} + +func getBoldStyleSequence() string { + return getStyleSequence(styleAttrBold) +} + +func getNoBoldStyleSequence() string { + return getStyleSequence(styleAttrNoBold) +} + +func getReverseStyleSequence() string { + return getStyleSequence(styleAttrReverse) +} + +func getNoReverseStyleSequence() string { + return getStyleSequence(styleAttrNoReverse) +} + +func getStyleSequence(attr ...string) string { + if !isColorEnabled { + return "" + } + + return fmt.Sprintf("%s[%sm", styleEscape, strings.Join(attr, `;`)) +} + +func getLogPlaceholder(placeholder string) string { + return fmt.Sprintf("${%s}", placeholder) +} + +func getLogLevelStylePlaceholder( + level string, + styleString string, +) (string, error) { + style, err := compileStyle(styleString) + if err != nil { + return "", hierr.Errorf( + err, + `can't compile specified style string: '%s'`, + styleString, + ) + } + + styleCode, err := tplutil.ExecuteToString(style, nil) + if err != nil { + return "", hierr.Errorf( + err, + `can't execute specified style string: '%s'`, + styleString, + ) + } + + return fmt.Sprintf( + "${color:%s:%s}", + level, + strings.Replace(styleCode, ":", "\\:", -1), + ), nil +} + +func executeLogColorPlaceholder(level lorg.Level, value string) string { + var ( + parts = strings.SplitN(value, ":", 2) + targetLevel = parts[0] + style = "" + ) + + if len(parts) > 1 { + style = parts[1] + } + + if targetLevel == strings.ToLower(level.String()) { + return style + } + + return "" +} + +func compileStyle(style string) (*template.Template, error) { + functions := map[string]interface{}{ + "bg": getBackgroundStyleSequence, + "fg": getForegroundStyleSequence, + "bold": getBoldStyleSequence, + "nobold": getNoBoldStyleSequence, + "reverse": getReverseStyleSequence, + "noreverse": getNoReverseStyleSequence, + "reset": getResetStyleSequence, + + "log": getLogPlaceholder, + "level": getLogLevelStylePlaceholder, + } + + return template.New("style").Delims("{", "}").Funcs(functions).Parse( + style, + ) +} + +func trimStyleCodes(input string) string { + return styleCodeRegexp.ReplaceAllLiteralString(input, ``) +} + +func getStatusBarStyle(theme string) (*template.Template, error) { + statusStyle := getStatusBarTheme(theme) + styleResetBlock + + style, err := compileStyle(statusStyle) + if err != nil { + return nil, hierr.Errorf( + err, + `can't compile status bar style template`, + ) + } + + tracef("using status bar style: '%s'", statusStyle) + + return style, nil +} + +func getLoggerStyle(theme string) (*lorg.Format, error) { + logStyle := getLogTheme(theme) + styleResetBlock + + style, err := compileStyle(logStyle) + if err != nil { + return nil, hierr.Errorf( + err, + `can't compile log style template`, + ) + } + + styleString, err := tplutil.ExecuteToString(style, nil) + if err != nil { + return nil, hierr.Errorf( + err, + `can't execute log style template`, + ) + } + + tracef("using log style: '%#s'", logStyle) + + lorgFormat := lorg.NewFormat(styleString) + lorgFormat.SetPlaceholder("color", executeLogColorPlaceholder) + + return lorgFormat, nil +} + +func parseTheme(target string, args map[string]interface{}) string { + var ( + theme = args["--"+target+"-format"].(string) + light = args["--light"].(bool) + dark = args["--dark"].(bool) + ) + + switch { + case light: + return themeLight + + case dark: + return themeLight + + default: + return theme + } +} diff --git a/themes.go b/themes.go index d957a7a..6ff07f5 100644 --- a/themes.go +++ b/themes.go @@ -16,18 +16,19 @@ var ( `{end}` + ` {bold}{.Phase}{nobold} ` + `{fg %d}{reverse}{noreverse}{fg %d}{bg %d} ` + - `{fg %d}{printf "%%4d" .Success}{fg %d}/{printf "%%4d" .Total} ` + - `{if .Failures}{fg %d}(failed: {.Failures}){end}{" "}` + `{fg %d}{bold}{printf "%%4d" .Success}{nobold}{fg %d}` + + `/{printf "%%4d" .Total} ` + + `{if .Failures}{fg %d}(failed: {.Failures}){end} {fg %d}{bg %d}` statusBarThemes = map[string]string{ themeDark: fmt.Sprintf( statusBarThemeTemplate, - 99, 7, 64, 237, 15, 237, 28, 15, 9, + 99, 7, 76, 237, 15, 237, 46, 15, 214, 237, 0, ), themeLight: fmt.Sprintf( statusBarThemeTemplate, - 99, 7, 64, 254, 16, 254, 106, 16, 9, + 99, 7, 64, 254, 16, 254, 106, 16, 9, 254, 0, ), } From b7e6f26623ba7c780b5a18591d6d440e0328b32c Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Fri, 24 Jun 2016 19:14:05 +0600 Subject: [PATCH 4/9] update readme --- README.md | 86 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 7ab2a46..7f4a8ca 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,37 @@ # orgalorg -Ultimate parallel cluster file synchronization tool. +Ultimate parallel cluster file synchronization tool and SSH commend +executioner. +![demo](https://raw.githubusercontent.com/reconquest/orgalorg/status-line/demo.gif) -# What +# Features -orgalorg provides easy way of synchronizing files acroess cluster. +* Zero-configuration. No config files. -orgalorg works through ssh & tar, so no unexpected protocol errors will arise. +* Running SSH commands or shell scripts on any number of hosts in parallel. All + output from nodes will be returned back, keeping stdout and stderr streams + mapping of original commands. -In default mode of operation (lately referred as sync mode) orgalorg will -perform following steps in order: +* Synchronizing files and directories across cluster with prior global cluster + locking. + After synchronization is done, arbitrary command can be evaluated. -1. Acquire global cluster lock (more detailed info above). -2. Create, upload and extract specified files in streaming mode to the - specified nodes into temporary run directory. -3. Start synchronization tool on each node, that should relocate files from - temporary run directory to the actual destination. +* Synchronizing files and directories with subsequent run of complex multi-step + scenario with steps synchronization across cluster. -So, orgalorg expected to work with third-party synchronization tool, that -will do actual files relocation and can be quite intricate, **but orgalorg can -work without that tool and perform simple files sync (more on this later)**. +* User-friendly progress indication. + +* Either strict or loose modes of failover to be sure, that either everything + will fail on any error, or everything will try to complete no mather of what. +* Interactive password authentication as well as SSH public key authentication. + +* Ability to run commands through `sudo`. + +* Grouped mode of output, so stdout and stderr from nodes will be grouped by + node name. Alternatively, output can be returned as soon as node returns + something. # Example usages @@ -30,19 +40,19 @@ host-specification arguments, like `-o host-a -o host-b`. ## Obtaining global cluster lock -``` +```bash orgalorg -o ... -L ``` ## Obtaining global cluster lock on custom directory -``` +```bash orgalorg -o ... -L -r /etc ``` ## Evaluating command on hosts in parallel -``` +```bash orgalorg -o ... -C uptime ``` @@ -51,34 +61,66 @@ orgalorg -o ... -C uptime `axfr` is a tool of your choice for retrieving domain information from your infrastructure DNS. -``` +```bash axfr | grep phpnode | orgalorg -s -C uptime ``` ## Evaluate command under root (passwordless sudo required) -``` +```bash orgalorg -o ... -x -C whoami ``` ## Copying SSH public key for remote authentication -``` +```bash orgalorg -o ... -p -i ~/.ssh/id_rsa.pub -C tee -a ~/.ssh/authorized_keys ``` ## Synchronizing configs and then reloading service (like nginx) -``` +```bash orgalorg -o ... -xn 'systemctl reload nginx' -S /etc/nginx.conf ``` ## Evaluating shell script -``` +```bash orgalorg -o ... -i script.bash -C bash ``` +## Install package on all nodes and get combined output from each node + +```bash +orgalorg -o ... -lx -C pacman -Sy my-package --noconfirm +``` + +## Evaluating shell oneliner + +```bash +orgalorg -o ... -C sleep '$(($RANDOM % 10))' '&&' echo done +``` + +# Description + +orgalorg provides easy way of synchronizing files across cluster and running +arbitrary SSH commands. + +orgalorg works through SSH & tar, so no unexpected protocol errors will arise. + +In default mode of operation (lately referred as sync mode) orgalorg will +perform following steps in order: + +1. Acquire global cluster lock (more detailed info above). +2. Create, upload and extract specified files in streaming mode to the + specified nodes into temporary run directory. +3. Start synchronization tool on each node, that should relocate files from + temporary run directory to the actual destination. + +So, orgalorg expected to work with third-party synchronization tool, that +will do actual files relocation and can be quite intricate, **but orgalorg can +work without that tool and perform simple files sync (more on this later)**. + ## Global Cluster Lock From 5ad671d0f4bae1228cd15e4525cec476b03b56b8 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Fri, 24 Jun 2016 20:56:20 +0600 Subject: [PATCH 5/9] make tests pass and update readme --- README.md | 30 +++++++++++++++++++ ...escape-space-in-the-remote-command.test.sh | 2 +- ...-verbose-debug-info-in-json-format.test.sh | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7f4a8ca..2387046 100644 --- a/README.md +++ b/README.md @@ -293,3 +293,33 @@ continue to the next step of execution process. <- ORGALORG:132464327653 SYNC [user@node2:1234] phase 1 completed ``` +# Testing + +To run tests it's enough to: + +``` +./run_tests +``` + +## Requirements + +Testcases are run through [tests.sh](https://github.com/reconquest/tests.sh) +library. + +For every testcase new set of temporary containers will be initialized through +[hastur](https://github.com/seletskiy/hastur), so `systemd` is required for +running test suite. + +orgalorg testcases are close to reality as possible, so orgalorg will really +connect via SSH to cluster of containers in each testcase. + +## Coverage + +Run following command to calculate total coverage (available after running +testsuite): + +```bash +make coverage.total +``` + +Current coverage level is something about **85%**. diff --git a/tests/testcases/commands/can-escape-space-in-the-remote-command.test.sh b/tests/testcases/commands/can-escape-space-in-the-remote-command.test.sh index 9b00d00..96637d0 100644 --- a/tests/testcases/commands/can-escape-space-in-the-remote-command.test.sh +++ b/tests/testcases/commands/can-escape-space-in-the-remote-command.test.sh @@ -1,3 +1,3 @@ -tests:ensure :orgalorg:with-key -e -C echo 'two spaces' +tests:ensure :orgalorg:with-key -e -C echo '"two spaces"' tests:assert-stdout "two spaces" diff --git a/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh b/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh index 2ede5dc..c42d9be 100644 --- a/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh +++ b/tests/testcases/verbosity/can-output-verbose-debug-info-in-json-format.test.sh @@ -2,4 +2,4 @@ tests:ensure :orgalorg:with-key --json -vv -C pwd tests:assert-stderr-re '"stream":"stderr"' tests:assert-stderr-re '"body":".*DEBUG.*connection established' -tests:assert-stderr-re '"body":".*DEBUG.*running lock command' +tests:assert-stderr-re '"body":".*TRACE.*running lock command' From 58ec8e24567a98ab4c8b9f390c69e638138e1ca0 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Tue, 28 Jun 2016 14:40:30 +0600 Subject: [PATCH 6/9] wip --- command.go | 2 -- lock.go | 30 +++++++++------- main.go | 7 ---- remote_execution.go | 4 --- remote_execution_runner.go | 2 -- status_bar.go | 71 +++++++++----------------------------- themes.go | 17 +++++---- 7 files changed, 43 insertions(+), 90 deletions(-) diff --git a/command.go b/command.go index f67ab40..aff38d8 100644 --- a/command.go +++ b/command.go @@ -48,8 +48,6 @@ func runRemoteExecution( outputLock = nil } - status.SetOutputLock(logLock) - errors := make(chan error, 0) for _, node := range lockedNodes.nodes { go func(node *distributedLockNode) { diff --git a/lock.go b/lock.go index 890b1c3..e1f1dc2 100644 --- a/lock.go +++ b/lock.go @@ -28,14 +28,23 @@ func acquireDistributedLock( var ( cluster = &distributedLock{} - connections = int64(0) - failures = int64(0) - errors = make(chan error, 0) nodeAddMutex = &sync.Mutex{} ) + report := &struct { + Locking bool + Nodes int64 + Fails int64 + Success int64 + }{ + Locking: true, + Nodes: int64(len(addresses)), + } + + status.Set(report) + for _, nodeAddress := range addresses { go func(nodeAddress address) { pool.run(func() { @@ -43,7 +52,8 @@ func acquireDistributedLock( node, err := connectToNode(cluster, runnerFactory, nodeAddress) if err != nil { - atomic.AddInt64(&failures, 1) + atomic.AddInt64(&report.Fails, 1) + atomic.AddInt64(&report.Nodes, -1) if noConnFail { failed = true @@ -66,13 +76,9 @@ func acquireDistributedLock( textStatus := "established" if failed { - status.IncFailures() - textStatus = "failed" } else { - status.IncSuccess() - - atomic.AddInt64(&connections, 1) + atomic.AddInt64(&report.Success, 1) nodeAddMutex.Lock() defer nodeAddMutex.Unlock() @@ -82,9 +88,9 @@ func acquireDistributedLock( debugf( `%4d/%d (%d failed) connection %s: %s`, - connections, - int64(len(addresses))-failures, - failures, + report.Success, + report.Nodes, + report.Fails, textStatus, nodeAddress, ) diff --git a/main.go b/main.go index 29ed224..7c89836 100644 --- a/main.go +++ b/main.go @@ -173,9 +173,6 @@ Output format and colors options: --status-format Format for the status bar. Full Go template syntax is available with delims of '{' and '}'. Variables available: - * .Phase - either: - * '` + statusBarPhaseConnecting + `'; - * '` + statusBarPhaseExecuting + `'; * .Total - total amount of connected nodes; * .Success - number of nodes that successfully done phase; @@ -617,8 +614,6 @@ func connectAndLock( noLockFail = args["--no-lock-fail"].(bool) ) - status.SetPhase(statusBarPhaseConnecting) - addresses, err := parseAddresses(hosts, defaultUser, fromStdin) if err != nil { return nil, hierr.Errorf( @@ -627,8 +622,6 @@ func connectAndLock( ) } - status.SetTotal(len(addresses)) - timeouts, err := makeTimeouts(args) if err != nil { return nil, hierr.Errorf( diff --git a/remote_execution.go b/remote_execution.go index 3f40f77..d7b7a8a 100644 --- a/remote_execution.go +++ b/remote_execution.go @@ -41,8 +41,6 @@ func (execution *remoteExecution) wait() error { for range execution.nodes { result := <-results if result.err != nil { - status.IncFailures() - exitCodes[result.node.exitCode]++ executionErrors = hierr.Push( @@ -59,8 +57,6 @@ func (execution *remoteExecution) wait() error { continue } - status.IncSuccess() - tracef( `%s has successfully finished execution`, result.node.node.String(), diff --git a/remote_execution_runner.go b/remote_execution_runner.go index 1e2dfe1..d4a9626 100644 --- a/remote_execution_runner.go +++ b/remote_execution_runner.go @@ -22,8 +22,6 @@ func (runner *remoteExecutionRunner) run( cluster *distributedLock, setupCallback func(*remoteExecutionNode), ) (*remoteExecution, error) { - status.SetPhase(statusBarPhaseExecuting) - command := joinCommand(runner.command) if runner.directory != "" { diff --git a/status_bar.go b/status_bar.go index 213d300..7ddd950 100644 --- a/status_bar.go +++ b/status_bar.go @@ -11,28 +11,13 @@ import ( "github.com/seletskiy/hierr" ) -type ( - statusBarPhase string -) - -const ( - statusBarPhaseConnecting statusBarPhase = "CONNECTING" - statusBarPhaseExecuting = "EVALUATING" -) - type statusBar struct { - sync.Mutex - - Phase statusBarPhase - Total int - Failures int - Success int + sync.Locker format *template.Template + last string - last string - - lock sync.Locker + data interface{} } func newStatusBar(format *template.Template) *statusBar { @@ -41,50 +26,33 @@ func newStatusBar(format *template.Template) *statusBar { } } -func (bar *statusBar) SetPhase(phase statusBarPhase) { - bar.Lock() - defer bar.Unlock() - - bar.Phase = phase - - bar.Success = 0 -} - -func (bar *statusBar) SetTotal(total int) { - bar.Lock() - defer bar.Unlock() - - bar.Total = total +func (bar *statusBar) Lock() { + if bar.Locker != nil { + bar.Locker.Lock() + } } -func (bar *statusBar) IncSuccess() { - bar.Lock() - defer bar.Unlock() - - bar.Success++ +func (bar *statusBar) Unlock() { + if bar.Locker != nil { + bar.Locker.Unlock() + } } -func (bar *statusBar) IncFailures() { +func (bar *statusBar) Set(data interface{}) { bar.Lock() defer bar.Unlock() - bar.Failures++ - bar.Total-- + bar.data = data } -func (bar *statusBar) SetOutputLock(lock sync.Locker) { - bar.lock = lock +func (bar *statusBar) SetLock(lock sync.Locker) { + bar.Locker = lock } func (bar *statusBar) Clear(writer io.Writer) { bar.Lock() defer bar.Unlock() - if bar.lock != nil { - bar.lock.Lock() - defer bar.lock.Unlock() - } - fmt.Fprint(writer, strings.Repeat(" ", len(bar.last))+"\r") bar.last = "" @@ -94,18 +62,13 @@ func (bar *statusBar) Draw(writer io.Writer) { bar.Lock() defer bar.Unlock() - if bar.lock != nil { - bar.lock.Lock() - defer bar.lock.Unlock() - } - buffer := &bytes.Buffer{} - if bar.Phase == "" { + if bar.data == nil { return } - err := bar.format.Execute(buffer, bar) + err := bar.format.Execute(buffer, bar.data) if err != nil { errorf("%s", hierr.Errorf( err, diff --git a/themes.go b/themes.go index 6ff07f5..ca4bcbc 100644 --- a/themes.go +++ b/themes.go @@ -10,20 +10,19 @@ const ( ) var ( - statusBarThemeTemplate = `{" "}{bg %d}{fg %d}` + - `{if eq .Phase "` + statusBarPhaseExecuting + `"}` + - `{bg %d}` + - `{end}` + - ` {bold}{.Phase}{nobold} ` + - `{fg %d}{reverse}{noreverse}{fg %d}{bg %d} ` + + statusBarThemeTemplate = `{" "}{bg %d}{fg %d}{" "}` + + `{bold}` + + `{if .Locking}{bg %d}LOCK{end}` + + `{nobold}{" "}` + + `{fg %d}{reverse}{noreverse}{fg %d}{bg %d}{" "}` + `{fg %d}{bold}{printf "%%4d" .Success}{nobold}{fg %d}` + - `/{printf "%%4d" .Total} ` + - `{if .Failures}{fg %d}(failed: {.Failures}){end} {fg %d}{bg %d}` + `/{printf "%%4d" .Total}{" "}` + + `{if .Failures}{fg %d}(failed: {.Failures}){end}{" "}{fg %d}{bg %d}` statusBarThemes = map[string]string{ themeDark: fmt.Sprintf( statusBarThemeTemplate, - 99, 7, 76, 237, 15, 237, 46, 15, 214, 237, 0, + 99, 7, 22, 237, 15, 237, 46, 15, 214, 237, 0, ), themeLight: fmt.Sprintf( From 8f420118a6e58b3b6d666afffb7ed0620de1dc97 Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Thu, 30 Jun 2016 14:33:05 +0600 Subject: [PATCH 7/9] switch to colorgful & barely, add upload status --- archive.go | 62 +++++++++++-- bytes_stringer.go | 33 +++++++ callback_writer.go | 9 ++ file.go | 6 ++ format.go | 18 ++-- lock.go | 24 ++--- log.go | 88 ++++++++++++------ main.go | 81 ++++++++-------- remote_execution.go | 28 +++++- status_bar.go | 84 ----------------- style.go | 219 -------------------------------------------- themes.go | 101 +++++++++++++------- 12 files changed, 321 insertions(+), 432 deletions(-) create mode 100644 bytes_stringer.go create mode 100644 callback_writer.go create mode 100644 file.go delete mode 100644 status_bar.go delete mode 100644 style.go diff --git a/archive.go b/archive.go index 20f5a85..b0665fa 100644 --- a/archive.go +++ b/archive.go @@ -71,7 +71,7 @@ func startArchiveReceivers( func archiveFilesToWriter( target io.WriteCloser, - files []string, + files []file, preserveUID, preserveGID bool, ) error { workDir, err := os.Getwd() @@ -82,17 +82,55 @@ func archiveFilesToWriter( ) } + status := &struct { + Phase string + Total int + Fails int + Success int + Written bytesStringer + Bytes bytesStringer + }{ + Phase: "upload", + Total: len(files), + } + + setStatus(status) + + for _, file := range files { + status.Bytes.Amount += file.size + } + archive := tar.NewWriter(target) - for fileIndex, fileName := range files { + stream := io.MultiWriter(archive, callbackWriter( + func(data []byte) (int, error) { + status.Written.Amount += len(data) + + err = bar.Render(os.Stderr) + if err != nil { + errorf( + `%s`, + hierr.Errorf( + err, + `can't render status bar`, + ), + ) + } + + return len(data), nil + }, + )) + + for fileIndex, file := range files { infof( "%5d/%d sending file: '%s'", fileIndex+1, len(files), - fileName, + file.path, ) err = writeFileToArchive( - fileName, + file.path, + stream, archive, workDir, preserveUID, @@ -102,9 +140,11 @@ func archiveFilesToWriter( return hierr.Errorf( err, `can't write file to archive: '%s'`, - fileName, + file.path, ) } + + status.Success++ } tracef("closing archive stream, %d files sent", len(files)) @@ -130,6 +170,7 @@ func archiveFilesToWriter( func writeFileToArchive( fileName string, + stream io.Writer, archive *tar.Writer, workDir string, preserveUID, preserveGID bool, @@ -208,7 +249,7 @@ func writeFileToArchive( ) } - _, err = io.Copy(archive, fileToArchive) + _, err = io.Copy(stream, fileToArchive) if err != nil { return hierr.Errorf( err, @@ -220,8 +261,8 @@ func writeFileToArchive( return nil } -func getFilesList(relative bool, sources ...string) ([]string, error) { - files := []string{} +func getFilesList(relative bool, sources ...string) ([]file, error) { + files := []file{} for _, source := range sources { err := filepath.Walk( @@ -246,7 +287,10 @@ func getFilesList(relative bool, sources ...string) ([]string, error) { } } - files = append(files, path) + files = append(files, file{ + path: path, + size: int(info.Size()), + }) return nil }, diff --git a/bytes_stringer.go b/bytes_stringer.go new file mode 100644 index 0000000..59188c6 --- /dev/null +++ b/bytes_stringer.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" +) + +type bytesStringer struct { + Amount int +} + +func (stringer bytesStringer) String() string { + amount := float64(stringer.Amount) + + suffixes := map[string]string{ + "b": "KiB", + "KiB": "MiB", + "MiB": "GiB", + "GiB": "TiB", + } + + suffix := "b" + for amount >= 1024 { + if newSuffix, ok := suffixes[suffix]; ok { + suffix = newSuffix + } else { + break + } + + amount /= 1024 + } + + return fmt.Sprintf("%.2f%s", amount, suffix) +} diff --git a/callback_writer.go b/callback_writer.go new file mode 100644 index 0000000..08980e6 --- /dev/null +++ b/callback_writer.go @@ -0,0 +1,9 @@ +package main + +type ( + callbackWriter func([]byte) (int, error) +) + +func (writer callbackWriter) Write(data []byte) (int, error) { + return writer(data) +} diff --git a/file.go b/file.go new file mode 100644 index 0000000..0afca78 --- /dev/null +++ b/file.go @@ -0,0 +1,6 @@ +package main + +type file struct { + path string + size int +} diff --git a/format.go b/format.go index da996f1..1d2408a 100644 --- a/format.go +++ b/format.go @@ -17,16 +17,22 @@ const ( func parseOutputFormat( args map[string]interface{}, -) (outputFormat, bool, bool) { +) outputFormat { - format := outputFormatText + formatType := outputFormatText if args["--json"].(bool) { - format = outputFormatJSON + formatType = outputFormatJSON } - isOutputOnTTY := terminal.IsTerminal(int(os.Stderr.Fd())) + return formatType +} + +func isOutputOnTTY() bool { + return terminal.IsTerminal(int(os.Stderr.Fd())) +} - isColorEnabled := isOutputOnTTY +func isColorEnabled(args map[string]interface{}, hasTTY bool) bool { + isColorEnabled := hasTTY if format != outputFormatText { isColorEnabled = false @@ -36,5 +42,5 @@ func parseOutputFormat( isColorEnabled = false } - return format, isOutputOnTTY, isColorEnabled + return isColorEnabled } diff --git a/lock.go b/lock.go index e1f1dc2..f427ef2 100644 --- a/lock.go +++ b/lock.go @@ -33,17 +33,17 @@ func acquireDistributedLock( nodeAddMutex = &sync.Mutex{} ) - report := &struct { - Locking bool - Nodes int64 + status := &struct { + Phase string + Total int64 Fails int64 Success int64 }{ - Locking: true, - Nodes: int64(len(addresses)), + Phase: `lock`, + Total: int64(len(addresses)), } - status.Set(report) + setStatus(status) for _, nodeAddress := range addresses { go func(nodeAddress address) { @@ -52,8 +52,8 @@ func acquireDistributedLock( node, err := connectToNode(cluster, runnerFactory, nodeAddress) if err != nil { - atomic.AddInt64(&report.Fails, 1) - atomic.AddInt64(&report.Nodes, -1) + atomic.AddInt64(&status.Fails, 1) + atomic.AddInt64(&status.Total, -1) if noConnFail { failed = true @@ -78,7 +78,7 @@ func acquireDistributedLock( if failed { textStatus = "failed" } else { - atomic.AddInt64(&report.Success, 1) + atomic.AddInt64(&status.Success, 1) nodeAddMutex.Lock() defer nodeAddMutex.Unlock() @@ -88,9 +88,9 @@ func acquireDistributedLock( debugf( `%4d/%d (%d failed) connection %s: %s`, - report.Success, - report.Nodes, - report.Fails, + status.Success, + status.Total, + status.Fails, textStatus, nodeAddress, ) diff --git a/log.go b/log.go index 9b6a871..c5413a1 100644 --- a/log.go +++ b/log.go @@ -1,16 +1,20 @@ package main import ( + "bytes" "fmt" "os" "strings" - "github.com/fatih/color" - "github.com/kovetskiy/lorg" + "github.com/reconquest/loreley" "github.com/seletskiy/hierr" ) +var ( + loggerFormattingBasicLength = 0 +) + func setLoggerOutputFormat(logger *lorg.Log, format outputFormat) { if format == outputFormatJSON { logger.SetOutput(&jsonOutputWriter{ @@ -36,29 +40,26 @@ func setLoggerVerbosity(level verbosity, logger *lorg.Log) { } } -func setLoggerStyle(logger *lorg.Log, style *lorg.Format) { +func setLoggerStyle(logger *lorg.Log, style lorg.Formatter) { logger.SetFormat(style) -} -func colorize( - attributes ...color.Attribute, -) string { - if !isColorEnabled { - return "" - } + buffer := &bytes.Buffer{} + logger.SetOutput(buffer) - sequence := []string{} - for _, attribute := range attributes { - sequence = append(sequence, fmt.Sprint(attribute)) - } + logger.Debug(``) - return fmt.Sprintf("\x1b[%sm", strings.Join(sequence, ";")) + loggerFormattingBasicLength = len(strings.TrimSuffix( + loreley.TrimStyles(buffer.String()), + "\n", + )) + + logger.SetOutput(os.Stderr) } func tracef(format string, args ...interface{}) { args = serializeErrors(args) - logger.Tracef(format, args...) + logger.Tracef(`%s`, wrapNewLines(format, args...)) drawStatus() } @@ -66,7 +67,7 @@ func tracef(format string, args ...interface{}) { func debugf(format string, args ...interface{}) { args = serializeErrors(args) - logger.Debugf(format, args...) + logger.Debugf(`%s`, wrapNewLines(format, args...)) drawStatus() } @@ -74,7 +75,7 @@ func debugf(format string, args ...interface{}) { func infof(format string, args ...interface{}) { args = serializeErrors(args) - logger.Infof(format, args...) + logger.Infof(`%s`, wrapNewLines(format, args...)) drawStatus() } @@ -86,7 +87,7 @@ func warningf(format string, args ...interface{}) { return } - logger.Warningf(format, args...) + logger.Warningf(`%s`, wrapNewLines(format, args...)) drawStatus() } @@ -94,7 +95,28 @@ func warningf(format string, args ...interface{}) { func errorf(format string, args ...interface{}) { args = serializeErrors(args) - logger.Errorf(format, args...) + logger.Errorf(`%s`, wrapNewLines(format, args...)) +} + +func fatalf(format string, args ...interface{}) { + args = serializeErrors(args) + + logger.Fatalf(`%s`, wrapNewLines(format, args...)) + + exit(1) +} + +func wrapNewLines(format string, values ...interface{}) string { + contents := fmt.Sprintf(format, values...) + contents = strings.TrimSuffix(contents, "\n") + contents = strings.Replace( + contents, + "\n", + "\n"+strings.Repeat(" ", loggerFormattingBasicLength), + -1, + ) + + return contents } func serializeErrors(args []interface{}) []interface{} { @@ -107,8 +129,16 @@ func serializeErrors(args []interface{}) []interface{} { return args } +func setStatus(status interface{}) { + if bar == nil { + return + } + + bar.SetStatus(status) +} + func shouldDrawStatus() bool { - if !isOutputOnTTY { + if bar == nil { return false } @@ -120,10 +150,6 @@ func shouldDrawStatus() bool { return false } - if status == nil { - return false - } - return true } @@ -132,7 +158,15 @@ func drawStatus() { return } - status.Draw(os.Stderr) + err := bar.Render(os.Stderr) + if err != nil { + errorf( + "%s", hierr.Errorf( + err, + `can't draw status bar`, + ), + ) + } } func clearStatus() { @@ -140,7 +174,7 @@ func clearStatus() { return } - status.Clear(os.Stderr) + bar.Clear(os.Stderr) } func serializeError(err error) string { diff --git a/main.go b/main.go index 7c89836..8c04cd8 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "github.com/docopt/docopt-go" "github.com/kovetskiy/lorg" "github.com/mattn/go-shellwords" + "github.com/reconquest/barely" "github.com/seletskiy/hierr" "github.com/theairkit/runcmd" ) @@ -170,7 +171,7 @@ Output format and colors options: * 'stream' = 'stdout' | 'stderr'; * 'node' = | null (if internal output); * 'body' = - --status-format Format for the status bar. + --bar-format Format for the status bar. Full Go template syntax is available with delims of '{' and '}'. Variables available: * .Total - total amount of connected nodes; @@ -215,8 +216,7 @@ Timeout options: ` const ( - defaultSSHPort = 22 - sshPasswordPrompt = "Password: " + defaultSSHPort = 22 // heartbeatTimeoutCoefficient will be multiplied to send timeout and // resulting value will be used as time interval between heartbeats. @@ -227,16 +227,17 @@ const ( defaultLockFile = "/" ) +var ( + sshPasswordPrompt = "Password: " +) + var ( logger = lorg.NewLog() verbose = verbosityNormal format = outputFormatText - pool *threadPool - status *statusBar - - isOutputOnTTY = false - isColorEnabled = false + pool *threadPool + bar *barely.StatusBar ) var ( @@ -244,37 +245,26 @@ var ( ) func main() { - usage, err := formatUsage(string(usage)) - if err != nil { - errorf("%s", hierr.Errorf( - err, - `can't format usage`, - )) - - exit(1) - } - - args, err := docopt.Parse(usage, nil, true, version, true) - if err != nil { - panic(err) - } + args := parseArgs() verbose = parseVerbosity(args) setLoggerVerbosity(verbose, logger) - format, isOutputOnTTY, isColorEnabled = parseOutputFormat(args) + format = parseOutputFormat(args) setLoggerOutputFormat(logger, format) - loggerStyle, err := getLoggerStyle(parseTheme("log", args)) + hasTTY := isOutputOnTTY() + + colorEnabled := isColorEnabled(args, hasTTY) + + loggerStyle, err := getLoggerTheme(parseTheme("log", args), colorEnabled) if err != nil { - errorf("%s", hierr.Errorf( + fatalf("%s", hierr.Errorf( err, `can't use given logger style`, )) - - exit(1) } setLoggerStyle(logger, loggerStyle) @@ -289,7 +279,7 @@ func main() { pool = newThreadPool(poolSize) - statusStyle, err := getStatusBarStyle(parseTheme("status", args)) + barStyle, err := getStatusBarTheme(parseTheme("bar", args), colorEnabled) if err != nil { errorf("%s", hierr.Errorf( err, @@ -297,7 +287,11 @@ func main() { )) } - status = newStatusBar(statusStyle) + if hasTTY { + bar = barely.NewStatusBar(barStyle.Template) + } else { + sshPasswordPrompt = "" + } switch { case args["--upload"].(bool): @@ -311,10 +305,25 @@ func main() { } if err != nil { - errorf("%s", err) + fatalf("%s", err) + } +} - exit(1) +func parseArgs() map[string]interface{} { + usage, err := formatUsage(string(usage)) + if err != nil { + fatalf("%s", hierr.Errorf( + err, + `can't format usage`, + )) } + + args, err := docopt.Parse(usage, nil, true, version, true) + if err != nil { + panic(err) + } + + return args } func formatUsage(template string) (string, error) { @@ -445,7 +454,7 @@ func handleSynchronize(args map[string]interface{}) error { ) var ( - filesList = []string{} + filesList = []file{} err error ) @@ -533,7 +542,7 @@ func handleSynchronize(args map[string]interface{}) error { func upload( args map[string]interface{}, cluster *distributedLock, - filesList []string, + filesList []file, ) error { var ( rootDir, _ = args["--root"].(string) @@ -780,9 +789,7 @@ func generateRunID() string { } func readPassword(prompt string) (string, error) { - if isOutputOnTTY { - fmt.Fprintf(os.Stderr, sshPasswordPrompt) - } + fmt.Fprintf(os.Stderr, sshPasswordPrompt) tty, err := os.Open("/dev/tty") if err != nil { @@ -801,7 +808,7 @@ func readPassword(prompt string) (string, error) { ) } - if isOutputOnTTY { + if sshPasswordPrompt != "" { fmt.Fprintln(os.Stderr) } diff --git a/remote_execution.go b/remote_execution.go index d7b7a8a..b6a8333 100644 --- a/remote_execution.go +++ b/remote_execution.go @@ -34,10 +34,21 @@ func (execution *remoteExecution) wait() error { ) var ( - failures = 0 + status = &struct { + Phase string + Total int + Fails int + Success int + }{ + Phase: `exec`, + Total: len(execution.nodes), + } + exitCodes = map[int]int{} ) + setStatus(status) + for range execution.nodes { result := <-results if result.err != nil { @@ -52,7 +63,14 @@ func (execution *remoteExecution) wait() error { ), ) - failures++ + status.Fails++ + status.Total-- + + tracef( + `%s finished with exit code: '%d'`, + result.node.node.String(), + result.node.exitCode, + ) continue } @@ -63,8 +81,8 @@ func (execution *remoteExecution) wait() error { ) } - if failures > 0 { - if failures == len(execution.nodes) { + if status.Fails > 0 { + if status.Fails == len(execution.nodes) { exitCodesValue := reflect.ValueOf(exitCodes) topError := fmt.Errorf( @@ -89,7 +107,7 @@ func (execution *remoteExecution) wait() error { return hierr.Errorf( executionErrors, `commands are exited with non-zero exit code on %d of %d nodes`, - failures, + status.Fails, len(execution.nodes), ) } diff --git a/status_bar.go b/status_bar.go deleted file mode 100644 index 7ddd950..0000000 --- a/status_bar.go +++ /dev/null @@ -1,84 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - "io" - "strings" - "sync" - "text/template" - - "github.com/seletskiy/hierr" -) - -type statusBar struct { - sync.Locker - - format *template.Template - last string - - data interface{} -} - -func newStatusBar(format *template.Template) *statusBar { - return &statusBar{ - format: format, - } -} - -func (bar *statusBar) Lock() { - if bar.Locker != nil { - bar.Locker.Lock() - } -} - -func (bar *statusBar) Unlock() { - if bar.Locker != nil { - bar.Locker.Unlock() - } -} - -func (bar *statusBar) Set(data interface{}) { - bar.Lock() - defer bar.Unlock() - - bar.data = data -} - -func (bar *statusBar) SetLock(lock sync.Locker) { - bar.Locker = lock -} - -func (bar *statusBar) Clear(writer io.Writer) { - bar.Lock() - defer bar.Unlock() - - fmt.Fprint(writer, strings.Repeat(" ", len(bar.last))+"\r") - - bar.last = "" -} - -func (bar *statusBar) Draw(writer io.Writer) { - bar.Lock() - defer bar.Unlock() - - buffer := &bytes.Buffer{} - - if bar.data == nil { - return - } - - err := bar.format.Execute(buffer, bar.data) - if err != nil { - errorf("%s", hierr.Errorf( - err, - `error during rendering status bar`, - )) - } - - fmt.Fprintf(buffer, "\r") - - bar.last = trimStyleCodes(buffer.String()) - - io.Copy(writer, buffer) -} diff --git a/style.go b/style.go deleted file mode 100644 index 5508be9..0000000 --- a/style.go +++ /dev/null @@ -1,219 +0,0 @@ -package main - -import ( - "fmt" - "regexp" - "strings" - "text/template" - - "github.com/kovetskiy/lorg" - "github.com/seletskiy/hierr" - "github.com/seletskiy/tplutil" -) - -const ( - styleEscape = "\x1b" - - styleAttrForeground = "3" - styleAttrBackground = "4" - styleAttrDefault = "9" - - styleAttrReset = "0" - styleAttrReverse = "7" - styleAttrNoReverse = "27" - styleAttrBold = "1" - styleAttrNoBold = "22" - - styleAttrForeground256 = "38;5" - styleAttrBackground256 = "48;5" - - styleResetBlock = "{reset}" -) - -var ( - styleCodeRegexp = regexp.MustCompile(styleEscape + `[^m]+`) -) - -func getResetStyleSequence() string { - return getStyleSequence(styleAttrReset) -} - -func getBackgroundStyleSequence(color int) string { - if color == 0 { - return getStyleSequence( - styleAttrBackground + styleAttrDefault, - ) - } - - return getStyleSequence(styleAttrBackground256, fmt.Sprint(color)) -} - -func getForegroundStyleSequence(color int) string { - if color == 0 { - return getStyleSequence( - styleAttrForeground + styleAttrDefault, - ) - } - - return getStyleSequence(styleAttrForeground256, fmt.Sprint(color)) -} - -func getBoldStyleSequence() string { - return getStyleSequence(styleAttrBold) -} - -func getNoBoldStyleSequence() string { - return getStyleSequence(styleAttrNoBold) -} - -func getReverseStyleSequence() string { - return getStyleSequence(styleAttrReverse) -} - -func getNoReverseStyleSequence() string { - return getStyleSequence(styleAttrNoReverse) -} - -func getStyleSequence(attr ...string) string { - if !isColorEnabled { - return "" - } - - return fmt.Sprintf("%s[%sm", styleEscape, strings.Join(attr, `;`)) -} - -func getLogPlaceholder(placeholder string) string { - return fmt.Sprintf("${%s}", placeholder) -} - -func getLogLevelStylePlaceholder( - level string, - styleString string, -) (string, error) { - style, err := compileStyle(styleString) - if err != nil { - return "", hierr.Errorf( - err, - `can't compile specified style string: '%s'`, - styleString, - ) - } - - styleCode, err := tplutil.ExecuteToString(style, nil) - if err != nil { - return "", hierr.Errorf( - err, - `can't execute specified style string: '%s'`, - styleString, - ) - } - - return fmt.Sprintf( - "${color:%s:%s}", - level, - strings.Replace(styleCode, ":", "\\:", -1), - ), nil -} - -func executeLogColorPlaceholder(level lorg.Level, value string) string { - var ( - parts = strings.SplitN(value, ":", 2) - targetLevel = parts[0] - style = "" - ) - - if len(parts) > 1 { - style = parts[1] - } - - if targetLevel == strings.ToLower(level.String()) { - return style - } - - return "" -} - -func compileStyle(style string) (*template.Template, error) { - functions := map[string]interface{}{ - "bg": getBackgroundStyleSequence, - "fg": getForegroundStyleSequence, - "bold": getBoldStyleSequence, - "nobold": getNoBoldStyleSequence, - "reverse": getReverseStyleSequence, - "noreverse": getNoReverseStyleSequence, - "reset": getResetStyleSequence, - - "log": getLogPlaceholder, - "level": getLogLevelStylePlaceholder, - } - - return template.New("style").Delims("{", "}").Funcs(functions).Parse( - style, - ) -} - -func trimStyleCodes(input string) string { - return styleCodeRegexp.ReplaceAllLiteralString(input, ``) -} - -func getStatusBarStyle(theme string) (*template.Template, error) { - statusStyle := getStatusBarTheme(theme) + styleResetBlock - - style, err := compileStyle(statusStyle) - if err != nil { - return nil, hierr.Errorf( - err, - `can't compile status bar style template`, - ) - } - - tracef("using status bar style: '%s'", statusStyle) - - return style, nil -} - -func getLoggerStyle(theme string) (*lorg.Format, error) { - logStyle := getLogTheme(theme) + styleResetBlock - - style, err := compileStyle(logStyle) - if err != nil { - return nil, hierr.Errorf( - err, - `can't compile log style template`, - ) - } - - styleString, err := tplutil.ExecuteToString(style, nil) - if err != nil { - return nil, hierr.Errorf( - err, - `can't execute log style template`, - ) - } - - tracef("using log style: '%#s'", logStyle) - - lorgFormat := lorg.NewFormat(styleString) - lorgFormat.SetPlaceholder("color", executeLogColorPlaceholder) - - return lorgFormat, nil -} - -func parseTheme(target string, args map[string]interface{}) string { - var ( - theme = args["--"+target+"-format"].(string) - light = args["--light"].(bool) - dark = args["--dark"].(bool) - ) - - switch { - case light: - return themeLight - - case dark: - return themeLight - - default: - return theme - } -} diff --git a/themes.go b/themes.go index ca4bcbc..872cd7f 100644 --- a/themes.go +++ b/themes.go @@ -2,6 +2,10 @@ package main import ( "fmt" + + "github.com/kovetskiy/lorg" + "github.com/reconquest/colorgful" + "github.com/reconquest/loreley" ) const ( @@ -10,60 +14,91 @@ const ( ) var ( - statusBarThemeTemplate = `{" "}{bg %d}{fg %d}{" "}` + + statusBarThemeTemplate = `{bg %d}{fg %d}` + `{bold}` + - `{if .Locking}{bg %d}LOCK{end}` + - `{nobold}{" "}` + - `{fg %d}{reverse}{noreverse}{fg %d}{bg %d}{" "}` + + `{if eq .Phase "lock"}{bg %d} LOCK{end}` + + `{if eq .Phase "exec"}{bg %d} EXEC{end}` + + `{if eq .Phase "upload"}{bg %d} UPLOAD{end}` + + `{nobold} ` + + `{from "" %d} ` + `{fg %d}{bold}{printf "%%4d" .Success}{nobold}{fg %d}` + - `/{printf "%%4d" .Total}{" "}` + - `{if .Failures}{fg %d}(failed: {.Failures}){end}{" "}{fg %d}{bg %d}` + `/{printf "%%4d" .Total} ` + + `{if .Fails}{fg %d}✗ {.Fails}{end} ` + + `{from "" %d}` + + `{if eq .Phase "upload"}{fg %d} ` + + `{printf "%%9s/%%s" .Written .Bytes} ` + + `{end}` statusBarThemes = map[string]string{ themeDark: fmt.Sprintf( statusBarThemeTemplate, - 99, 7, 22, 237, 15, 237, 46, 15, 214, 237, 0, + 99, 7, 22, 1, 25, 237, 46, 15, 214, 16, 140, ), themeLight: fmt.Sprintf( statusBarThemeTemplate, - 99, 7, 64, 254, 16, 254, 106, 16, 9, 254, 0, + 99, 7, 22, 1, 64, 254, 106, 16, 9, -1, 140, ), } - logThemeTemplate = `{level "error" "{fg %d}"}` + - `{level "warning" "{fg %d}{bg %d}"}` + - `{level "debug" "{fg %d}"}` + - `{level "trace" "{fg %d}"}` + - `* {log "time"} ` + - `{level "error" "{bg %d}{bold}"}{log "level:[%%s]:right:true"}` + - `{level "error" "{bg %d}"}{nobold} %%s` + logFormat = `${time} ${level:[%s]:right:true} %s` +) - logThemes = map[string]string{ - themeDark: fmt.Sprintf( - logThemeTemplate, - 1, 11, 0, 250, 243, 52, 0, - ), +func getLoggerTheme( + theme string, + isColorEnabled bool, +) (lorg.Formatter, error) { + colorgful.NoColors = !isColorEnabled - themeLight: fmt.Sprintf( - logThemeTemplate, - 199, 172, 230, 240, 248, 220, 0, - ), + switch theme { + case "dark": + return colorgful.ApplyDefaultTheme( + logFormat, + colorgful.Dark, + ) + case "light": + return colorgful.ApplyDefaultTheme( + logFormat, + colorgful.Light, + ) + default: + return colorgful.Format(theme) } -) +} -func getStatusBarTheme(theme string) string { +func getStatusBarTheme( + theme string, + isColorEnabled bool, +) (*loreley.Style, error) { if format, ok := statusBarThemes[theme]; ok { - return format + theme = format } - return theme + style, err := loreley.CompileWithReset(theme, nil) + if err != nil { + return nil, err + } + + style.NoColors = !isColorEnabled + + return style, nil } -func getLogTheme(theme string) string { - if format, ok := logThemes[theme]; ok { - return format - } +func parseTheme(target string, args map[string]interface{}) string { + var ( + theme = args["--"+target+"-format"].(string) + light = args["--light"].(bool) + dark = args["--dark"].(bool) + ) - return theme + switch { + case light: + return themeLight + + case dark: + return themeDark + + default: + return theme + } } From cd9a0d70ff71272e91d4649a275d4bc887025cee Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Thu, 30 Jun 2016 17:02:28 +0600 Subject: [PATCH 8/9] migrate to loreley TTY detection --- format.go | 25 ++++++++++--------------- main.go | 41 ++++++++++++++++------------------------- themes.go | 14 ++------------ 3 files changed, 28 insertions(+), 52 deletions(-) diff --git a/format.go b/format.go index 1d2408a..de6107d 100644 --- a/format.go +++ b/format.go @@ -1,9 +1,7 @@ package main import ( - "os" - - "golang.org/x/crypto/ssh/terminal" + "github.com/reconquest/loreley" ) type ( @@ -27,20 +25,17 @@ func parseOutputFormat( return formatType } -func isOutputOnTTY() bool { - return terminal.IsTerminal(int(os.Stderr.Fd())) -} - -func isColorEnabled(args map[string]interface{}, hasTTY bool) bool { - isColorEnabled := hasTTY +func parseColorMode(args map[string]interface{}) loreley.ColorizeMode { + switch args["--color"].(string) { + case "always": + return loreley.ColorizeAlways - if format != outputFormatText { - isColorEnabled = false - } + case "auto": + return loreley.ColorizeOnTTY - if args["--no-colors"].(bool) { - isColorEnabled = false + case "never": + return loreley.ColorizeNever } - return isColorEnabled + return loreley.ColorizeNever } diff --git a/main.go b/main.go index 8c04cd8..bf5a33d 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ import ( "github.com/kovetskiy/lorg" "github.com/mattn/go-shellwords" "github.com/reconquest/barely" + "github.com/reconquest/loreley" "github.com/seletskiy/hierr" "github.com/theairkit/runcmd" ) @@ -173,33 +174,24 @@ Output format and colors options: * 'body' = --bar-format Format for the status bar. Full Go template syntax is available with delims - of '{' and '}'. Variables available: - * .Total - total amount of connected nodes; - * .Success - number of nodes that successfully done - phase; - * .Failures - number of failed nodes; - Additional functions are available: - * bg - set background color to specified; - * 0 can be used for default bg; - * fg - set foreground color to specified; - * 0 can be used for default fg; - * bold/nobold - set or reset bold mode; - * reverse/noreverse - set or reset reverse mode; - * reset - completely resets mode; + of '{' and '}'. + See https://github.com/reconquest/barely for more + info. For example, run orgalorg with '-vv' flag. Two embedded themes are available by their names: ` + themeDark + ` and ` + themeLight + ` [default: ` + themeDark + `] --log-format Format for the logs. - Same, as above, with additional functions: - * log - inserts lorg placeholder - specification; - * level - insert in place specified - format if log level matches specified level. + See https://github.com/reconquest/colorgful for more + info. [default: ` + themeDark + `] --dark Set all available formats to predefined dark theme. --light Set all available formats to predefined light theme. - --no-colors Do not use colors. + --color Specify, whether to use colors: + * never - disable colors; + * auto - use colors only when TTY presents. + * always - always use colorized output. + [default: auto] Timeout options: --conn-timeout Remote host connection timeout in milliseconds. @@ -255,11 +247,9 @@ func main() { setLoggerOutputFormat(logger, format) - hasTTY := isOutputOnTTY() + loreley.Colorize = parseColorMode(args) - colorEnabled := isColorEnabled(args, hasTTY) - - loggerStyle, err := getLoggerTheme(parseTheme("log", args), colorEnabled) + loggerStyle, err := getLoggerTheme(parseTheme("log", args)) if err != nil { fatalf("%s", hierr.Errorf( err, @@ -279,7 +269,7 @@ func main() { pool = newThreadPool(poolSize) - barStyle, err := getStatusBarTheme(parseTheme("bar", args), colorEnabled) + barStyle, err := getStatusBarTheme(parseTheme("bar", args)) if err != nil { errorf("%s", hierr.Errorf( err, @@ -287,9 +277,10 @@ func main() { )) } - if hasTTY { + if loreley.HasTTY(int(os.Stderr.Fd())) { bar = barely.NewStatusBar(barStyle.Template) } else { + bar = nil sshPasswordPrompt = "" } diff --git a/themes.go b/themes.go index 872cd7f..36bb615 100644 --- a/themes.go +++ b/themes.go @@ -44,12 +44,7 @@ var ( logFormat = `${time} ${level:[%s]:right:true} %s` ) -func getLoggerTheme( - theme string, - isColorEnabled bool, -) (lorg.Formatter, error) { - colorgful.NoColors = !isColorEnabled - +func getLoggerTheme(theme string) (lorg.Formatter, error) { switch theme { case "dark": return colorgful.ApplyDefaultTheme( @@ -66,10 +61,7 @@ func getLoggerTheme( } } -func getStatusBarTheme( - theme string, - isColorEnabled bool, -) (*loreley.Style, error) { +func getStatusBarTheme(theme string) (*loreley.Style, error) { if format, ok := statusBarThemes[theme]; ok { theme = format } @@ -79,8 +71,6 @@ func getStatusBarTheme( return nil, err } - style.NoColors = !isColorEnabled - return style, nil } From 450e31436bff0e6ded0dbd1550df8a5c2178803f Mon Sep 17 00:00:00 2001 From: Stanislav Seletskiy Date: Mon, 11 Jul 2016 13:53:32 +0600 Subject: [PATCH 9/9] fix typos --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2387046..dbaa6a9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # orgalorg -Ultimate parallel cluster file synchronization tool and SSH commend +Ultimate parallel cluster file synchronization tool and SSH commands executioner. ![demo](https://raw.githubusercontent.com/reconquest/orgalorg/status-line/demo.gif) @@ -22,8 +22,8 @@ executioner. * User-friendly progress indication. -* Either strict or loose modes of failover to be sure, that either everything - will fail on any error, or everything will try to complete no mather of what. +* Both strict or loose modes of failover to be sure that everything will either + fail on any error or try to complete, no matter of what. * Interactive password authentication as well as SSH public key authentication. @@ -109,13 +109,13 @@ arbitrary SSH commands. orgalorg works through SSH & tar, so no unexpected protocol errors will arise. In default mode of operation (lately referred as sync mode) orgalorg will -perform following steps in order: +perform steps in the following order: -1. Acquire global cluster lock (more detailed info above). +1. Acquire global cluster lock (check more detailed info above). 2. Create, upload and extract specified files in streaming mode to the specified nodes into temporary run directory. 3. Start synchronization tool on each node, that should relocate files from - temporary run directory to the actual destination. + temporary run directory to the destination. So, orgalorg expected to work with third-party synchronization tool, that will do actual files relocation and can be quite intricate, **but orgalorg can