Skip to content

Commit

Permalink
feature(*): support exec subcommand
Browse files Browse the repository at this point in the history
issue #153
usage: curveadm exec 0e5d809f16b4 --cmd="ps -ef"

Signed-off-by: Wangpan <[email protected]>
  • Loading branch information
aspirer committed Nov 17, 2022
1 parent 7341b1b commit 684c193
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 6 deletions.
1 change: 1 addition & 0 deletions cli/command/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func addSubCommands(cmd *cobra.Command, curveadm *cli.CurveAdm) {
NewCompletionCommand(curveadm), // curveadm completion
NewDeployCommand(curveadm), // curveadm deploy
NewEnterCommand(curveadm), // curveadm enter
NewExecCommand(curveadm), // curveadm exec
NewFormatCommand(curveadm), // curveadm format
NewMigrateCommand(curveadm), // curveadm migrate
NewPrecheckCommand(curveadm), // curveadm precheck
Expand Down
92 changes: 92 additions & 0 deletions cli/command/exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2021 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: 2021-10-15
* Author: Jingli Chen (Wine93)
*/

// __SIGN_BY_WINE93__

package command

import (
"github.com/opencurve/curveadm/cli/cli"
"github.com/opencurve/curveadm/internal/configure/topology"
"github.com/opencurve/curveadm/internal/errno"
"github.com/opencurve/curveadm/internal/tools"
"github.com/opencurve/curveadm/internal/utils"
"github.com/spf13/cobra"
)

type execOptions struct {
id string
cmd string
}

func NewExecCommand(curveadm *cli.CurveAdm) *cobra.Command {
var options execOptions

cmd := &cobra.Command{
Use: "exec ID [OPTIONS]",
Short: "Exec a cmd in service container",
Args: utils.ExactArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
options.id = args[0]
return curveadm.CheckId(options.id)
},
RunE: func(cmd *cobra.Command, args []string) error {
return runExec(curveadm, options)
},
DisableFlagsInUseLine: true,
}

flags := cmd.Flags()
flags.StringVar(&options.id, "id", "*", "Specify service id")
flags.StringVar(&options.cmd, "cmd", "*", "Specify command to exec")

return cmd
}

func runExec(curveadm *cli.CurveAdm, options execOptions) error {
// 1) parse cluster topology
dcs, err := curveadm.ParseTopology()
if err != nil {
return err
}

// 2) filter service
dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{
Id: options.id,
Role: "*",
Host: "*",
})
if len(dcs) == 0 {
return errno.ERR_NO_SERVICES_MATCHED
}

// 3) get container id
dc := dcs[0]
serviceId := curveadm.GetServiceId(dc.GetId())
containerId, err := curveadm.GetContainerId(serviceId)
if err != nil {
return err
}

// 4) exec cmd in remote container
return tools.ExecCmdInRemoteContainer(curveadm, dc.GetHost(), containerId, options.cmd)
}
2 changes: 1 addition & 1 deletion cli/command/playground/enter.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ func runEnter(curveadm *cli.CurveAdm, options enterOptions) error {
F("id=%s", id)
}

// 2) attch remote container
// 2) attch local container
return tools.AttachLocalContainer(curveadm, playgrounds[0].Name)
}
32 changes: 27 additions & 5 deletions internal/tools/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ import (
)

const (
TEMPLATE_SCP = `scp -P {{.port}} {{or .options ""}} {{.source}} {{.user}}@{{.host}}:{{.target}}`
TEMPLATE_SSH_COMMAND = `ssh {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}`
TEMPLATE_SSH_ATTACH = `ssh -tt {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}`
TEMPLATE_COMMAND_EXEC_CONTAINER = `{{.sudo}} docker exec -it {{.container_id}} /bin/bash -c "cd {{.home_dir}}; /bin/bash"`
TEMPLATE_LOCAL_EXEC_CONTAINER = `docker exec -it {{.container_id}} /bin/bash` // FIXME: merge it
TEMPLATE_SCP = `scp -P {{.port}} {{or .options ""}} {{.source}} {{.user}}@{{.host}}:{{.target}}`
TEMPLATE_SSH_COMMAND = `ssh {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}`
TEMPLATE_SSH_ATTACH = `ssh -tt {{.user}}@{{.host}} -p {{.port}} {{or .options ""}} {{or .become ""}} {{.command}}`
TEMPLATE_COMMAND_EXEC_CONTAINER = `{{.sudo}} docker exec -it {{.container_id}} /bin/bash -c "cd {{.home_dir}}; /bin/bash"`
TEMPLATE_LOCAL_EXEC_CONTAINER = `docker exec -it {{.container_id}} /bin/bash` // FIXME: merge it
TEMPLATE_COMMAND_EXEC_CONTAINER_NOATTACH = `{{.sudo}} docker exec -t {{.container_id}} /bin/bash -c "{{.command}}"`
)

func prepareOptions(curveadm *cli.CurveAdm, host string, become bool, extra map[string]interface{}) (map[string]interface{}, error) {
Expand Down Expand Up @@ -168,6 +169,27 @@ func AttachLocalContainer(curveadm *cli.CurveAdm, containerId string) error {
return runCommand(curveadm, command, map[string]interface{}{})
}

func ExecCmdInRemoteContainer(curveadm *cli.CurveAdm, host, containerId, cmd string) error {
data := map[string]interface{}{
"sudo": curveadm.Config().GetSudoAlias(),
"container_id": containerId,
"command": cmd,
}
tmpl := template.Must(template.New("command").Parse(TEMPLATE_COMMAND_EXEC_CONTAINER_NOATTACH))
buffer := bytes.NewBufferString("")
if err := tmpl.Execute(buffer, data); err != nil {
return errno.ERR_BUILD_TEMPLATE_FAILED.E(err)
}
command := buffer.String()

options, err := prepareOptions(curveadm, host, true,
map[string]interface{}{"command": command})
if err != nil {
return err
}
return ssh(curveadm, options)
}

func Scp(curveadm *cli.CurveAdm, host, source, target string) error {
options, err := prepareOptions(curveadm, host, false,
map[string]interface{}{
Expand Down

0 comments on commit 684c193

Please sign in to comment.