From 85d3e7aa91e493ebd09d37a37a4938b1395f85fc Mon Sep 17 00:00:00 2001 From: "leoyang.yl" Date: Sat, 18 Sep 2021 17:08:37 +0800 Subject: [PATCH] Add downgrade commands --- etcdctl/ctlv3/command/downgrade_command.go | 135 +++++++++++++++++++++ etcdctl/ctlv3/command/printer.go | 10 ++ etcdctl/ctlv3/command/printer_simple.go | 10 ++ etcdctl/ctlv3/ctl.go | 1 + 4 files changed, 156 insertions(+) create mode 100644 etcdctl/ctlv3/command/downgrade_command.go diff --git a/etcdctl/ctlv3/command/downgrade_command.go b/etcdctl/ctlv3/command/downgrade_command.go new file mode 100644 index 000000000000..379d94f4ca2e --- /dev/null +++ b/etcdctl/ctlv3/command/downgrade_command.go @@ -0,0 +1,135 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package command + +import ( + "errors" + "github.com/spf13/cobra" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/pkg/v3/cobrautl" +) + +// NewDowngradeCommand returns the cobra command for "downgrade". +func NewDowngradeCommand() *cobra.Command { + dc := &cobra.Command{ + Use: "downgrade ", + Short: "Downgrade related commands", + } + + dc.AddCommand(NewDowngradeValidateCommand()) + dc.AddCommand(NewDowngradeEnableCommand()) + dc.AddCommand(NewDowngradeCancelCommand()) + + return dc +} + +// NewDowngradeValidateCommand returns the cobra command for "downgrade validate". +func NewDowngradeValidateCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "validate ", + Short: "Validate downgrade capability before starting downgrade", + + Run: downgradeValidateCommandFunc, + } + return cc +} + +// NewDowngradeEnableCommand returns the cobra command for "downgrade enable". +func NewDowngradeEnableCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "enable ", + Short: "Start a downgrade action to cluster", + + Run: downgradeEnableCommandFunc, + } + return cc +} + +// NewDowngradeCancelCommand returns the cobra command for "downgrade cancel". +func NewDowngradeCancelCommand() *cobra.Command { + cc := &cobra.Command{ + Use: "cancel", + Short: "Cancel the ongoing downgrade action to cluster", + + Run: downgradeCancelCommandFunc, + } + return cc +} + +// downgradeValidateCommandFunc executes the "downgrade validate" command. +func downgradeValidateCommandFunc(cmd *cobra.Command, args []string) { + if len(args) < 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("TARGET_VERSION not provided")) + } + if len(args) > 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("too many arguments")) + } + targetVersion := args[0] + + if len(targetVersion) == 0 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + } + + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_VALIDATE), targetVersion) + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeValidate(*resp) +} + +// downgradeEnableCommandFunc executes the "downgrade enable" command. +func downgradeEnableCommandFunc(cmd *cobra.Command, args []string) { + if len(args) < 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("TARGET_VERSION not provided")) + } + if len(args) > 1 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("too many arguments")) + } + targetVersion := args[0] + + if len(targetVersion) == 0 { + cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("member peer urls not provided")) + } + + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_ENABLE), targetVersion) + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeEnable(*resp) +} + +// downgradeCancelCommandFunc executes the "downgrade cancel" command. +func downgradeCancelCommandFunc(cmd *cobra.Command, args []string) { + ctx, cancel := commandCtx(cmd) + cli := mustClientFromCmd(cmd) + + resp, err := cli.Downgrade(ctx, int32(pb.DowngradeRequest_ENABLE), "") + cancel() + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + + display.DowngradeCancel(*resp) +} diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 2d31d9ec8c6b..65614d53275e 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -50,6 +50,10 @@ type printer interface { EndpointHashKV([]epHashKV) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) + DowngradeValidate(r v3.DowngradeResponse) + DowngradeEnable(r v3.DowngradeResponse) + DowngradeCancel(r v3.DowngradeResponse) + Alarm(v3.AlarmResponse) RoleAdd(role string, r v3.AuthRoleAddResponse) @@ -115,6 +119,9 @@ func (p *printerRPC) Alarm(r v3.AlarmResponse) { p.p((*pb.AlarmRespons func (p *printerRPC) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p((*pb.MoveLeaderResponse)(&r)) } +func (p *printerRPC) DowngradeValidate(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } +func (p *printerRPC) DowngradeEnable(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } +func (p *printerRPC) DowngradeCancel(r v3.DowngradeResponse) { p.p((*pb.DowngradeResponse)(&r)) } func (p *printerRPC) RoleAdd(_ string, r v3.AuthRoleAddResponse) { p.p((*pb.AuthRoleAddResponse)(&r)) } func (p *printerRPC) RoleGet(_ string, r v3.AuthRoleGetResponse) { p.p((*pb.AuthRoleGetResponse)(&r)) } func (p *printerRPC) RoleDelete(_ string, r v3.AuthRoleDeleteResponse) { @@ -160,6 +167,9 @@ func (p *printerUnsupported) EndpointStatus([]epStatus) { p.p(nil) } func (p *printerUnsupported) EndpointHashKV([]epHashKV) { p.p(nil) } func (p *printerUnsupported) MoveLeader(leader, target uint64, r v3.MoveLeaderResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeValidate(r v3.DowngradeResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeEnable(r v3.DowngradeResponse) { p.p(nil) } +func (p *printerUnsupported) DowngradeCancel(r v3.DowngradeResponse) { p.p(nil) } func makeMemberListTable(r v3.MemberListResponse) (hdr []string, rows [][]string) { hdr = []string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs", "Is Learner"} diff --git a/etcdctl/ctlv3/command/printer_simple.go b/etcdctl/ctlv3/command/printer_simple.go index 14028c614457..1970a49a4bc5 100644 --- a/etcdctl/ctlv3/command/printer_simple.go +++ b/etcdctl/ctlv3/command/printer_simple.go @@ -176,6 +176,16 @@ func (s *simplePrinter) MoveLeader(leader, target uint64, r v3.MoveLeaderRespons fmt.Printf("Leadership transferred from %s to %s\n", types.ID(leader), types.ID(target)) } +func (s *simplePrinter) DowngradeValidate(r v3.DowngradeResponse) { + fmt.Printf("Downgrade validate success, cluster version %s", r.Version) +} +func (s *simplePrinter) DowngradeEnable(r v3.DowngradeResponse) { + fmt.Printf("Downgrade enable success, cluster version %s", r.Version) +} +func (s *simplePrinter) DowngradeCancel(r v3.DowngradeResponse) { + fmt.Printf("Downgrade cancel success, cluster version %s", r.Version) +} + func (s *simplePrinter) RoleAdd(role string, r v3.AuthRoleAddResponse) { fmt.Printf("Role %s created\n", role) } diff --git a/etcdctl/ctlv3/ctl.go b/etcdctl/ctlv3/ctl.go index 8de7a77689df..bfe8f8674ab8 100644 --- a/etcdctl/ctlv3/ctl.go +++ b/etcdctl/ctlv3/ctl.go @@ -97,6 +97,7 @@ func init() { command.NewRoleCommand(), command.NewCheckCommand(), command.NewCompletionCommand(), + command.NewDowngradeCommand(), ) }