mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 08:23:50 +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 {
|
type Subcommand struct {
|
||||||
Use string
|
Use string
|
||||||
Short string
|
Short string
|
||||||
|
Example string
|
||||||
NoRequireConfig bool
|
NoRequireConfig bool
|
||||||
Run func(subcommand *Subcommand, args []string) error
|
Run func(subcommand *Subcommand, args []string) error
|
||||||
SetupFlags func(f *pflag.FlagSet)
|
SetupFlags func(f *pflag.FlagSet)
|
||||||
@ -94,6 +95,7 @@ func addSubcommandToCobraCmd(c *cobra.Command, s *Subcommand) {
|
|||||||
cmd := cobra.Command{
|
cmd := cobra.Command{
|
||||||
Use: s.Use,
|
Use: s.Use,
|
||||||
Short: s.Short,
|
Short: s.Short,
|
||||||
|
Example: s.Example,
|
||||||
}
|
}
|
||||||
if s.SetupSubcommands == nil {
|
if s.SetupSubcommands == nil {
|
||||||
cmd.Run = s.run
|
cmd.Run = s.run
|
||||||
@ -113,4 +115,4 @@ func Run() {
|
|||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"github.com/zrepl/zrepl/cli"
|
"github.com/zrepl/zrepl/cli"
|
||||||
"github.com/zrepl/zrepl/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
@ -12,7 +13,7 @@ import (
|
|||||||
var TestCmd = &cli.Subcommand {
|
var TestCmd = &cli.Subcommand {
|
||||||
Use: "test",
|
Use: "test",
|
||||||
SetupSubcommands: func() []*cli.Subcommand {
|
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 fmt.Errorf("filter errors occurred")
|
||||||
}
|
}
|
||||||
return nil
|
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