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

swctl: option of continuous printing of commands to stdout/err #139

Merged
merged 1 commit into from
Oct 12, 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
7 changes: 4 additions & 3 deletions cmd/swctl/app/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Cli interface {
Client() client.API
Entities() []Entity
GlobalOptions() *GlobalOptions
Exec(cmd string, args []string) (stdout string, stderr string, err error)
Exec(cmd string, args []string, liveOutput bool) (stdout string, stderr string, err error)
AppName() string

Out() *streams.Out
Expand Down Expand Up @@ -136,7 +136,7 @@ func (cli *CLI) GlobalOptions() *GlobalOptions {
return cli.globalOptions
}

func (cli *CLI) Exec(cmd string, args []string) (string, string, error) {
func (cli *CLI) Exec(cmd string, args []string, liveOutput bool) (string, string, error) {
if cmd == "" {
return "", "", errors.New("cannot execute empty command")
}
Expand All @@ -145,7 +145,8 @@ func (cli *CLI) Exec(cmd string, args []string) (string, string, error) {
args = append(cmdParts[1:], args...)
}
ecmd := newExternalCmd(externalExe(cmdParts[0]), args, cli)
res, err := ecmd.exec()

res, err := ecmd.exec(liveOutput)
if err != nil {
return "", "", err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/swctl/app/cmd_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func runConfigCmd(cli Cli, opts ConfigCmdOptions) error {
args = append(args, hideInternalFlag)
}

stdout, stderr, err := cli.Exec("agentctl config", args)
stdout, stderr, err := cli.Exec("agentctl config", args, false)
if err != nil {
return err
}
Expand Down
18 changes: 9 additions & 9 deletions cmd/swctl/app/cmd_dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,15 @@ func linkSetUpDown(cli Cli) *cobra.Command {
}
} else if args[len(args)-1] == "down" {
//link down interface, only assigned network devices have /net directory which is name of interface
stdout, stderr, err := cli.Exec("ls", []string{"/sys/bus/pci/devices/" + physicalInterfaces[matchId].Pci + "/net"})
stdout, stderr, err := cli.Exec("ls", []string{"/sys/bus/pci/devices/" + physicalInterfaces[matchId].Pci + "/net"}, false)
if stderr != "" {
return errors.New(stderr)
}
if err != err {
return err
}
if stdout != "" {
_, _, err = cli.Exec("sudo ip link set "+stdout+" down", nil)
_, _, err = cli.Exec("sudo ip link set "+stdout+" down", nil, false)
if err != err {
return err
}
Expand All @@ -269,7 +269,7 @@ func linkSetUpDown(cli Cli) *cobra.Command {
}

func IsDockerAvailable(cli Cli) (bool, error) {
out, _, err := cli.Exec("whereis docker", nil)
out, _, err := cli.Exec("whereis docker", nil, false)
if err != nil {
return false, err
}
Expand All @@ -280,7 +280,7 @@ func IsDockerAvailable(cli Cli) (bool, error) {
}

func AllocatedHugePages(cli Cli) (int, error) {
out, _, err := cli.Exec("sysctl vm.nr_hugepages -n", nil)
out, _, err := cli.Exec("sysctl vm.nr_hugepages -n", nil, false)
if err != nil {
return 0, err
}
Expand All @@ -300,7 +300,7 @@ func ResizeHugePages(cli Cli, size uint) error {
fmt.Fprintln(cli.Out(), "Skipping hugepages")
return nil
}
_, _, err := cli.Exec(fmt.Sprintf("sudo sysctl -w vm.nr_hugepages=%d", size), nil)
_, _, err := cli.Exec(fmt.Sprintf("sudo sysctl -w vm.nr_hugepages=%d", size), nil, false)
if err != nil {
return err
}
Expand Down Expand Up @@ -341,7 +341,7 @@ func InstallDocker(cli Cli, dockerVersion string) error {
}

for _, command := range commands {
out, stderr, err := cli.Exec("bash -c", []string{command})
out, stderr, err := cli.Exec("bash -c", []string{command}, false)
if stderr != "" {
return errors.New(command + ": " + stderr)
}
Expand Down Expand Up @@ -433,7 +433,7 @@ func unbindDevice(cli Cli, pci string, driver string) error {
//Mostly
path := fmt.Sprintf("/sys/bus/pci/drivers/%s/unbind", driver)

_, stderr, err := cli.Exec("sudo bash -c", []string{"echo \"" + pci + "\" > " + path})
_, stderr, err := cli.Exec("sudo bash -c", []string{"echo \"" + pci + "\" > " + path}, false)
if stderr != "" {
return errors.New(stderr)
}
Expand All @@ -446,7 +446,7 @@ func bindDevice(cli Cli, pci string, driver string) error {

path := fmt.Sprintf("/sys/bus/pci/drivers/%s/bind", driver)

_, stderr, err := cli.Exec("sudo bash -c", []string{"echo \"" + pci + "\" > " + path})
_, stderr, err := cli.Exec("sudo bash -c", []string{"echo \"" + pci + "\" > " + path}, false)
if stderr != "" {
return errors.New(stderr)
}
Expand All @@ -459,7 +459,7 @@ func bindDevice(cli Cli, pci string, driver string) error {
func DumpDevices(cli Cli) ([]NetworkInterface, error) {
var nics []NetworkInterface

stdout, _, err := cli.Exec("lspci", []string{"-Dvmmnnk"})
stdout, _, err := cli.Exec("lspci", []string{"-Dvmmnnk"}, false)
if err != nil {
return nil, err
}
Expand Down
16 changes: 6 additions & 10 deletions cmd/swctl/app/cmd_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,10 @@ func newDeploymentUp(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose up", args)
_, _, err := cli.Exec("docker compose up", args, true)
if err != nil {
return err
}
fmt.Fprintln(cli.Out(), stdout)
fmt.Fprintln(cli.Err(), stderr)
return nil
},
}
Expand All @@ -78,12 +76,10 @@ func newDeploymentDown(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose down", args)
_, _, err := cli.Exec("docker compose down", args, true)
if err != nil {
return err
}
fmt.Fprintln(cli.Out(), stdout)
fmt.Fprintln(cli.Err(), stderr)
return nil
},
}
Expand All @@ -97,7 +93,7 @@ func newDeploymentConfig(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose convert", args)
stdout, stderr, err := cli.Exec("docker compose convert", args, false)
if err != nil {
return err
}
Expand All @@ -116,7 +112,7 @@ func newDeploymentInfo(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose ps", args)
stdout, stderr, err := cli.Exec("docker compose ps", args, false)
if err != nil {
return err
}
Expand All @@ -135,7 +131,7 @@ func newDeploymentImages(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose images", args)
stdout, stderr, err := cli.Exec("docker compose images", args, false)
if err != nil {
return err
}
Expand All @@ -154,7 +150,7 @@ func newDeploymentServices(cli Cli) *cobra.Command {
Args: cobra.ArbitraryArgs,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
stdout, stderr, err := cli.Exec("docker compose ps --services", args)
stdout, stderr, err := cli.Exec("docker compose ps --services", args, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/swctl/app/cmd_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func runStatusCmd(cli Cli, opts StatusOptions) error {
if sn, ok := compo.GetMetadata()["containerServiceName"]; ok {
cmd := fmt.Sprintf("vpp-probe --env=%s --query label=%s=%s discover", defaultVppProbeEnv, compose.ServiceLabel, sn)
formatArg := fmt.Sprintf("--format=%s", opts.Format)
stdout, stderr, err := cli.Exec(cmd, []string{formatArg})
stdout, stderr, err := cli.Exec(cmd, []string{formatArg}, false)
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
logrus.Tracef("vpp-probe discover failed for service %s with error: %v: %s", sn, ee.String(), ee.Stderr)
Expand Down
12 changes: 6 additions & 6 deletions cmd/swctl/app/cmd_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func writeInterfaces(cli Cli, w io.Writer, components []client.Component, otherA
for _, compo := range components {
if sn, ok := compo.GetMetadata()["containerServiceName"]; ok {
cmd := fmt.Sprintf("vpp-probe --color never --env=%s --query label=%s=%s discover", defaultVppProbeEnv, compose.ServiceLabel, sn)
stdout, _, err := cli.Exec(cmd, []string{})
stdout, _, err := cli.Exec(cmd, []string{}, false)
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
logrus.Tracef("vpp-probe discover failed for service %s with error: %v: %s", sn, ee.String(), ee.Stderr)
Expand Down Expand Up @@ -258,7 +258,7 @@ func writeStatusAsJson(cli Cli, w io.Writer, components []client.Component, othe

func writeDockerComposeConfig(cli Cli, w io.Writer, components []client.Component, otherArgs ...interface{}) error {
cmd := "docker compose config"
stdout, stderr, err := cli.Exec(cmd, []string{})
stdout, stderr, err := cli.Exec(cmd, []string{}, false)
if err != nil {
return err
}
Expand All @@ -271,7 +271,7 @@ func writeDockerComposeConfig(cli Cli, w io.Writer, components []client.Componen

func writeDockerContainers(cli Cli, w io.Writer, components []client.Component, otherArgs ...interface{}) error {
cmd := "docker compose ps --all"
stdout, stderr, err := cli.Exec(cmd, []string{})
stdout, stderr, err := cli.Exec(cmd, []string{}, false)
if err != nil {
return err
}
Expand All @@ -284,7 +284,7 @@ func writeDockerContainers(cli Cli, w io.Writer, components []client.Component,

func writeDockerInspect(cli Cli, w io.Writer, components []client.Component, otherArgs ...interface{}) error {
cmd := fmt.Sprintf("docker inspect %s", fmt.Sprintf("%s", otherArgs[0]))
stdout, _, err := cli.Exec(cmd, []string{})
stdout, _, err := cli.Exec(cmd, []string{}, false)
if err != nil {
return err
}
Expand All @@ -305,7 +305,7 @@ func writeAgentCtlInfo(cli Cli, w io.Writer, components []client.Component, args

cmd := fmt.Sprintf("agentctl --host %s --http-port %d --grpc-port=%d report -i -o %s",
host, httpPort, grpcPort, tempDirName)
_, _, err = cli.Exec(cmd, []string{})
_, _, err = cli.Exec(cmd, []string{}, false)
if err != nil {
return err
}
Expand Down Expand Up @@ -341,7 +341,7 @@ func writeAgentCtlInfo(cli Cli, w io.Writer, components []client.Component, args
func writeDockerLogs(cli Cli, w io.Writer, components []client.Component, args ...interface{}) error {
serviceName := args[0]
cmd := fmt.Sprintf("docker compose logs --no-color -n 10000 %s", serviceName)
stdout, stderr, err := cli.Exec(cmd, []string{})
stdout, stderr, err := cli.Exec(cmd, []string{}, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/swctl/app/cmd_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func runTraceCmd(cli Cli, opts TraceCmdOptions) error {
// - consider selecting IP and source network namespace automatically
// - consider allowing users to simply select component names for ping src/dst

stdout, stderr, err := cli.Exec(fmt.Sprintf("vpp-probe --env=%s trace", defaultVppProbeEnv), args)
stdout, stderr, err := cli.Exec(fmt.Sprintf("vpp-probe --env=%s trace", defaultVppProbeEnv), args, false)
if err != nil {
return err
}
Expand Down
15 changes: 12 additions & 3 deletions cmd/swctl/app/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package app
import (
"bytes"
"fmt"
"io"
"os/exec"
"strings"
"syscall"
Expand Down Expand Up @@ -106,12 +107,20 @@ type ExecResult struct {
Stderr string
}

func (ec *externalCmd) exec() (*ExecResult, error) {
func (ec *externalCmd) exec(liveOutput bool) (*ExecResult, error) {
var stdout, stderr bytes.Buffer
cmd := exec.Command(ec.name, ec.args...)
if liveOutput {
stdoutMultiWriter := io.MultiWriter(&stdout, ec.cli.out)
stderrMultiWriter := io.MultiWriter(&stderr, ec.cli.err)
cmd.Stdout = stdoutMultiWriter
cmd.Stderr = stderrMultiWriter
} else {
cmd.Stdout = &stdout
cmd.Stderr = &stderr
}

cmd.Env = ec.env
cmd.Stdout = &stdout
cmd.Stderr = &stderr

now := time.Now()
logrus.Tracef("[%s] %q", color.Gray.Sprint("EXEC"), cmd.String())
Expand Down