resolve conflicts

mine
derailed 2020-07-02 18:05:26 -06:00
commit 874226a1b3
9 changed files with 92 additions and 15 deletions

View File

@ -29,6 +29,7 @@ func NewContainer(gvr client.GVR) ResourceViewer {
c.SetEnvFn(c.k9sEnv)
c.GetTable().SetEnterFn(c.viewLogs)
c.GetTable().SetColorerFn(render.Container{}.ColorerFunc())
c.GetTable().SetDecorateFn(c.decorateRows)
c.SetBindKeysFn(c.bindKeys)
c.GetTable().SetDecorateFn(c.portForwardIndicator)
@ -48,6 +49,10 @@ func (c *Container) portForwardIndicator(data render.TableData) render.TableData
return data
}
func (c *Container) decorateRows(data render.TableData) render.TableData {
return decorateCpuMemHeaderRows(c.App(), data)
}
// Name returns the component name.
func (c *Container) Name() string { return containerTitle }

View File

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"github.com/derailed/k9s/internal"
@ -177,3 +178,40 @@ func fqn(ns, n string) string {
}
return ns + "/" + n
}
func decorateCpuMemHeaderRows(app *App, data render.TableData) render.TableData {
for colIndex, header := range data.Header {
check := ""
if header.Name == "%CPU/L" {
check = "cpu"
}
if header.Name == "%MEM/L" {
check = "memory"
}
if len(check) == 0 {
continue
}
for _, re := range data.RowEvents {
if re.Row.Fields[colIndex] == render.NAValue {
continue
}
n, err := strconv.Atoi(re.Row.Fields[colIndex])
if err != nil {
continue
}
if n > 100 {
n = 100
}
severity := app.Config.K9s.Thresholds.LevelFor(check, n)
if severity == config.SeverityLow {
continue
}
color := app.Config.K9s.Thresholds.SeverityColor(check, n)
if len(color) > 0 {
re.Row.Fields[colIndex] = "[" + color + "::b]" + re.Row.Fields[colIndex]
}
}
}
return data
}

View File

