k9s/internal/ui/config.go

116 lines
3.1 KiB
Go

package ui
import (
"context"
"fmt"
"path/filepath"
"github.com/derailed/k9s/internal/config"
"github.com/derailed/k9s/internal/render"
"github.com/derailed/tview"
"github.com/fsnotify/fsnotify"
"github.com/rs/zerolog/log"
)
// Synchronizer manages ui event queue.
type synchronizer interface {
QueueUpdateDraw(func()) *tview.Application
QueueUpdate(func()) *tview.Application
}
// Configurator represents an application configurationa.
type Configurator struct {
skinFile string
Config *config.Config
Styles *config.Styles
Bench *config.Bench
}
// HasSkins returns true if a skin file was located.
func (c *Configurator) HasSkins() bool {
return c.skinFile != ""
}
// StylesUpdater watches for skin file changes.
func (c *Configurator) StylesUpdater(ctx context.Context, s synchronizer) error {
if !c.HasSkins() {
return nil
}
w, err := fsnotify.NewWatcher()
if err != nil {
return err
}
go func() {
for {
select {
case evt := <-w.Events:
_ = evt
s.QueueUpdateDraw(func() {
c.RefreshStyles(c.Config.K9s.CurrentCluster)
})
case err := <-w.Errors:
log.Info().Err(err).Msg("Skin watcher failed")
return
case <-ctx.Done():
log.Debug().Msgf("SkinWatcher Done `%s!!", c.skinFile)
if err := w.Close(); err != nil {
log.Error().Err(err).Msg("Closing watcher")
}
return
}
}
}()
log.Debug().Msgf("SkinWatcher watching `%s", c.skinFile)
return w.Add(c.skinFile)
}
// InitBench load benchmark configuration if any.
func (c *Configurator) InitBench(cluster string) {
var err error
if c.Bench, err = config.NewBench(BenchConfig(cluster)); err != nil {
log.Info().Err(err).Msg("No benchmark config file found, using defaults.")
}
}
// BenchConfig location of the benchmarks configuration file.
func BenchConfig(cluster string) string {
return filepath.Join(config.K9sHome, config.K9sBench+"-"+cluster+".yml")
}
// RefreshStyles load for skin configuration changes.
func (c *Configurator) RefreshStyles(cluster string) {
clusterSkins := filepath.Join(config.K9sHome, fmt.Sprintf("%s_skin.yml", cluster))
if c.Styles == nil {
c.Styles = config.NewStyles()
}
if err := c.Styles.Load(clusterSkins); err != nil {
log.Info().Msgf("No cluster specific skin file found -- %s", clusterSkins)
} else {
log.Debug().Msgf("Found cluster skins %s", clusterSkins)
c.updateStyles(clusterSkins)
return
}
if err := c.Styles.Load(config.K9sStylesFile); err != nil {
log.Info().Msgf("No skin file found -- %s. Loading stock skins.", config.K9sStylesFile)
c.updateStyles("")
return
}
c.updateStyles(config.K9sStylesFile)
}
func (c *Configurator) updateStyles(f string) {
c.skinFile = f
c.Styles.Update()
render.StdColor = config.AsColor(c.Styles.Frame().Status.NewColor)
render.AddColor = config.AsColor(c.Styles.Frame().Status.AddColor)
render.ModColor = config.AsColor(c.Styles.Frame().Status.ModifyColor)
render.ErrColor = config.AsColor(c.Styles.Frame().Status.ErrorColor)
render.HighlightColor = config.AsColor(c.Styles.Frame().Status.HighlightColor)
render.CompletedColor = config.AsColor(c.Styles.Frame().Status.CompletedColor)
}