mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 08:23:50 +01:00
a58ce74ed0
Primary goals: - Scrollable output ( fixes #245 ) - Sending job signals from status view - Filtering of output by filesystem Implementation: - original TUI framework: github.com/rivo/tview - but: tview is quasi-unmaintained, didn't support some features - => use fork https://gitlab.com/tslocum/cview - however, don't buy into either too much to avoid lock-in - instead: **port over the existing status UI drawing code and adjust it to produce strings instead of directly drawing into the termbox buffer** Co-authored-by: Calistoc <calistoc@protonmail.com> Co-authored-by: InsanePrawn <insane.prawny@gmail.com> fixes #245 fixes #220
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
package status
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/mattn/go-isatty"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/zrepl/zrepl/cli"
|
|
"github.com/zrepl/zrepl/client/status/client"
|
|
"github.com/zrepl/zrepl/config"
|
|
"github.com/zrepl/zrepl/daemon"
|
|
"github.com/zrepl/zrepl/util/choices"
|
|
)
|
|
|
|
type Client interface {
|
|
Status() (daemon.Status, error)
|
|
StatusRaw() ([]byte, error)
|
|
SignalReplication(job string) error
|
|
SignalSnapshot(job string) error
|
|
SignalReset(job string) error
|
|
}
|
|
|
|
type statusFlags struct {
|
|
Mode choices.Choices
|
|
Job string
|
|
Delay time.Duration
|
|
}
|
|
|
|
var statusv2Flags statusFlags
|
|
|
|
type statusv2Mode int
|
|
|
|
const (
|
|
StatusV2ModeInteractive statusv2Mode = 1 + iota
|
|
StatusV2ModeDump
|
|
StatusV2ModeRaw
|
|
StatusV2ModeLegacy
|
|
)
|
|
|
|
var Subcommand = &cli.Subcommand{
|
|
Use: "status",
|
|
Short: "retrieve & display daemon status information",
|
|
SetupFlags: func(f *pflag.FlagSet) {
|
|
statusv2Flags.Mode.Init(
|
|
"interactive", StatusV2ModeInteractive,
|
|
"dump", StatusV2ModeDump,
|
|
"raw", StatusV2ModeRaw,
|
|
"legacy", StatusV2ModeLegacy,
|
|
)
|
|
statusv2Flags.Mode.SetTypeString("mode")
|
|
statusv2Flags.Mode.SetDefaultValue(StatusV2ModeInteractive)
|
|
f.Var(&statusv2Flags.Mode, "mode", statusv2Flags.Mode.Usage())
|
|
f.StringVar(&statusv2Flags.Job, "job", "", "only show specified job (works in \"dump\" and \"interactive\" mode)")
|
|
f.DurationVarP(&statusv2Flags.Delay, "delay", "d", 1*time.Second, "use -d 3s for 3 seconds delay (minimum delay is 1s)")
|
|
},
|
|
Run: func(ctx context.Context, subcommand *cli.Subcommand, args []string) error {
|
|
return runStatusV2Command(ctx, subcommand.Config(), args)
|
|
},
|
|
}
|
|
|
|
func runStatusV2Command(ctx context.Context, config *config.Config, args []string) error {
|
|
|
|
c, err := client.New("unix", config.Global.Control.SockPath)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "connect to daemon socket at %q", config.Global.Control.SockPath)
|
|
}
|
|
|
|
mode := statusv2Flags.Mode.Value().(statusv2Mode)
|
|
|
|
if !isatty.IsTerminal(os.Stdout.Fd()) && mode != StatusV2ModeDump {
|
|
usemode, err := statusv2Flags.Mode.InputForChoice(StatusV2ModeDump)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return errors.Errorf("error: stdout is not a tty, please use --mode %s", usemode)
|
|
}
|
|
|
|
switch mode {
|
|
case StatusV2ModeInteractive:
|
|
return interactive(c, statusv2Flags)
|
|
case StatusV2ModeDump:
|
|
return dump(c, statusv2Flags.Job)
|
|
case StatusV2ModeRaw:
|
|
return raw(c)
|
|
case StatusV2ModeLegacy:
|
|
return legacy(c, statusv2Flags)
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|