2020-03-27 20:37:17 +01:00
|
|
|
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)
|
2021-03-23 18:12:20 +01:00
|
|
|
SignalWakeup(job string) error
|
2020-03-27 20:37:17 +01:00
|
|
|
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)
|
|
|
|
|
2021-03-15 01:49:55 +01:00
|
|
|
if !isatty.IsTerminal(os.Stdout.Fd()) && mode != StatusV2ModeDump && mode != StatusV2ModeRaw {
|
|
|
|
dumpmode, err := statusv2Flags.Mode.InputForChoice(StatusV2ModeDump)
|
2020-03-27 20:37:17 +01:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-03-15 01:49:55 +01:00
|
|
|
rawmode, err := statusv2Flags.Mode.InputForChoice(StatusV2ModeRaw)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return errors.Errorf("error: stdout is not a tty, please use --mode %s or --mode %s", dumpmode, rawmode)
|
2020-03-27 20:37:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|