311 lines
7.3 KiB
Go
311 lines
7.3 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Authors of K9s
|
|
|
|
package config
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
|
|
"github.com/derailed/k9s/internal/client"
|
|
"github.com/derailed/k9s/internal/config/data"
|
|
)
|
|
|
|
// K9s tracks K9s configuration options.
|
|
type K9s struct {
|
|
LiveViewAutoRefresh bool `yaml:"liveViewAutoRefresh"`
|
|
ScreenDumpDir string `yaml:"screenDumpDir,omitempty"`
|
|
RefreshRate int `yaml:"refreshRate"`
|
|
MaxConnRetry int `yaml:"maxConnRetry"`
|
|
ReadOnly bool `yaml:"readOnly"`
|
|
NoExitOnCtrlC bool `yaml:"noExitOnCtrlC"`
|
|
UI UI `yaml:"ui"`
|
|
SkipLatestRevCheck bool `yaml:"skipLatestRevCheck"`
|
|
DisablePodCounting bool `yaml:"disablePodCounting"`
|
|
ShellPod *ShellPod `yaml:"shellPod"`
|
|
ImageScans *ImageScans `yaml:"imageScans"`
|
|
Logger *Logger `yaml:"logger"`
|
|
Thresholds Threshold `yaml:"thresholds"`
|
|
manualRefreshRate int
|
|
manualHeadless *bool
|
|
manualLogoless *bool
|
|
manualCrumbsless *bool
|
|
manualReadOnly *bool
|
|
manualCommand *string
|
|
manualScreenDumpDir *string
|
|
dir *data.Dir
|
|
activeContextName string
|
|
activeConfig *data.Config
|
|
conn client.Connection
|
|
ks data.KubeSettings
|
|
}
|
|
|
|
// NewK9s create a new K9s configuration.
|
|
func NewK9s(conn client.Connection, ks data.KubeSettings) *K9s {
|
|
return &K9s{
|
|
RefreshRate: defaultRefreshRate,
|
|
MaxConnRetry: defaultMaxConnRetry,
|
|
ScreenDumpDir: AppDumpsDir,
|
|
Logger: NewLogger(),
|
|
Thresholds: NewThreshold(),
|
|
ShellPod: NewShellPod(),
|
|
ImageScans: NewImageScans(),
|
|
dir: data.NewDir(AppContextsDir, conn, ks),
|
|
conn: conn,
|
|
ks: ks,
|
|
}
|
|
}
|
|
|
|
func (k *K9s) Save() error {
|
|
if k.activeConfig != nil {
|
|
path := filepath.Join(
|
|
AppContextsDir,
|
|
k.activeConfig.Context.ClusterName,
|
|
k.activeContextName,
|
|
data.MainConfigFile,
|
|
)
|
|
return k.activeConfig.Save(path)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (k *K9s) Refine(k1 *K9s) {
|
|
k.LiveViewAutoRefresh = k1.LiveViewAutoRefresh
|
|
k.ScreenDumpDir = k1.ScreenDumpDir
|
|
k.RefreshRate = k1.RefreshRate
|
|
k.MaxConnRetry = k1.MaxConnRetry
|
|
k.ReadOnly = k1.ReadOnly
|
|
k.NoExitOnCtrlC = k1.NoExitOnCtrlC
|
|
k.UI = k1.UI
|
|
k.SkipLatestRevCheck = k1.SkipLatestRevCheck
|
|
k.DisablePodCounting = k1.DisablePodCounting
|
|
k.ShellPod = k1.ShellPod
|
|
k.ImageScans = k1.ImageScans
|
|
k.Logger = k1.Logger
|
|
k.Thresholds = k1.Thresholds
|
|
}
|
|
|
|
func (k *K9s) Generate(k9sFlags *Flags) {
|
|
if *k9sFlags.RefreshRate != DefaultRefreshRate {
|
|
k.OverrideRefreshRate(*k9sFlags.RefreshRate)
|
|
}
|
|
|
|
k.OverrideHeadless(*k9sFlags.Headless)
|
|
k.OverrideLogoless(*k9sFlags.Logoless)
|
|
k.OverrideCrumbsless(*k9sFlags.Crumbsless)
|
|
k.OverrideReadOnly(*k9sFlags.ReadOnly)
|
|
k.OverrideWrite(*k9sFlags.Write)
|
|
k.OverrideCommand(*k9sFlags.Command)
|
|
k.OverrideScreenDumpDir(*k9sFlags.ScreenDumpDir)
|
|
}
|
|
|
|
// OverrideScreenDumpDir set the screen dump dir manually.
|
|
func (k *K9s) OverrideScreenDumpDir(dir string) {
|
|
k.manualScreenDumpDir = &dir
|
|
}
|
|
|
|
func (k *K9s) GetScreenDumpDir() string {
|
|
screenDumpDir := k.ScreenDumpDir
|
|
if k.manualScreenDumpDir != nil && *k.manualScreenDumpDir != "" {
|
|
screenDumpDir = *k.manualScreenDumpDir
|
|
}
|
|
if screenDumpDir == "" {
|
|
screenDumpDir = AppDumpsDir
|
|
}
|
|
|
|
return screenDumpDir
|
|
}
|
|
|
|
func (k *K9s) Reset() {
|
|
k.activeConfig, k.activeContextName = nil, ""
|
|
}
|
|
|
|
func (k *K9s) ActiveContextDir() string {
|
|
if k.activeConfig == nil {
|
|
return "na"
|
|
}
|
|
|
|
return filepath.Join(
|
|
SanitizeFileName(k.activeConfig.Context.ClusterName),
|
|
SanitizeFileName(k.ActiveContextName()),
|
|
)
|
|
}
|
|
|
|
func (k *K9s) ActiveContextNamespace() (string, error) {
|
|
if k.activeConfig != nil {
|
|
return k.activeConfig.Context.Namespace.Active, nil
|
|
}
|
|
|
|
return "", errors.New("context config is not set")
|
|
}
|
|
|
|
func (k *K9s) ActiveContextName() string {
|
|
return k.activeContextName
|
|
}
|
|
|
|
// ActiveContext returns the currently active context.
|
|
func (k *K9s) ActiveContext() (*data.Context, error) {
|
|
if k.activeConfig != nil {
|
|
return k.activeConfig.Context, nil
|
|
}
|
|
|
|
ct, err := k.ActivateContext(k.activeContextName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ct, nil
|
|
}
|
|
|
|
// ActivateContext initializes the active context is not present.
|
|
func (k *K9s) ActivateContext(n string) (*data.Context, error) {
|
|
k.activeContextName = n
|
|
ct, err := k.ks.GetContext(k.activeContextName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cfg, err := k.dir.Load(n, ct)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
k.activeConfig = cfg
|
|
// If the context specifies a default namespace, use it!
|
|
if k.conn != nil {
|
|
if ns := k.conn.ActiveNamespace(); ns != client.BlankNamespace {
|
|
k.activeConfig.Context.Namespace.Active = ns
|
|
}
|
|
}
|
|
|
|
return cfg.Context, nil
|
|
}
|
|
|
|
// OverrideRefreshRate set the refresh rate manually.
|
|
func (k *K9s) OverrideRefreshRate(r int) {
|
|
k.manualRefreshRate = r
|
|
}
|
|
|
|
// OverrideHeadless toggle the header manually.
|
|
func (k *K9s) OverrideHeadless(b bool) {
|
|
k.manualHeadless = &b
|
|
}
|
|
|
|
// OverrideLogoless toggle the k9s logo manually.
|
|
func (k *K9s) OverrideLogoless(b bool) {
|
|
k.manualLogoless = &b
|
|
}
|
|
|
|
// OverrideCrumbsless tooh the crumbslessness manually.
|
|
func (k *K9s) OverrideCrumbsless(b bool) {
|
|
k.manualCrumbsless = &b
|
|
}
|
|
|
|
// OverrideReadOnly set the readonly mode manually.
|
|
func (k *K9s) OverrideReadOnly(b bool) {
|
|
if b {
|
|
k.manualReadOnly = &b
|
|
}
|
|
}
|
|
|
|
// OverrideWrite set the write mode manually.
|
|
func (k *K9s) OverrideWrite(b bool) {
|
|
if b {
|
|
var flag bool
|
|
k.manualReadOnly = &flag
|
|
}
|
|
}
|
|
|
|
// OverrideCommand set the command manually.
|
|
func (k *K9s) OverrideCommand(cmd string) {
|
|
k.manualCommand = &cmd
|
|
}
|
|
|
|
// IsHeadless returns headless setting.
|
|
func (k *K9s) IsHeadless() bool {
|
|
h := k.UI.Headless
|
|
if k.manualHeadless != nil && *k.manualHeadless {
|
|
h = *k.manualHeadless
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
// IsLogoless returns logoless setting.
|
|
func (k *K9s) IsLogoless() bool {
|
|
h := k.UI.Logoless
|
|
if k.manualLogoless != nil && *k.manualLogoless {
|
|
h = *k.manualLogoless
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
// IsCrumbsless returns crumbsless setting.
|
|
func (k *K9s) IsCrumbsless() bool {
|
|
h := k.UI.Crumbsless
|
|
if k.manualCrumbsless != nil && *k.manualCrumbsless {
|
|
h = *k.manualCrumbsless
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
// GetRefreshRate returns the current refresh rate.
|
|
func (k *K9s) GetRefreshRate() int {
|
|
rate := k.RefreshRate
|
|
if k.manualRefreshRate != 0 {
|
|
rate = k.manualRefreshRate
|
|
}
|
|
|
|
return rate
|
|
}
|
|
|
|
// IsReadOnly returns the readonly setting.
|
|
func (k *K9s) IsReadOnly() bool {
|
|
readOnly := k.ReadOnly
|
|
if k.manualReadOnly != nil {
|
|
readOnly = *k.manualReadOnly
|
|
}
|
|
if k.activeConfig != nil && k.activeConfig.Context.ReadOnly {
|
|
readOnly = true
|
|
}
|
|
|
|
return readOnly
|
|
}
|
|
|
|
func (k *K9s) validateDefaults() {
|
|
if k.RefreshRate <= 0 {
|
|
k.RefreshRate = defaultRefreshRate
|
|
}
|
|
if k.MaxConnRetry <= 0 {
|
|
k.MaxConnRetry = defaultMaxConnRetry
|
|
}
|
|
}
|
|
|
|
// Validate the current configuration.
|
|
func (k *K9s) Validate(c client.Connection, ks data.KubeSettings) {
|
|
k.validateDefaults()
|
|
if k.activeConfig == nil {
|
|
if n, err := ks.CurrentContextName(); err == nil {
|
|
_, _ = k.ActivateContext(n)
|
|
}
|
|
}
|
|
if k.ImageScans == nil {
|
|
k.ImageScans = NewImageScans()
|
|
}
|
|
if k.ShellPod == nil {
|
|
k.ShellPod = NewShellPod()
|
|
}
|
|
k.ShellPod.Validate(c, ks)
|
|
|
|
if k.Logger == nil {
|
|
k.Logger = NewLogger()
|
|
} else {
|
|
k.Logger.Validate(c, ks)
|
|
}
|
|
if k.Thresholds == nil {
|
|
k.Thresholds = NewThreshold()
|
|
}
|
|
k.Thresholds.Validate(c, ks)
|
|
}
|