From 2ce1e0f8a28b4164a00b6b9374599c4060d4da2b Mon Sep 17 00:00:00 2001 From: Adam Bozanich Date: Tue, 25 Apr 2017 22:57:15 -0700 Subject: [PATCH] cli: cleanup options --- README.md | 27 ++++++++++++++++++++++++--- ephemerald/main.go | 23 +++++++++++++---------- ui/writer.go | 38 ++++++++++++++++++++++++++++++++++---- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index c9bbadd..2656d47 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,11 @@ Ephemerald manages pools of short-lived servers to be used for testing purposes. [![asciicast](https://asciinema.org/a/117629.png)](https://asciinema.org/a/117629) -Ephemerald has [REST API](#api) for accessing server instances from any language and comes with a built-in [go client](net/client.go). See the [examples](_example/) directory for example configurations and client usage. +It has [REST API](#api) for accessing server instances from any language and comes with a built-in [go client](net/client.go). See the [examples](_example/) directory for example configurations and client usage. + +The ephemerald server can run on a remote host; container connection parameters are rewritten so that the client +connects to the right place. This way ephemerald can run on a large server and be used from less powerful +development machines. * [Running](#running) * [Configuration](#building) @@ -38,10 +42,27 @@ Ephemerald has [REST API](#api) for accessing server instances from any language To run the server, supply a configuration file: ```sh -$ ephemerald -f config.json +$ ephemerald -c config.json ``` -Press Ctrl-C to quit the server. +Press Q to quit the server. + +### Flags + + * `--help` print help message. + * `-p ` changes the listen port. Defaults to 6000 + * `--ui stream` will dump the event steam to the console in lieu of a curses-esque UI. + * `--ui none` will not print any UI information (useful with `--log-file /dev/stdout`) + * `--log-file ` write logs to file at `path`. Defaults to `/dev/null` + * `--log-level ` log level. defaults to `info`. Options are `debug`,`info`,`warn`,`error` + +Note: use Ctrl-C to stop the server wen not in `--ui tui` mode (`SIGINT`,`SIGQUIT` always work too) + +For example, to see only log messages (at debug level) use: + +```sh +$ ephememerald --ui none --log-level debug --log-file /dev/stdout -c config.json +``` ## Configuration diff --git a/ephemerald/main.go b/ephemerald/main.go index 88cfd12..16427cc 100644 --- a/ephemerald/main.go +++ b/ephemerald/main.go @@ -20,25 +20,25 @@ import ( ) var ( - listenPort = kingpin.Flag("port", "Listen port").Short('p'). + listenPort = kingpin.Flag("port", "Listen port. Default: "+strconv.Itoa(net.DefaultPort)).Short('p'). Default(strconv.Itoa(net.DefaultPort)). Int() - configFile = kingpin.Flag("config", "config file").Short('f'). + configFile = kingpin.Flag("config", "config file").Short('c'). Required(). File() - logLevel = kingpin.Flag("log-level", "Log level"). + logLevel = kingpin.Flag("log-level", "Log level (debug, info, warn, error). Default: info"). Default("info"). - Enum("debug", "info", "error", "warn") + Enum("debug", "info", "warn", "error") - logFile = kingpin.Flag("log-file", "Log file"). + logFile = kingpin.Flag("log-file", "Log file. Default: /dev/null"). Default("/dev/null"). OpenFile(os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) - useGUI = kingpin.Flag("gui", "terminal gui output"). - Default("true"). - Bool() + uiType = kingpin.Flag("ui", "UI type (tui, stream, or none). Default: tui"). + Default("tui"). + Enum("tui", "stream", "none") ) func main() { @@ -57,10 +57,13 @@ func main() { var appui ui.UI - if *useGUI { + switch *uiType { + case "tui": appui, err = ui.NewTUI(uishutdown) - } else { + case "stream": appui, err = ui.NewIOUI(os.Stdout) + default: + appui = ui.NewNoopUI() } kingpin.FatalIfError(err, "Can't start UI") diff --git a/ui/writer.go b/ui/writer.go index b4fd626..d88d5d7 100644 --- a/ui/writer.go +++ b/ui/writer.go @@ -34,16 +34,46 @@ func (w *ioWriter) deleteContainer(c container) { } func (w *ioWriter) writePool(p pool) { - fmt.Fprintf(w.w, "[POOL] %v %v items: %v ready: %v pending: %v\n", p.name, p.state, p.numItems, p.numReady, p.numPending) + ioPool(p).Print(w.w) } func (w *ioWriter) writeContainer(c container) { - fmt.Fprintf(w.w, "[CONTAINER] %v %v %v %v %v %v\n", c.pname, w.cid(c.id), c.state, c.actionName, c.actionAttempt, c.actionError) + ioContainer(c).Print(w.w) } func (w *ioWriter) stop() { } -func (w *ioWriter) cid(cid string) string { - return cid[0:12] +const ( + ioPoolPrefix = "[POOL] " + ioContainerPrefix = "[CONTAINER] " +) + +type ioPool pool + +func (p ioPool) Print(w io.Writer) { + fmt.Fprint(w, ioPoolPrefix) + fmt.Fprintf(w, "%v %v items: %v ready: %v pending: %v\n", p.name, p.state, p.numItems, p.numReady, p.numPending) +} + +type ioContainer container + +func (c ioContainer) Print(w io.Writer) { + fmt.Fprint(w, ioContainerPrefix) + fmt.Fprintf(w, "%v %v %v", c.pname, c.id[0:12], c.state) + + if c.actionName == "" { + goto done + } + + fmt.Fprintf(w, " %v [%v/%v]", c.actionName, c.actionAttempt, c.actionAttempts) + + if c.actionError == nil { + goto done + } + + fmt.Fprintf(w, " %v", c.actionError) + +done: + fmt.Fprintln(w) }