@ -4,9 +4,11 @@ import (
"bytes"
"context"
"fmt"
"github.com/atotto/clipboard"
"io"
"os"
"path/filepath"
"regexp"
"strings"
"time"
@ -29,6 +31,9 @@ const (
flushTimeout = 50 * time.Millisecond
)
// InvalidCharsRX contains invalid filename characters.
var invalidPathCharsRX = regexp.MustCompile(`[:/\\]+`)
// Log represents a generic log viewer.
type Log struct {
*tview.Flex
@ -180,13 +185,14 @@ func (l *Log) bindKeys() {
ui.Key4: ui.NewKeyAction("30m", l.sinceCmd(30*60), true),
ui.Key5: ui.NewKeyAction("1h", l.sinceCmd(60*60), true),
tcell.KeyEnter: ui.NewSharedKeyAction("Filter", l.filterCmd, false),
ui.KeyC: ui.NewKeyAction("Clear", l.clearCmd, true),
tcell.KeyCtrlK: ui.NewKeyAction("Clear", l.clearCmd, true),
ui.KeyM: ui.NewKeyAction("Mark", l.markCmd, true),
ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true),
ui.KeyF: ui.NewKeyAction("Toggle FullScreen", l.toggleFullScreenCmd, true),
ui.KeyT: ui.NewKeyAction("Toggle Timestamp", l.toggleTimestampCmd, true),
ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.toggleTextWrapCmd, true),
tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true),
ui.KeyC: ui.NewKeyAction("Copy", l.cpCmd, true),
})
}
@ -284,18 +290,32 @@ func (l *Log) SaveCmd(evt *tcell.EventKey) *tcell.EventKey {
return nil
}
func (l *Log) cpCmd(evt *tcell.EventKey) *tcell.EventKey {
l.app.Flash().Info("Content copied to clipboard...")
if err := clipboard.WriteAll(l.logs.GetText(true)); err != nil {
l.app.Flash().Err(err)
}
return nil
}
func sanitizeFilename(name string) string {
processedString := invalidPathCharsRX.ReplaceAllString(name, "-")
return processedString
}
func ensureDir(dir string) error {
return os.MkdirAll(dir, 0744)
}
func saveData(cluster, name, data string) (string, error) {
dir := filepath.Join(config.K9sDumpDir, cluster)
dir := filepath.Join(config.K9sDumpDir, sanitizeFilename(cluster))
if err := ensureDir(dir); err != nil {
return "", err
}
now := time.Now().UnixNano()
fName := fmt.Sprintf("%s-%d.log", strings.Replace(name, "/", "-", -1), now)
fName := fmt.Sprintf("%s-%d.log", sanitizeFilename(name), now)
path := filepath.Join(dir, fName)
mod := os.O_CREATE | os.O_WRONLY

View File

@ -16,7 +16,7 @@ func TestLogAutoScroll(t *testing.T) {
v.GetModel().Set(dao.LogItems{dao.NewLogItemFromString("blee"), dao.NewLogItemFromString("bozo")})
v.GetModel().Notify()
assert.Equal(t, 14, len(v.Hints()))
assert.Equal(t, 15, len(v.Hints()))
v.toggleAutoScrollCmd(nil)
assert.Equal(t, "Autoscroll: Off FullScreen: Off Timestamps: Off Wrap: Off", v.Indicator().GetText(true))

View File

@ -49,7 +49,7 @@ func (p *Pod) portForwardIndicator(data render.TableData) render.TableData {
}
}
return data
return decorateCpuMemHeaderRows(p.App(), data)
}
func (p *Pod) bindDangerousKeys(aa ui.KeyActions) {

View File

@ -18,12 +18,12 @@ import (
func computeFilename(cluster, ns, title, path string) (string, error) {
now := time.Now().UnixNano()
dir := filepath.Join(config.K9sDumpDir, cluster)
dir := filepath.Join(config.K9sDumpDir, sanitizeFilename(cluster))
if err := ensureDir(dir); err != nil {
return "", err
}
name := title + "-" + strings.Replace(path, "/", "-", -1)
name := title + "-" + sanitizeFilename(path)
if path == "" {
name = title
}

View File

@ -61,13 +61,13 @@ func enableRegion(str string) string {
}
func saveYAML(cluster, name, data string) (string, error) {
dir := filepath.Join(config.K9sDumpDir, cluster)
dir := filepath.Join(config.K9sDumpDir, sanitizeFilename(cluster))
if err := ensureDir(dir); err != nil {
return "", err
}
now := time.Now().UnixNano()
fName := fmt.Sprintf("%s-%d.yml", strings.Replace(name, "/", "-", -1), now)
fName := fmt.Sprintf("%s-%d.yml", sanitizeFilename(name), now)
path := filepath.Join(dir, fName)
mod := os.O_CREATE | os.O_WRONLY

View File

@ -2,9 +2,10 @@
K9s plugins extend the tool to provide additonal functionality via actions to further help you observe or administer your Kubernetes clusters.
| Plugin-Name | Description | Available on Views | Shortcut | Kubectl plugin, external dependencies |
|-----------------|--------------------------------|--------------------|----------|-------------------------------------------|
| log_stern.yml | View resource logs using stern | pods | Ctrl-l | |
| log_jq.yml | View resource logs using jq | pods | Ctrl-j | kubetcl-plugins/kubectl-jq |
| job_suspend.yml | Suspends a running cronjob | cronjobs | Ctrl-s | |
| dive.yml | Dive image layers | containers | d | [Dive](https://github.com/wagoodman/dive) |
| Plugin-Name | Description | Available on Views | Shortcut | Kubectl plugin, external dependencies |
|-----------------|----------------------------------|--------------------|----------|---------------------------------------------------------------------------------------|
| log_stern.yml | View resource logs using stern | pods | Ctrl-l | |
| log_jq.yml | View resource logs using jq | pods | Ctrl-j | kubetcl-plugins/kubectl-jq |
| job_suspend.yml | Suspends a running cronjob | cronjobs | Ctrl-s | |
| dive.yml | Dive image layers | containers | d | [Dive](https://github.com/wagoodman/dive) |
| get-all.yml | get all resources in a namespace | all | g | [Krew](https://krew.sigs.k8s.io/), [ketall](https://github.com/corneliusweig/ketall/) |

13
plugins/get-all.yml Normal file
View File

@ -0,0 +1,13 @@
plugin:
#get all resources in a namespace using the krew get-all plugin
get-all:
shortCut: g
confirm: false
description: get-all
scopes:
- all
command: sh
background: false
args:
- -c
- "kubectl get-all -n $NAMESPACE | less"