Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature(copy tool): add copy tool2 command #386

Merged
merged 1 commit into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cli/command/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/opencurve/curveadm/cli/command/client"
"github.com/opencurve/curveadm/cli/command/cluster"
"github.com/opencurve/curveadm/cli/command/config"
copycmd "github.com/opencurve/curveadm/cli/command/copy"
"github.com/opencurve/curveadm/cli/command/hosts"
"github.com/opencurve/curveadm/cli/command/monitor"
"github.com/opencurve/curveadm/cli/command/pfs"
Expand Down Expand Up @@ -66,6 +67,7 @@ func addSubCommands(cmd *cobra.Command, curveadm *cli.CurveAdm) {
target.NewTargetCommand(curveadm), // curveadm target ...
pfs.NewPFSCommand(curveadm), // curveadm pfs ...
monitor.NewMonitorCommand(curveadm), // curveadm monitor ...
copycmd.NewCopyCommand(curveadm), // curveadm copy ...

NewAuditCommand(curveadm), // curveadm audit
NewCleanCommand(curveadm), // curveadm clean
Expand Down
43 changes: 43 additions & 0 deletions cli/command/copy/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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: CurveAdm
* Created Date: 2023-12-25
* Author: Xinyu Zhuo (0fatal)
*/

package copy

import (
"github.com/opencurve/curveadm/cli/cli"
cliutil "github.com/opencurve/curveadm/internal/utils"
"github.com/spf13/cobra"
)

func NewCopyCommand(curveadm *cli.CurveAdm) *cobra.Command {
cmd := &cobra.Command{
Use: "copy",
Short: "Manage copy",
Args: cliutil.NoArgs,
RunE: cliutil.ShowHelp(curveadm.Err()),
}

cmd.AddCommand(
NewCopyTool2Command(curveadm),
)
return cmd
}
111 changes: 111 additions & 0 deletions cli/command/copy/tool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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: CurveAdm
* Created Date: 2023-12-25
* Author: Xinyu Zhuo (0fatal)
*/

package copy

import (
"github.com/fatih/color"
"github.com/opencurve/curveadm/cli/cli"
comm "github.com/opencurve/curveadm/internal/common"
"github.com/opencurve/curveadm/internal/configure/topology"
"github.com/opencurve/curveadm/internal/errno"
"github.com/opencurve/curveadm/internal/playbook"
cliutil "github.com/opencurve/curveadm/internal/utils"
"github.com/spf13/cobra"
)

var (
COPY_TOOL_PLAYBOOK_STEPS = []int{
playbook.COPY_TOOL,
}
)

type copyOptions struct {
host string
path string
confPath string
}

func NewCopyTool2Command(curveadm *cli.CurveAdm) *cobra.Command {
var options copyOptions

cmd := &cobra.Command{
Use: "tool [OPTIONS]",
Short: "Copy tool v2 on the specified host",
Args: cliutil.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runCopyTool(curveadm, options)
},
DisableFlagsInUseLine: true,
}

flags := cmd.Flags()
flags.StringVar(&options.host, "host", "localhost", "Specify target host")
flags.StringVar(&options.path, "path", "/usr/local/bin/curve", "Specify target copy path of tool v2")
flags.StringVar(&options.confPath, "confPath", "/etc/curve/curve.yaml", "Specify target config path of tool v2")

return cmd
}

func genCopyToolPlaybook(curveadm *cli.CurveAdm,
dcs []*topology.DeployConfig,
options copyOptions,
) (*playbook.Playbook, error) {
configs := curveadm.FilterDeployConfig(dcs, topology.FilterOption{Id: "*", Role: "*", Host: options.host})[:1]
if len(configs) == 0 {
return nil, errno.ERR_NO_SERVICES_MATCHED
}
steps := COPY_TOOL_PLAYBOOK_STEPS
pb := playbook.NewPlaybook(curveadm)
for _, step := range steps {
pb.AddStep(&playbook.PlaybookStep{
Type: step,
Configs: configs,
Options: map[string]interface{}{
comm.KEY_COPY_PATH: options.path,
comm.KEY_COPY_CONF_PATH: options.confPath,
},
})
}
return pb, nil
}

func runCopyTool(curveadm *cli.CurveAdm, options copyOptions) error {
dcs, err := curveadm.ParseTopology()
if err != nil {
return err
}

pb, err := genCopyToolPlaybook(curveadm, dcs, options)
if err != nil {
return err
}

err = pb.Run()
if err != nil {
return err
}

curveadm.WriteOutln(color.GreenString("Copy %s to %s success."),
"curve tool v2", options.host)
return nil
}
4 changes: 4 additions & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ const (
KEY_SERVICE_HOSTS = "SERVICE_HOSTS"
KEY_MONITOR_STATUS = "MONITOR_STATUS"
CLEANED_MONITOR_CONF = "-"

// copy
KEY_COPY_PATH = "COPY_PATH"
KEY_COPY_CONF_PATH = "COPY_CONF_PATH"
)

