Add customizable dump directory property (#1321)
* Add customizable dump directory property Add property for configuration file and arguments * Resolve Comments Co-authored-by: Artem Vlasov <artemv@tradeix.com>mine
parent
08ee61a298
commit
0249f7cf2c
|
|
@ -355,6 +355,8 @@ K9s uses aliases to navigate most K8s resources.
|
||||||
- default
|
- default
|
||||||
view:
|
view:
|
||||||
active: dp
|
active: dp
|
||||||
|
# The path to screen dump. Default: '%temp_dir%/k9s-screens-%username%' (k9s info)
|
||||||
|
screenDumpDir: /tmp
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
25
cmd/info.go
25
cmd/info.go
|
|
@ -6,7 +6,10 @@ import (
|
||||||
"github.com/derailed/k9s/internal/color"
|
"github.com/derailed/k9s/internal/color"
|
||||||
"github.com/derailed/k9s/internal/config"
|
"github.com/derailed/k9s/internal/config"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func infoCmd() *cobra.Command {
|
func infoCmd() *cobra.Command {
|
||||||
|
|
@ -26,7 +29,7 @@ func printInfo() {
|
||||||
printLogo(color.Cyan)
|
printLogo(color.Cyan)
|
||||||
printTuple(fmat, "Configuration", config.K9sConfigFile, color.Cyan)
|
printTuple(fmat, "Configuration", config.K9sConfigFile, color.Cyan)
|
||||||
printTuple(fmat, "Logs", config.DefaultLogFile, color.Cyan)
|
printTuple(fmat, "Logs", config.DefaultLogFile, color.Cyan)
|
||||||
printTuple(fmat, "Screen Dumps", config.K9sDumpDir, color.Cyan)
|
printTuple(fmat, "Screen Dumps", getScreenDumpDirForInfo(), color.Cyan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printLogo(c color.Paint) {
|
func printLogo(c color.Paint) {
|
||||||
|
|
@ -35,3 +38,23 @@ func printLogo(c color.Paint) {
|
||||||
}
|
}
|
||||||
fmt.Fprintln(out)
|
fmt.Fprintln(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getScreenDumpDirForInfo get default screen dump config dir or from config.K9sConfigFile configuration.
|
||||||
|
func getScreenDumpDirForInfo() string {
|
||||||
|
if config.K9sConfigFile == "" {
|
||||||
|
return config.K9sDefaultScreenDumpDir
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.ReadFile(config.K9sConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("Reads k9s config file %v", err)
|
||||||
|
return config.K9sDefaultScreenDumpDir
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg config.Config
|
||||||
|
if err := yaml.Unmarshal(f, &cfg); err != nil {
|
||||||
|
log.Error().Err(err).Msgf("Unmarshal k9s config %v", err)
|
||||||
|
return config.K9sDefaultScreenDumpDir
|
||||||
|
}
|
||||||
|
return cfg.K9s.GetScreenDumpDir()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/derailed/k9s/internal/config"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_getScreenDumpDirForInfo(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
k9sConfigFile string
|
||||||
|
expectedScreenDumpDir string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "withK9sConfigFile",
|
||||||
|
k9sConfigFile: "testdata/k9s.yml",
|
||||||
|
expectedScreenDumpDir: "/tmp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "withEmptyK9sConfigFile",
|
||||||
|
k9sConfigFile: "",
|
||||||
|
expectedScreenDumpDir: config.K9sDefaultScreenDumpDir,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "withInvalidK9sConfigFilePath",
|
||||||
|
k9sConfigFile: "invalid",
|
||||||
|
expectedScreenDumpDir: config.K9sDefaultScreenDumpDir,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "withScreenDumpDirEmptyInK9sConfigFile",
|
||||||
|
k9sConfigFile: "testdata/k9s1.yml",
|
||||||
|
expectedScreenDumpDir: config.K9sDefaultScreenDumpDir,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
initK9sConfigFile := config.K9sConfigFile
|
||||||
|
|
||||||
|
config.K9sConfigFile = tt.k9sConfigFile
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expectedScreenDumpDir, getScreenDumpDirForInfo())
|
||||||
|
|
||||||
|
config.K9sConfigFile = initK9sConfigFile
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -108,6 +108,7 @@ func loadConfiguration() *config.Config {
|
||||||
k9sCfg.K9s.OverrideReadOnly(*k9sFlags.ReadOnly)
|
k9sCfg.K9s.OverrideReadOnly(*k9sFlags.ReadOnly)
|
||||||
k9sCfg.K9s.OverrideWrite(*k9sFlags.Write)
|
k9sCfg.K9s.OverrideWrite(*k9sFlags.Write)
|
||||||
k9sCfg.K9s.OverrideCommand(*k9sFlags.Command)
|
k9sCfg.K9s.OverrideCommand(*k9sFlags.Command)
|
||||||
|
k9sCfg.K9s.OverrideScreenDumpDir(*k9sFlags.ScreenDumpDir)
|
||||||
|
|
||||||
if err := k9sCfg.Refine(k8sFlags, k9sFlags, k8sCfg); err != nil {
|
if err := k9sCfg.Refine(k8sFlags, k9sFlags, k8sCfg); err != nil {
|
||||||
log.Error().Err(err).Msgf("refine failed")
|
log.Error().Err(err).Msgf("refine failed")
|
||||||
|
|
@ -210,6 +211,13 @@ func initK9sFlags() {
|
||||||
false,
|
false,
|
||||||
"Sets write mode by overriding the readOnly configuration setting",
|
"Sets write mode by overriding the readOnly configuration setting",
|
||||||
)
|
)
|
||||||
|
rootCmd.Flags().StringVar(
|
||||||
|
k9sFlags.ScreenDumpDir,
|
||||||
|
"screen-dump-dir",
|
||||||
|
"",
|
||||||
|
"Sets a path to a dir for a screen dumps",
|
||||||
|
)
|
||||||
|
rootCmd.Flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initK8sFlags() {
|
func initK8sFlags() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
k9s:
|
||||||
|
refreshRate: 2
|
||||||
|
readOnly: false
|
||||||
|
logger:
|
||||||
|
tail: 200
|
||||||
|
buffer: 2000
|
||||||
|
currentContext: minikube
|
||||||
|
currentCluster: minikube
|
||||||
|
clusters:
|
||||||
|
minikube:
|
||||||
|
namespace:
|
||||||
|
active: kube-system
|
||||||
|
favorites:
|
||||||
|
- default
|
||||||
|
- kube-public
|
||||||
|
- istio-system
|
||||||
|
- all
|
||||||
|
- kube-system
|
||||||
|
view:
|
||||||
|
active: ctx
|
||||||
|
fred:
|
||||||
|
namespace:
|
||||||
|
active: default
|
||||||
|
favorites:
|
||||||
|
- default
|
||||||
|
- kube-public
|
||||||
|
- istio-system
|
||||||
|
- all
|
||||||
|
- kube-system
|
||||||
|
view:
|
||||||
|
active: po
|
||||||
|
screenDumpDir: /tmp
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
k9s:
|
||||||
|
refreshRate: 10
|
||||||
|
namespace:
|
||||||
|
active: fred
|
||||||
|
favorites:
|
||||||
|
- blee
|
||||||
|
- duh
|
||||||
|
- crap
|
||||||
|
|
@ -19,8 +19,8 @@ const K9sConfig = "K9SCONFIG"
|
||||||
var (
|
var (
|
||||||
// K9sConfigFile represents K9s config file location.
|
// K9sConfigFile represents K9s config file location.
|
||||||
K9sConfigFile = filepath.Join(K9sHome(), "config.yml")
|
K9sConfigFile = filepath.Join(K9sHome(), "config.yml")
|
||||||
// K9sDumpDir represents a directory where K9s screen dumps will be persisted.
|
// K9sDefaultScreenDumpDir represents a default directory where K9s screen dumps will be persisted.
|
||||||
K9sDumpDir = filepath.Join(os.TempDir(), fmt.Sprintf("k9s-screens-%s", MustK9sUser()))
|
K9sDefaultScreenDumpDir = filepath.Join(os.TempDir(), fmt.Sprintf("k9s-screens-%s", MustK9sUser()))
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -116,6 +116,8 @@ func (c *Config) Refine(flags *genericclioptions.ConfigFlags, k9sFlags *Flags, c
|
||||||
c.K9s.CurrentCluster = *flags.ClusterName
|
c.K9s.CurrentCluster = *flags.ClusterName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnsurePath(c.K9s.GetScreenDumpDir(), DefaultDirMod)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,7 @@ var expectedConfig = `k9s:
|
||||||
memory:
|
memory:
|
||||||
critical: 90
|
critical: 90
|
||||||
warn: 70
|
warn: 70
|
||||||
|
screenDumpDir: /tmp
|
||||||
`
|
`
|
||||||
|
|
||||||
var resetConfig = `k9s:
|
var resetConfig = `k9s:
|
||||||
|
|
@ -393,4 +394,5 @@ var resetConfig = `k9s:
|
||||||
memory:
|
memory:
|
||||||
critical: 90
|
critical: 90
|
||||||
warn: 70
|
warn: 70
|
||||||
|
screenDumpDir: /tmp
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ type Flags struct {
|
||||||
ReadOnly *bool
|
ReadOnly *bool
|
||||||
Write *bool
|
Write *bool
|
||||||
Crumbsless *bool
|
Crumbsless *bool
|
||||||
|
ScreenDumpDir *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFlags returns new configuration flags.
|
// NewFlags returns new configuration flags.
|
||||||
|
|
@ -47,6 +48,7 @@ func NewFlags() *Flags {
|
||||||
ReadOnly: boolPtr(false),
|
ReadOnly: boolPtr(false),
|
||||||
Write: boolPtr(false),
|
Write: boolPtr(false),
|
||||||
Crumbsless: boolPtr(false),
|
Crumbsless: boolPtr(false),
|
||||||
|
ScreenDumpDir: strPtr(K9sDefaultScreenDumpDir),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,14 @@ type K9s struct {
|
||||||
CurrentCluster string `yaml:"currentCluster"`
|
CurrentCluster string `yaml:"currentCluster"`
|
||||||
Clusters map[string]*Cluster `yaml:"clusters,omitempty"`
|
Clusters map[string]*Cluster `yaml:"clusters,omitempty"`
|
||||||
Thresholds Threshold `yaml:"thresholds"`
|
Thresholds Threshold `yaml:"thresholds"`
|
||||||
|
ScreenDumpDir string `yaml:"screenDumpDir"`
|
||||||
manualRefreshRate int
|
manualRefreshRate int
|
||||||
manualHeadless *bool
|
manualHeadless *bool
|
||||||
manualLogoless *bool
|
manualLogoless *bool
|
||||||
manualCrumbsless *bool
|
manualCrumbsless *bool
|
||||||
manualReadOnly *bool
|
manualReadOnly *bool
|
||||||
manualCommand *string
|
manualCommand *string
|
||||||
|
manualScreenDumpDir *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewK9s create a new K9s configuration.
|
// NewK9s create a new K9s configuration.
|
||||||
|
|
@ -40,6 +42,7 @@ func NewK9s() *K9s {
|
||||||
Logger: NewLogger(),
|
Logger: NewLogger(),
|
||||||
Clusters: make(map[string]*Cluster),
|
Clusters: make(map[string]*Cluster),
|
||||||
Thresholds: NewThreshold(),
|
Thresholds: NewThreshold(),
|
||||||
|
ScreenDumpDir: K9sDefaultScreenDumpDir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +94,11 @@ func (k *K9s) OverrideCommand(cmd string) {
|
||||||
k.manualCommand = &cmd
|
k.manualCommand = &cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OverrideScreenDumpDir set the screen dump dir manually.
|
||||||
|
func (k *K9s) OverrideScreenDumpDir(dir string) {
|
||||||
|
k.manualScreenDumpDir = &dir
|
||||||
|
}
|
||||||
|
|
||||||
// IsHeadless returns headless setting.
|
// IsHeadless returns headless setting.
|
||||||
func (k *K9s) IsHeadless() bool {
|
func (k *K9s) IsHeadless() bool {
|
||||||
h := k.Headless
|
h := k.Headless
|
||||||
|
|
@ -155,6 +163,20 @@ func (k *K9s) ActiveCluster() *Cluster {
|
||||||
return k.Clusters[k.CurrentCluster]
|
return k.Clusters[k.CurrentCluster]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *K9s) GetScreenDumpDir() string {
|
||||||
|
screenDumpDir := k.ScreenDumpDir
|
||||||
|
|
||||||
|
if k.manualScreenDumpDir != nil && *k.manualScreenDumpDir != "" {
|
||||||
|
screenDumpDir = *k.manualScreenDumpDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if screenDumpDir == "" {
|
||||||
|
return K9sDefaultScreenDumpDir
|
||||||
|
}
|
||||||
|
|
||||||
|
return screenDumpDir
|
||||||
|
}
|
||||||
|
|
||||||
func (k *K9s) validateDefaults() {
|
func (k *K9s) validateDefaults() {
|
||||||
if k.RefreshRate <= 0 {
|
if k.RefreshRate <= 0 {
|
||||||
k.RefreshRate = defaultRefreshRate
|
k.RefreshRate = defaultRefreshRate
|
||||||
|
|
@ -162,6 +184,9 @@ func (k *K9s) validateDefaults() {
|
||||||
if k.MaxConnRetry <= 0 {
|
if k.MaxConnRetry <= 0 {
|
||||||
k.MaxConnRetry = defaultMaxConnRetry
|
k.MaxConnRetry = defaultMaxConnRetry
|
||||||
}
|
}
|
||||||
|
if k.ScreenDumpDir == "" {
|
||||||
|
k.ScreenDumpDir = K9sDefaultScreenDumpDir
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *K9s) validateClusters(c client.Connection, ks KubeSettings) {
|
func (k *K9s) validateClusters(c client.Connection, ks KubeSettings) {
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ func TestK9sValidate(t *testing.T) {
|
||||||
assert.Equal(t, "ctx1", c.CurrentContext)
|
assert.Equal(t, "ctx1", c.CurrentContext)
|
||||||
assert.Equal(t, "c1", c.CurrentCluster)
|
assert.Equal(t, "c1", c.CurrentCluster)
|
||||||
assert.Equal(t, 1, len(c.Clusters))
|
assert.Equal(t, 1, len(c.Clusters))
|
||||||
|
assert.Equal(t, config.K9sDefaultScreenDumpDir, c.GetScreenDumpDir())
|
||||||
_, ok := c.Clusters[c.CurrentCluster]
|
_, ok := c.Clusters[c.CurrentCluster]
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
}
|
}
|
||||||
|
|
@ -130,3 +131,38 @@ func TestK9sActiveCluster(t *testing.T) {
|
||||||
assert.Equal(t, "kube-system", cl.Namespace.Active)
|
assert.Equal(t, "kube-system", cl.Namespace.Active)
|
||||||
assert.Equal(t, 5, len(cl.Namespace.Favorites))
|
assert.Equal(t, 5, len(cl.Namespace.Favorites))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetScreenDumpDir(t *testing.T) {
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
assert.Nil(t, cfg.Load("testdata/k9s.yml"))
|
||||||
|
|
||||||
|
assert.Equal(t, "/tmp", cfg.K9s.GetScreenDumpDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetScreenDumpDirOverride(t *testing.T) {
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
assert.Nil(t, cfg.Load("testdata/k9s.yml"))
|
||||||
|
cfg.K9s.OverrideScreenDumpDir("/override")
|
||||||
|
|
||||||
|
assert.Equal(t, "/override", cfg.K9s.GetScreenDumpDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetScreenDumpDirOverrideEmpty(t *testing.T) {
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
assert.Nil(t, cfg.Load("testdata/k9s.yml"))
|
||||||
|
cfg.K9s.OverrideScreenDumpDir("")
|
||||||
|
|
||||||
|
assert.Equal(t, "/tmp", cfg.K9s.GetScreenDumpDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetScreenDumpDirEmpty(t *testing.T) {
|
||||||
|
mk := NewMockKubeSettings()
|
||||||
|
cfg := config.NewConfig(mk)
|
||||||
|
assert.Nil(t, cfg.Load("testdata/k9s1.yml"))
|
||||||
|
cfg.K9s.OverrideScreenDumpDir("")
|
||||||
|
|
||||||
|
assert.Equal(t, config.K9sDefaultScreenDumpDir, cfg.K9s.GetScreenDumpDir())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,4 @@ k9s:
|
||||||
- kube-system
|
- kube-system
|
||||||
view:
|
view:
|
||||||
active: po
|
active: po
|
||||||
|
screenDumpDir: /tmp
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ func (d *Details) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Details) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (d *Details) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if path, err := saveYAML(d.app.Config.K9s.CurrentCluster, d.title, d.text.GetText(true)); err != nil {
|
if path, err := saveYAML(d.app.Config.K9s.GetScreenDumpDir(), d.app.Config.K9s.CurrentCluster, d.title, d.text.GetText(true)); err != nil {
|
||||||
d.app.Flash().Err(err)
|
d.app.Flash().Err(err)
|
||||||
} else {
|
} else {
|
||||||
d.app.Flash().Infof("Log %s saved successfully!", path)
|
d.app.Flash().Infof("Log %s saved successfully!", path)
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ func (v *LiveView) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *LiveView) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (v *LiveView) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if path, err := saveYAML(v.app.Config.K9s.CurrentCluster, v.title, v.text.GetText(true)); err != nil {
|
if path, err := saveYAML(v.app.Config.K9s.GetScreenDumpDir(), v.app.Config.K9s.CurrentCluster, v.title, v.text.GetText(true)); err != nil {
|
||||||
v.app.Flash().Err(err)
|
v.app.Flash().Err(err)
|
||||||
} else {
|
} else {
|
||||||
v.app.Flash().Infof("Log %s saved successfully!", path)
|
v.app.Flash().Infof("Log %s saved successfully!", path)
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ func (l *Log) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
// SaveCmd dumps the logs to file.
|
// SaveCmd dumps the logs to file.
|
||||||
func (l *Log) SaveCmd(*tcell.EventKey) *tcell.EventKey {
|
func (l *Log) SaveCmd(*tcell.EventKey) *tcell.EventKey {
|
||||||
if path, err := saveData(l.app.Config.K9s.CurrentContext, l.model.GetPath(), l.logs.GetText(true)); err != nil {
|
if path, err := saveData(l.app.Config.K9s.GetScreenDumpDir(), l.app.Config.K9s.CurrentContext, l.model.GetPath(), l.logs.GetText(true)); err != nil {
|
||||||
l.app.Flash().Err(err)
|
l.app.Flash().Err(err)
|
||||||
} else {
|
} else {
|
||||||
l.app.Flash().Infof("Log %s saved successfully!", path)
|
l.app.Flash().Infof("Log %s saved successfully!", path)
|
||||||
|
|
@ -429,8 +429,8 @@ func ensureDir(dir string) error {
|
||||||
return os.MkdirAll(dir, 0744)
|
return os.MkdirAll(dir, 0744)
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveData(cluster, name, data string) (string, error) {
|
func saveData(screenDumpDir, cluster, name, data string) (string, error) {
|
||||||
dir := filepath.Join(config.K9sDumpDir, dao.SanitizeFilename(cluster))
|
dir := filepath.Join(screenDumpDir, dao.SanitizeFilename(cluster))
|
||||||
if err := ensureDir(dir); err != nil {
|
if err := ensureDir(dir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,7 @@ func TestLogViewSave(t *testing.T) {
|
||||||
ii.Lines(0, false, ll)
|
ii.Lines(0, false, ll)
|
||||||
v.Flush(ll)
|
v.Flush(ll)
|
||||||
|
|
||||||
config.K9sDumpDir = "/tmp"
|
dir := filepath.Join(app.Config.K9s.GetScreenDumpDir(), app.Config.K9s.CurrentCluster)
|
||||||
dir := filepath.Join(config.K9sDumpDir, app.Config.K9s.CurrentCluster)
|
|
||||||
c1, _ := os.ReadDir(dir)
|
c1, _ := os.ReadDir(dir)
|
||||||
v.SaveCmd(nil)
|
v.SaveCmd(nil)
|
||||||
c2, _ := os.ReadDir(dir)
|
c2, _ := os.ReadDir(dir)
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ func (l *Logger) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (l *Logger) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if path, err := saveYAML(l.app.Config.K9s.CurrentCluster, l.title, l.GetText(true)); err != nil {
|
if path, err := saveYAML(l.app.Config.K9s.GetScreenDumpDir(), l.app.Config.K9s.CurrentCluster, l.title, l.GetText(true)); err != nil {
|
||||||
l.app.Flash().Err(err)
|
l.app.Flash().Err(err)
|
||||||
} else {
|
} else {
|
||||||
l.app.Flash().Infof("Log %s saved successfully!", path)
|
l.app.Flash().Infof("Log %s saved successfully!", path)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ func NewScreenDump(gvr client.GVR) ResourceViewer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ScreenDump) dirContext(ctx context.Context) context.Context {
|
func (s *ScreenDump) dirContext(ctx context.Context) context.Context {
|
||||||
dir := filepath.Join(config.K9sDumpDir, s.App().Config.K9s.CurrentCluster)
|
dir := filepath.Join(s.App().Config.K9s.GetScreenDumpDir(), s.App().Config.K9s.CurrentCluster)
|
||||||
log.Debug().Msgf("SD-DIR %q", dir)
|
log.Debug().Msgf("SD-DIR %q", dir)
|
||||||
config.EnsureFullPath(dir, config.DefaultDirMod)
|
config.EnsureFullPath(dir, config.DefaultDirMod)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ func (t *Table) BufferActive(state bool, k model.BufferKind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (t *Table) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if path, err := saveTable(t.app.Config.K9s.CurrentCluster, t.GVR().R(), t.Path, t.GetFilteredData()); err != nil {
|
if path, err := saveTable(t.app.Config.K9s.GetScreenDumpDir(), t.app.Config.K9s.CurrentCluster, t.GVR().R(), t.Path, t.GetFilteredData()); err != nil {
|
||||||
t.app.Flash().Err(err)
|
t.app.Flash().Err(err)
|
||||||
} else {
|
} else {
|
||||||
t.app.Flash().Infof("File %s saved successfully!", path)
|
t.app.Flash().Infof("File %s saved successfully!", path)
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
"github.com/derailed/k9s/internal/config"
|
|
||||||
"github.com/derailed/k9s/internal/dao"
|
"github.com/derailed/k9s/internal/dao"
|
||||||
"github.com/derailed/k9s/internal/render"
|
"github.com/derailed/k9s/internal/render"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func computeFilename(cluster, ns, title, path string) (string, error) {
|
func computeFilename(screenDumpDir, cluster, ns, title, path string) (string, error) {
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
|
|
||||||
dir := filepath.Join(config.K9sDumpDir, dao.SanitizeFilename(cluster))
|
dir := filepath.Join(screenDumpDir, dao.SanitizeFilename(cluster))
|
||||||
if err := ensureDir(dir); err != nil {
|
if err := ensureDir(dir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -39,13 +38,13 @@ func computeFilename(cluster, ns, title, path string) (string, error) {
|
||||||
return strings.ToLower(filepath.Join(dir, fName)), nil
|
return strings.ToLower(filepath.Join(dir, fName)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveTable(cluster, title, path string, data render.TableData) (string, error) {
|
func saveTable(screenDumpDir, cluster, title, path string, data render.TableData) (string, error) {
|
||||||
ns := data.Namespace
|
ns := data.Namespace
|
||||||
if client.IsClusterWide(ns) {
|
if client.IsClusterWide(ns) {
|
||||||
ns = client.NamespaceAll
|
ns = client.NamespaceAll
|
||||||
}
|
}
|
||||||
|
|
||||||
fPath, err := computeFilename(cluster, ns, title, path)
|
fPath, err := computeFilename(screenDumpDir, cluster, ns, title, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func TestTableSave(t *testing.T) {
|
||||||
v.Init(makeContext())
|
v.Init(makeContext())
|
||||||
v.SetTitle("k9s-test")
|
v.SetTitle("k9s-test")
|
||||||
|
|
||||||
dir := filepath.Join(config.K9sDumpDir, v.app.Config.K9s.CurrentCluster)
|
dir := filepath.Join(v.app.Config.K9s.GetScreenDumpDir(), v.app.Config.K9s.CurrentCluster)
|
||||||
c1, _ := os.ReadDir(dir)
|
c1, _ := os.ReadDir(dir)
|
||||||
v.saveCmd(nil)
|
v.saveCmd(nil)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ func enableRegion(str string) string {
|
||||||
return strings.ReplaceAll(strings.ReplaceAll(str, "<<<", "["), ">>>", "]")
|
return strings.ReplaceAll(strings.ReplaceAll(str, "<<<", "["), ">>>", "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveYAML(cluster, name, data string) (string, error) {
|
func saveYAML(screenDumpDir, cluster, name, data string) (string, error) {
|
||||||
dir := filepath.Join(config.K9sDumpDir, dao.SanitizeFilename(cluster))
|
dir := filepath.Join(screenDumpDir, dao.SanitizeFilename(cluster))
|
||||||
if err := ensureDir(dir); err != nil {
|
if err := ensureDir(dir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue