155 lines
2.9 KiB
Go
155 lines
2.9 KiB
Go
package views
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
"github.com/derailed/k9s/internal/resource"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type subjectViewer interface {
|
|
resourceViewer
|
|
|
|
setSubject(s string)
|
|
}
|
|
|
|
type command struct {
|
|
app *appView
|
|
history *cmdStack
|
|
}
|
|
|
|
func newCommand(app *appView) *command {
|
|
return &command{app: app, history: newCmdStack()}
|
|
}
|
|
|
|
func (c *command) lastCmd() bool {
|
|
return c.history.last()
|
|
}
|
|
|
|
func (c *command) pushCmd(cmd string) {
|
|
c.history.push(cmd)
|
|
c.app.crumbs().update(c.history.stack)
|
|
}
|
|
|
|
func (c *command) previousCmd() (string, bool) {
|
|
c.history.pop()
|
|
c.app.crumbs().update(c.history.stack)
|
|
|
|
return c.history.top()
|
|
}
|
|
|
|
// DefaultCmd reset default command ie show pods.
|
|
func (c *command) defaultCmd() {
|
|
c.pushCmd(c.app.config.ActiveView())
|
|
c.run(c.app.config.ActiveView())
|
|
}
|
|
|
|
// Helpers...
|
|
|
|
var policyMatcher = regexp.MustCompile(`\Apol\s([u|g|s]):([\w-:]+)\b`)
|
|
|
|
func (c *command) isStdCmd(cmd string) bool {
|
|
switch {
|
|
case cmd == "q", cmd == "quit":
|
|
c.app.BailOut()
|
|
return true
|
|
case cmd == "?", cmd == "help":
|
|
c.app.inject(newHelpView(c.app, c.app.currentView()))
|
|
return true
|
|
case cmd == "alias":
|
|
c.app.inject(newAliasView(c.app, c.app.currentView()))
|
|
return true
|
|
case policyMatcher.MatchString(cmd):
|
|
tokens := policyMatcher.FindAllStringSubmatch(cmd, -1)
|
|
if len(tokens) == 1 && len(tokens[0]) == 3 {
|
|
c.app.inject(newPolicyView(c.app, tokens[0][1], tokens[0][2]))
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (c *command) isAliasCmd(cmd string) bool {
|
|
|
|
cmds := make(map[string]resCmd, 30)
|
|
resourceViews(c.app.conn(), cmds)
|
|
res, ok := cmds[cmd]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
var r resource.List
|
|
if res.listFn != nil {
|
|
r = res.listFn(c.app.conn(), resource.DefaultNamespace)
|
|
}
|
|
|
|
v := res.viewFn(res.title, c.app, r)
|
|
if res.colorerFn != nil {
|
|
v.setColorerFn(res.colorerFn)
|
|
}
|
|
if res.enterFn != nil {
|
|
v.setEnterFn(res.enterFn)
|
|
}
|
|
if res.decorateFn != nil {
|
|
v.setDecorateFn(res.decorateFn)
|
|
}
|
|
|
|
const fmat = "Viewing resource %s..."
|
|
c.app.flash().infof(fmat, res.title)
|
|
log.Debug().Msgf("Running command %s", cmd)
|
|
c.exec(cmd, v)
|
|
|
|
return true
|
|
}
|
|
|
|
func (c *command) isCRDCmd(cmd string) bool {
|
|
crds := map[string]resCmd{}
|
|
allCRDs(c.app.conn(), crds)
|
|
res, ok := crds[cmd]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
name := res.plural
|
|
if name == "" {
|
|
name = res.singular
|
|
}
|
|
v := newResourceView(
|
|
res.title,
|
|
c.app,
|
|
resource.NewCustomList(c.app.conn(), "", res.api, res.version, name),
|
|
)
|
|
v.setColorerFn(defaultColorer)
|
|
c.exec(cmd, v)
|
|
|
|
return true
|
|
}
|
|
|
|
// Exec the command by showing associated display.
|
|
func (c *command) run(cmd string) bool {
|
|
if c.isStdCmd(cmd) {
|
|
return true
|
|
}
|
|
|
|
if c.isAliasCmd(cmd) {
|
|
return true
|
|
}
|
|
|
|
if c.isCRDCmd(cmd) {
|
|
return true
|
|
}
|
|
|
|
c.app.flash().warnf("Huh? `%s` command not found", cmd)
|
|
return false
|
|
}
|
|
|
|
func (c *command) exec(cmd string, v igniter) {
|
|
if v == nil {
|
|
return
|
|
}
|
|
|
|
c.app.config.SetActiveView(cmd)
|
|
c.app.config.Save()
|
|
c.app.inject(v)
|
|
}
|