From c4cf783865250277dd534c8ae4ff900fae58fc34 Mon Sep 17 00:00:00 2001 From: wsehjk Date: Fri, 22 Dec 2023 13:19:29 +0800 Subject: [PATCH] Feat "$curve bs export target" issue #2564 Signed-off-by: wsehjk --- tools-v2/internal/error/error.go | 6 + tools-v2/internal/utils/target.go | 33 +++++ tools-v2/pkg/cli/command/curvebs/bs.go | 2 + .../pkg/cli/command/curvebs/export/export.go | 48 +++++++ .../command/curvebs/export/target/target.go | 130 ++++++++++++++++++ .../command/curvebs/status/client/client.go | 11 ++ .../command/curvebs/status/cluster/cluster.go | 16 ++- 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 tools-v2/internal/utils/target.go create mode 100644 tools-v2/pkg/cli/command/curvebs/export/export.go create mode 100644 tools-v2/pkg/cli/command/curvebs/export/target/target.go diff --git a/tools-v2/internal/error/error.go b/tools-v2/internal/error/error.go index aea8ad92d3..d3fa5fa1af 100644 --- a/tools-v2/internal/error/error.go +++ b/tools-v2/internal/error/error.go @@ -500,6 +500,12 @@ var ( ErrInvalidMetaServerAddr = func() *CmdError { return NewInternalCmdError(80, "invalid metaserver external addr: %s") } + ErrTargetCluster = func() *CmdError { + return NewInternalCmdError(81, "get cluster target error: %s") + } + ErrTargetClient = func() *CmdError { + return NewInternalCmdError(82, "get client target error: %s") + } // http error ErrHttpUnreadableResult = func() *CmdError { diff --git a/tools-v2/internal/utils/target.go b/tools-v2/internal/utils/target.go new file mode 100644 index 0000000000..998fa63996 --- /dev/null +++ b/tools-v2/internal/utils/target.go @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 NetEase Inc. + * + * 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. + */ + +/* + * Project: CurveCli + * Created Date: 2023-12-26 + * Author: wsehjk + */ +package cobrautil +const ( + LabelKey = "label" + ClientTarget = "client" + EtcdTarget = "etcd" + MdsTarget = "mds" + ChunkServerTarget = "chunkserver" + SnapshotTarget = "snapshot" + SnapshotServerTarget = "snapshotcloneserver" + TargetKey = "targets" + JobKey = "job" +) \ No newline at end of file diff --git a/tools-v2/pkg/cli/command/curvebs/bs.go b/tools-v2/pkg/cli/command/curvebs/bs.go index c82ca69528..783cbdbae0 100644 --- a/tools-v2/pkg/cli/command/curvebs/bs.go +++ b/tools-v2/pkg/cli/command/curvebs/bs.go @@ -36,6 +36,7 @@ import ( "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/stop" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/update" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/export" ) type CurveBsCommand struct { @@ -56,6 +57,7 @@ func (bsCmd *CurveBsCommand) AddSubCommands() { check.NewCheckCommand(), snapshot.NewSnapshotCommand(), stop.NewStopCommand(), + export.NewExportCommand(), ) } diff --git a/tools-v2/pkg/cli/command/curvebs/export/export.go b/tools-v2/pkg/cli/command/curvebs/export/export.go new file mode 100644 index 0000000000..b8f337a8aa --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/export/export.go @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ +/* +* Project: CurveCli +* Created Date: 2023-12-11 +* Author: wsehjk + */ + +package export + +import ( + basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command" + target "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/export/target" + "github.com/spf13/cobra" +) +type ExportCommand struct { + basecmd.MidCurveCmd +} + +var _ basecmd.MidCurveCmdFunc = (*ExportCommand)(nil) // check interface + +func (eCmd *ExportCommand) AddSubCommands() { + eCmd.Cmd.AddCommand( + target.NewTargetCommand(), + ) +} +func NewExportCommand() *cobra.Command{ + eCmd := &ExportCommand { + basecmd.MidCurveCmd{ + Use: "export", + Short: "export the target in curvebs", + }, + } + return basecmd.NewMidCurveCli(&eCmd.MidCurveCmd, eCmd) +} \ No newline at end of file diff --git a/tools-v2/pkg/cli/command/curvebs/export/target/target.go b/tools-v2/pkg/cli/command/curvebs/export/target/target.go new file mode 100644 index 0000000000..073946f924 --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/export/target/target.go @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2023 NetEase Inc. +* +* 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. + */ +/* +* Project: curve +* Created Date: 2023-12-11 +* Author: wsehjk + */ + +package target + +import ( + "encoding/json" + "fmt" + + cmderror "github.com/opencurve/curve/tools-v2/internal/error" + basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/client" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/cluster" + cobrautil "github.com/opencurve/curve/tools-v2/internal/utils" + "github.com/opencurve/curve/tools-v2/pkg/output" + "github.com/spf13/cobra" +) + +const ( + targetExample = "$curve bs export target" +) +type ResultStruct map[string]interface{} +type targetcommand struct { + basecmd.FinalCurveCmd +} +// check interface targetcommand implement FinalCurveCmdFunc +var _ basecmd.FinalCurveCmdFunc = (*targetcommand)(nil) + +func ExtractClusterResult(clusterResult map[string]interface{}, service string) ResultStruct{ + result := ResultStruct{} + arrs := clusterResult[service].([]map[string]string) + result[cobrautil.LabelKey] = map[string]string{ + cobrautil.JobKey : service, + } + if service == cobrautil.SnapshotTarget { + result[cobrautil.LabelKey] = map[string]string{ + cobrautil.JobKey : cobrautil.SnapshotServerTarget, + } + } + result[cobrautil.TargetKey] = make([]string, 0) + for _, arr := range arrs { + if addr, ok := arr["addr"]; ok { // see the output of curve bs status cluster + result[cobrautil.TargetKey] = append(result[cobrautil.TargetKey].([]string), addr) + } + if addr, ok := arr["internalAddr"]; ok { + result[cobrautil.TargetKey] = append(result[cobrautil.TargetKey].([]string), addr) + } + } + return result +} +func NewTargetCommand() (cmd *cobra.Command) { + tcmd := &targetcommand{ + FinalCurveCmd: basecmd.FinalCurveCmd { + Use: "target", + Short: "export all the target in cluster and used by monitor", + Example: targetExample, + }, + } + return basecmd.NewFinalCurveCli(&tcmd.FinalCurveCmd, tcmd) +} + +func (tcmd *targetcommand)Init(cmd *cobra.Command, args []string) error { + return nil +} +func (tcmd *targetcommand)RunCommand(cmd *cobra.Command, args []string) error { + // get cluster target + clusterResult, err := cluster.GetClusterStatus() + if err != nil { + retErr := cmderror.ErrTargetCluster() + retErr.Format(err.Error()) + return retErr.ToError() + } + tcmd.Result = []ResultStruct{} + tcmd.Result = append(tcmd.Result.([]ResultStruct), ExtractClusterResult(clusterResult.(map[string]interface{}), cobrautil.EtcdTarget)) + tcmd.Result = append(tcmd.Result.([]ResultStruct), ExtractClusterResult(clusterResult.(map[string]interface{}), cobrautil.MdsTarget)) + tcmd.Result = append(tcmd.Result.([]ResultStruct), ExtractClusterResult(clusterResult.(map[string]interface{}), cobrautil.ChunkServerTarget)) + tcmd.Result = append(tcmd.Result.([]ResultStruct), ExtractClusterResult(clusterResult.(map[string]interface{}), cobrautil.SnapshotTarget)) + + // get client target + clientResult, err := client.GetClientStatus() + if err != nil { + retErr := cmderror.ErrTargetClient() + retErr.Format(err.Error()) + return retErr.ToError() + } + clientStruct := ResultStruct{} + clientStruct[cobrautil.LabelKey] = map[string]string{ + cobrautil.JobKey : cobrautil.ClientTarget, + } + clientStruct[cobrautil.TargetKey] = make([]string, 0) + for _, result := range clientResult.([]map[string]string) { + clientStruct[cobrautil.TargetKey] = append(clientStruct[cobrautil.TargetKey].([]string), result["addr"]) + } + tcmd.Result = append(tcmd.Result.([]ResultStruct), clientStruct) + return nil +} + +func (tcmd *targetcommand)Print(cmd *cobra.Command, args []string) error { + output, err := json.MarshalIndent(tcmd.Result, "", " ") + if err != nil { + return err + } + fmt.Println(string(output)) + return nil +} +// result in plain format string +func (tcmd *targetcommand)ResultPlainOutput() error { + return output.FinalCmdOutputPlain(&tcmd.FinalCurveCmd) +} + +// target final command has no flag +func (tcmd *targetcommand)AddFlags() { } \ No newline at end of file diff --git a/tools-v2/pkg/cli/command/curvebs/status/client/client.go b/tools-v2/pkg/cli/command/curvebs/status/client/client.go index e056090224..7299ecbdaa 100644 --- a/tools-v2/pkg/cli/command/curvebs/status/client/client.go +++ b/tools-v2/pkg/cli/command/curvebs/status/client/client.go @@ -25,6 +25,7 @@ package client import ( "strconv" "strings" + "fmt" cmderror "github.com/opencurve/curve/tools-v2/internal/error" cobrautil "github.com/opencurve/curve/tools-v2/internal/utils" @@ -238,3 +239,13 @@ func NewStatusClientCommand() *ClientCommand { basecmd.NewFinalCurveCli(&clientCmd.FinalCurveCmd, clientCmd) return clientCmd } + +func GetClientStatus() (interface{}, error){ + clientCommand := NewStatusClientCommand() + clientCommand.Cmd.SetArgs([]string{ + fmt.Sprintf("--%s", config.FORMAT), config.FORMAT_NOOUT,}) + clientCommand.Cmd.SilenceErrors = true + err := clientCommand.Cmd.Execute() + + return clientCommand.Result, err +} \ No newline at end of file diff --git a/tools-v2/pkg/cli/command/curvebs/status/cluster/cluster.go b/tools-v2/pkg/cli/command/curvebs/status/cluster/cluster.go index 9d951a9067..80f61aaad6 100644 --- a/tools-v2/pkg/cli/command/curvebs/status/cluster/cluster.go +++ b/tools-v2/pkg/cli/command/curvebs/status/cluster/cluster.go @@ -67,6 +67,10 @@ const ( ) func NewClusterCommand() *cobra.Command { + return NewStatusClusterCommand().Cmd +} + +func NewStatusClusterCommand() *ClusterCommand { cCmd := &ClusterCommand{ FinalCurveCmd: basecmd.FinalCurveCmd{ Use: "cluster", @@ -75,7 +79,7 @@ func NewClusterCommand() *cobra.Command { }, } basecmd.NewFinalCurveCli(&cCmd.FinalCurveCmd, cCmd) - return cCmd.Cmd + return cCmd } func (cCmd *ClusterCommand) AddFlags() { @@ -245,3 +249,13 @@ func (cCmd *ClusterCommand) buildTableCopyset(results []map[string]string) { row = append(row, results[0][cobrautil.ROW_UNHEALTHY_RATIO]) cCmd.tableCopyset.Append(row) } + +func GetClusterStatus() (interface{}, error){ + clusterCommand := NewStatusClusterCommand() + // cluster command no output + clusterCommand.Cmd.SetArgs([]string{ + fmt.Sprintf("--%s", config.FORMAT), config.FORMAT_NOOUT,}) + clusterCommand.Cmd.SilenceErrors = true + err := clusterCommand.Cmd.Execute() + return clusterCommand.Result, err +} \ No newline at end of file