k9s/internal/views/exec.go

87 lines
1.9 KiB
Go

package views
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"os/signal"
"strings"
"syscall"
"github.com/rs/zerolog/log"
)
func runK(clear bool, app *appView, args ...string) bool {
bin, err := exec.LookPath("kubectl")
if err != nil {
log.Error().Msgf("Unable to find kubeclt command in path %v", err)
return false
}
return app.Suspend(func() {
last := len(args) - 1
if args[last] == "sh" {
args[last] = "bash"
if err := execute(clear, bin, args...); err != nil {
args[last] = "sh"
} else {
return
}
}
if err := execute(clear, bin, args...); err != nil {
log.Error().Msgf("Command exited: %T %v %v", err, err, args)
app.flash().errf("Command exited: %v", err)
}
})
}
func run(clear bool, app *appView, args ...string) bool {
bin, err := exec.LookPath(os.Getenv("EDITOR"))
if err != nil {
log.Error().Msgf("Unable to find editor command in path %v", err)
return false
}
return app.Suspend(func() {
if err := execute(clear, bin, args...); err != nil {
log.Error().Msgf("Command exited: %T %v %v", err, err, args)
app.flash().errf("Command exited: %v", err)
}
})
}
func execute(clear bool, bin string, args ...string) error {
if clear {
clearScreen()
}
log.Debug().Msgf("Running command > %s %s", bin, strings.Join(args, " "))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
log.Debug().Msg("Command canceled with signal!")
cancel()
}()
cmd := exec.Command(bin, args...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
err := cmd.Run()
log.Debug().Msgf("Command return status %v", err)
select {
case <-ctx.Done():
return errors.New("canceled by operator")
default:
return err
}
}
func clearScreen() {
log.Debug().Msg("Clearing screen...")
fmt.Print("\033[H\033[2J")
}