// others
Expand Down
3 changes: 3 additions & 0 deletions internal/playbook/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const (
INSTALL_CLIENT
UNINSTALL_CLIENT
ATTACH_LEADER_OR_RANDOM_CONTAINER
COPY_TOOL

// bs
FORMAT_CHUNKFILE_POOL
Expand Down Expand Up @@ -250,6 +251,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) {
t, err = comm.NewInstallClientTask(curveadm, config.GetCC(i))
case UNINSTALL_CLIENT:
t, err = comm.NewUninstallClientTask(curveadm, nil)
case COPY_TOOL:
t, err = comm.NewCopyToolTask(curveadm, config.GetDC(i))
// bs
case FORMAT_CHUNKFILE_POOL:
t, err = bs.NewFormatChunkfilePoolTask(curveadm, config.GetFC(i))
Expand Down
101 changes: 101 additions & 0 deletions internal/task/task/common/copy_tool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* 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: CurveAdm
* Created Date: 2023-12-25
* Author: Xinyu Zhuo (0fatal)
*/

package common

import (
"fmt"
"github.com/opencurve/curveadm/cli/cli"
comm "github.com/opencurve/curveadm/internal/common"
"github.com/opencurve/curveadm/internal/configure/topology"
"github.com/opencurve/curveadm/internal/errno"
"github.com/opencurve/curveadm/internal/task/step"
"github.com/opencurve/curveadm/internal/task/task"
tui "github.com/opencurve/curveadm/internal/tui/common"
"github.com/opencurve/curveadm/pkg/module"
"path/filepath"
)

func checkPathExist(path string, sshConfig *module.SSHConfig, curveadm *cli.CurveAdm) error {
sshClient, err := module.NewSSHClient(*sshConfig)
if err != nil {
return errno.ERR_SSH_CONNECT_FAILED.E(err)
}

module := module.NewModule(sshClient)
cmd := module.Shell().Stat(path)
if _, err := cmd.Execute(curveadm.ExecOptions()); err == nil {
if pass := tui.ConfirmYes(tui.PromptPathExist(path)); !pass {
return errno.ERR_CANCEL_OPERATION
}
}
return nil
}

func NewCopyToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) {
layout := dc.GetProjectLayout()
path := curveadm.MemStorage().Get(comm.KEY_COPY_PATH).(string)
confPath := curveadm.MemStorage().Get(comm.KEY_COPY_CONF_PATH).(string)
hc, err := curveadm.GetHost(dc.GetHost())
if err != nil {
return nil, err
}

serviceId := curveadm.GetServiceId(dc.GetId())
containerId, err := curveadm.GetContainerId(serviceId)
if err != nil {
return nil, err
}

if err = checkPathExist(path, hc.GetSSHConfig(), curveadm); err != nil {
return nil, err
}
if err = checkPathExist(confPath, hc.GetSSHConfig(), curveadm); err != nil {
return nil, err
}

subname := fmt.Sprintf("host=%s", dc.GetHost())
t := task.NewTask("Copy version 2 tool to host", subname, hc.GetSSHConfig())

t.AddStep(&step.CreateDirectory{
Paths: []string{filepath.Dir(path)},
ExecOptions: curveadm.ExecOptions(),
})
t.AddStep(&step.CopyFromContainer{
ContainerSrcPath: layout.ToolsV2BinaryPath,
ContainerId: containerId,
HostDestPath: path,
ExecOptions: curveadm.ExecOptions(),
})
t.AddStep(&step.CreateDirectory{
Paths: []string{filepath.Dir(confPath)},
ExecOptions: curveadm.ExecOptions(),
})
t.AddStep(&step.CopyFromContainer{
ContainerSrcPath: layout.ToolsV2ConfSystemPath,
ContainerId: containerId,
HostDestPath: confPath,
ExecOptions: curveadm.ExecOptions(),
})

return t, nil
}
11 changes: 10 additions & 1 deletion internal/tui/common/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ to watch the formatting progress.
`
PROMPT_CANCEL_OPERATION = `[x] {{.operation}} canceled`

PROMPT_PATH_EXIST = `{{.path}} already exists.
`
0fatal marked this conversation as resolved.
Show resolved Hide resolved

DEFAULT_CONFIRM_PROMPT = "Do you want to continue?"
)

Expand Down Expand Up @@ -210,7 +213,7 @@ func PromptErrorCode(code int, description, clue, logpath string) string {
if len(clue) > 0 {
prompt.data["clue"] = prettyClue(clue)
}
prompt.data["website"] = fmt.Sprintf("https://github.com/opencurve/curveadm/wiki/errno%d#%06d", code / 100000, code)
prompt.data["website"] = fmt.Sprintf("https://github.com/opencurve/curveadm/wiki/errno%d#%06d", code/100000, code)
if len(logpath) > 0 {
prompt.data["logpath"] = logpath
}
Expand All @@ -230,3 +233,9 @@ func PromptAutoUpgrade(version string) string {
prompt.data["version"] = version
return prompt.Build()
}

func PromptPathExist(path string) string {
prompt := NewPrompt(color.YellowString(PROMPT_PATH_EXIST) + DEFAULT_CONFIRM_PROMPT)
prompt.data["path"] = path
return prompt.Build()
}