From 598072b158db24a68a238a980e84e24742cea4f7 Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Fri, 18 Sep 2020 20:52:59 +0800 Subject: [PATCH 1/2] cmd: extend decode cmd to print any field Signed-off-by: Neil Shen --- cmd/cmd.go | 6 +++-- cmd/{validate.go => debug.go} | 49 +++++++++++++++++++++++------------ main.go | 5 +++- tests/br_other/run.sh | 11 +++++--- 4 files changed, 48 insertions(+), 23 deletions(-) rename cmd/{validate.go => debug.go} (88%) diff --git a/cmd/cmd.go b/cmd/cmd.go index a1fc3cf4d..5c58d5627 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -4,6 +4,7 @@ package cmd import ( "context" + "fmt" "os" "path/filepath" "sync" @@ -70,7 +71,7 @@ func AddFlags(cmd *cobra.Command) { _ = cmd.PersistentFlags().MarkHidden(FlagSlowLogFile) } -// Init ... +// Init initializes BR cli. func Init(cmd *cobra.Command) (err error) { initOnce.Do(func() { // Initialize the logger. @@ -95,7 +96,8 @@ func Init(cmd *cobra.Command) (err error) { if len(conf.File.Filename) != 0 { atomic.StoreUint64(&hasLogFile, 1) summary.InitCollector(true) - cmd.Printf("Detail BR log in %s\n", conf.File.Filename) + // cmd.PrintErr prints to stderr, but PrintErrf prints to stdout. + cmd.PrintErr(fmt.Sprintf("Detail BR log in %s \n", conf.File.Filename)) } lg, p, e := log.InitLogger(conf) if e != nil { diff --git a/cmd/validate.go b/cmd/debug.go similarity index 88% rename from cmd/validate.go rename to cmd/debug.go index 638ca0502..2db9ce331 100644 --- a/cmd/validate.go +++ b/cmd/debug.go @@ -8,7 +8,8 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "fmt" + "path" + "reflect" "github.com/gogo/protobuf/proto" "github.com/pingcap/errors" @@ -26,10 +27,10 @@ import ( "github.com/pingcap/br/pkg/utils" ) -// NewValidateCommand return a debug subcommand. -func NewValidateCommand() *cobra.Command { +// NewDebugCommand return a debug subcommand. +func NewDebugCommand() *cobra.Command { meta := &cobra.Command{ - Use: "validate ", + Use: "debug ", Short: "commands to check/debug backup data", SilenceUsage: false, PersistentPreRunE: func(c *cobra.Command, args []string) error { @@ -40,6 +41,8 @@ func NewValidateCommand() *cobra.Command { task.LogArguments(c) return nil }, + // To be compatible with older BR. + Aliases: []string{"validate"}, } meta.AddCommand(newCheckSumCommand()) meta.AddCommand(newBackupMetaCommand()) @@ -247,26 +250,38 @@ func decodeBackupMetaCommand() *cobra.Command { return err } - backupMetaJSON, err := json.Marshal(backupMeta) + fieldName, err := cmd.Flags().GetString("field") if err != nil { + // No field flag, write backupmeta to external storage in JSON format. + backupMetaJSON, err := json.Marshal(backupMeta) + if err != nil { + return errors.Trace(err) + } + err = s.Write(ctx, utils.MetaJSONFile, backupMetaJSON) + if err == nil { + cmd.Printf("backupmeta decoded at %s\n", path.Join(cfg.Storage, utils.MetaJSONFile)) + } return errors.Trace(err) } - err = s.Write(ctx, utils.MetaJSONFile, backupMetaJSON) - if err != nil { - return errors.Trace(err) + switch fieldName { + // To be compatible with older BR. + case "start-version": + fieldName = "StartVersion" + case "end-version": + fieldName = "EndVersion" } - field, err := cmd.Flags().GetString("field") - if err != nil { - log.Error("get field flag failed", zap.Error(err)) - return err + _, found := reflect.TypeOf(*backupMeta).FieldByName(fieldName) + if !found { + cmd.Printf("field '%s' not found\n", fieldName) + return nil } - switch field { - case "start-version": - fmt.Println(backupMeta.StartVersion) - case "end-version": - fmt.Println(backupMeta.EndVersion) + field := reflect.ValueOf(*backupMeta).FieldByName(fieldName) + if !field.CanInterface() { + cmd.Printf("field '%s' can not print\n", fieldName) + } else { + cmd.Printf("%v\n", field.Interface()) } return nil }, diff --git a/main.go b/main.go index 8a42f4983..895da9a7b 100644 --- a/main.go +++ b/main.go @@ -49,10 +49,13 @@ func main() { cmd.AddFlags(rootCmd) cmd.SetDefaultContext(ctx) rootCmd.AddCommand( - cmd.NewValidateCommand(), + cmd.NewDebugCommand(), cmd.NewBackupCommand(), cmd.NewRestoreCommand(), ) + // Ouputs cmd.Print to stdout. + rootCmd.SetOut(os.Stdout) + rootCmd.SetArgs(os.Args[1:]) if err := rootCmd.Execute(); err != nil { os.Exit(1) diff --git a/tests/br_other/run.sh b/tests/br_other/run.sh index 7d968610e..c0abdd667 100644 --- a/tests/br_other/run.sh +++ b/tests/br_other/run.sh @@ -33,6 +33,12 @@ done echo "backup start..." run_br --pd $PD_ADDR backup full -s "local://$TEST_DIR/$DB" --ratelimit 5 --concurrency 4 +# Test debug decode +run_br -s "local://$TEST_DIR/$DB" debug decode --field "Schemas" +run_br -s "local://$TEST_DIR/$DB" debug decode --field "EndVersion" +# Ensure compatibility +run_br -s "local://$TEST_DIR/$DB" validate decode --field "end-version" + # Test validate backupmeta run_br validate backupmeta -s "local://$TEST_DIR/$DB" run_br validate backupmeta -s "local://$TEST_DIR/$DB" --offset 100 @@ -62,7 +68,6 @@ run_br --pd $PD_ADDR backup full -s "local://$TEST_DIR/$DB/lock" --remove-schedu # record last backup pid _pid=$! - # give the former backup some time to write down lock file (and initialize signal listener). sleep 1 pkill -10 -P $_pid @@ -93,10 +98,10 @@ else exit 1 fi -# make sure we won't stuck in non-scheduler state, even we send a SIGTERM to it. +# make sure we won't stuck in non-scheduler state, even we send a SIGTERM to it. # give enough time to BR so it can gracefully stop. sleep 10 -! curl http://$PD_ADDR/pd/api/v1/config/schedule | grep '"disable": true' +! curl http://$PD_ADDR/pd/api/v1/config/schedule | grep '"disable": true' run_sql "DROP DATABASE $DB;" From 268ea4e4ce07d91b22ca9848d859af1c5f6c787b Mon Sep 17 00:00:00 2001 From: Neil Shen Date: Tue, 29 Sep 2020 20:16:36 +0800 Subject: [PATCH 2/2] try fix tests Signed-off-by: Neil Shen --- cmd/debug.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cmd/debug.go b/cmd/debug.go index 6a28906b4..12532640f 100644 --- a/cmd/debug.go +++ b/cmd/debug.go @@ -247,25 +247,26 @@ func decodeBackupMetaCommand() *cobra.Command { var cfg task.Config if err := cfg.ParseFromFlags(cmd.Flags()); err != nil { - return err + return errors.Trace(err) } _, s, backupMeta, err := task.ReadBackupMeta(ctx, utils.MetaFile, &cfg) if err != nil { - return err + return errors.Trace(err) } - fieldName, err := cmd.Flags().GetString("field") - if err != nil { + fieldName, _ := cmd.Flags().GetString("field") + if fieldName == "" { // No field flag, write backupmeta to external storage in JSON format. backupMetaJSON, err := json.Marshal(backupMeta) if err != nil { return errors.Trace(err) } err = s.Write(ctx, utils.MetaJSONFile, backupMetaJSON) - if err == nil { - cmd.Printf("backupmeta decoded at %s\n", path.Join(cfg.Storage, utils.MetaJSONFile)) + if err != nil { + return errors.Trace(err) } - return errors.Trace(err) + cmd.Printf("backupmeta decoded at %s\n", path.Join(cfg.Storage, utils.MetaJSONFile)) + return nil } switch fieldName {