mirror of
https://github.com/zrepl/zrepl.git
synced 2024-12-22 15:11:16 +01:00
cli: add 'test placeholder' subcommand for placeholder debugging
This commit is contained in:
parent
ca6d5d3bb5
commit
2db3977408
@ -42,6 +42,7 @@ func init() {
|
||||
type Subcommand struct {
|
||||
Use string
|
||||
Short string
|
||||
Example string
|
||||
NoRequireConfig bool
|
||||
Run func(subcommand *Subcommand, args []string) error
|
||||
SetupFlags func(f *pflag.FlagSet)
|
||||
@ -94,6 +95,7 @@ func addSubcommandToCobraCmd(c *cobra.Command, s *Subcommand) {
|
||||
cmd := cobra.Command{
|
||||
Use: s.Use,
|
||||
Short: s.Short,
|
||||
Example: s.Example,
|
||||
}
|
||||
if s.SetupSubcommands == nil {
|
||||
cmd.Run = s.run
|
||||
@ -113,4 +115,4 @@ func Run() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/zrepl/zrepl/cli"
|
||||
"github.com/zrepl/zrepl/config"
|
||||
@ -12,7 +13,7 @@ import (
|
||||
var TestCmd = &cli.Subcommand {
|
||||
Use: "test",
|
||||
SetupSubcommands: func() []*cli.Subcommand {
|
||||
return []*cli.Subcommand{testFilter}
|
||||
return []*cli.Subcommand{testFilter, testPlaceholder}
|
||||
},
|
||||
}
|
||||
|
||||
@ -105,4 +106,86 @@ func runTestFilterCmd(subcommand *cli.Subcommand, args []string) error {
|
||||
return fmt.Errorf("filter errors occurred")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var testPlaceholderArgs struct {
|
||||
action string
|
||||
ds string
|
||||
plv string
|
||||
all bool
|
||||
}
|
||||
|
||||
var testPlaceholder = &cli.Subcommand{
|
||||
Use: "placeholder [--all | --dataset DATASET --action [compute | check [--placeholder PROP_VALUE]]]",
|
||||
Short: fmt.Sprintf("list received placeholder filesystems & compute the ZFS property %q", zfs.ZREPL_PLACEHOLDER_PROPERTY_NAME),
|
||||
Example: `
|
||||
placeholder --all
|
||||
placeholder --dataset path/to/sink/clientident/fs --action compute
|
||||
placeholder --dataset path/to/sink/clientident/fs --action check --placeholder 1671a61be44d32d1f3f047c5f124b06f98f54143d82900545ee529165060b859`,
|
||||
NoRequireConfig: true,
|
||||
SetupFlags: func(f *pflag.FlagSet) {
|
||||
f.StringVar(&testPlaceholderArgs.action, "action", "", "check | compute")
|
||||
f.StringVar(&testPlaceholderArgs.ds, "dataset", "", "dataset path (not required to exist)")
|
||||
f.StringVar(&testPlaceholderArgs.plv, "placeholder", "", "existing placeholder value to check against DATASET path")
|
||||
f.BoolVar(&testPlaceholderArgs.all, "all", false, "list tab-separated placeholder status of all filesystems")
|
||||
},
|
||||
Run: runTestPlaceholder,
|
||||
}
|
||||
|
||||
func runTestPlaceholder(subcommand *cli.Subcommand, args []string) error {
|
||||
|
||||
// all actions first
|
||||
if testPlaceholderArgs.all {
|
||||
out, err := zfs.ZFSList([]string{"name", zfs.ZREPL_PLACEHOLDER_PROPERTY_NAME})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not list ZFS filesystems")
|
||||
}
|
||||
fmt.Printf("IS_PLACEHOLDER\tDATASET\tPROPVALUE\tCOMPUTED\n")
|
||||
for _, row := range out {
|
||||
dp, err := zfs.NewDatasetPath(row[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
computedProp := zfs.PlaceholderPropertyValue(dp)
|
||||
is := "yes"
|
||||
if computedProp != row[1] {
|
||||
is = "no"
|
||||
}
|
||||
fmt.Printf("%s\t%s\t%q\t%q\n", is, dp.ToString(), row[1], computedProp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// other actions
|
||||
|
||||
dp, err := zfs.NewDatasetPath(testPlaceholderArgs.ds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
computedProp := zfs.PlaceholderPropertyValue(dp)
|
||||
|
||||
switch testPlaceholderArgs.action {
|
||||
case "check":
|
||||
var isPlaceholder bool
|
||||
if testPlaceholderArgs.plv != "" {
|
||||
isPlaceholder = computedProp == testPlaceholderArgs.plv
|
||||
} else {
|
||||
isPlaceholder, err = zfs.ZFSIsPlaceholderFilesystem(dp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if isPlaceholder {
|
||||
fmt.Printf("%s is placeholder\n", dp.ToString())
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("%s is not a placeholder", dp.ToString())
|
||||
}
|
||||
case "compute":
|
||||
fmt.Printf("%s\n", computedProp)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown --action %q", testPlaceholderArgs.action)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user