From 67e75494525a3f4e4031bc7dd50f940da909c0f2 Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Fri, 17 Jan 2025 14:27:27 +0000 Subject: [PATCH] Add k9s Signed-off-by: Nikolaos Karaolidis --- .../configs/user/console/docker/default.nix | 8 +- .../user/console/kubernetes/default.nix | 74 +++++++---- .../console/kubernetes/remove-splash.patch | 123 ++++++++++++++++++ .../user/console/kubernetes/theme.yaml | 117 +++++++++++++++++ 4 files changed, 299 insertions(+), 23 deletions(-) create mode 100644 hosts/common/configs/user/console/kubernetes/remove-splash.patch create mode 100644 hosts/common/configs/user/console/kubernetes/theme.yaml diff --git a/hosts/common/configs/user/console/docker/default.nix b/hosts/common/configs/user/console/docker/default.nix index 5f5f110..f86199f 100644 --- a/hosts/common/configs/user/console/docker/default.nix +++ b/hosts/common/configs/user/console/docker/default.nix @@ -27,7 +27,13 @@ }; }; - home-manager.users.${user}.home.packages = with pkgs; [ docker-compose ]; + home-manager.users.${user}.home = { + packages = with pkgs; [ docker-compose ]; + + sessionVariables = { + DOCKER_CONFIG = "${home}/.config/docker"; + }; + }; } // lib.mkIf config.virtualisation.docker.rootless.enable { environment.persistence."/persist"."${home}/.local/share/docker" = { }; diff --git a/hosts/common/configs/user/console/kubernetes/default.nix b/hosts/common/configs/user/console/kubernetes/default.nix index 7e18072..69660d1 100644 --- a/hosts/common/configs/user/console/kubernetes/default.nix +++ b/hosts/common/configs/user/console/kubernetes/default.nix @@ -4,6 +4,16 @@ }: { pkgs, ... }: { + nixpkgs.overlays = [ + (final: prev: { + k9s = prev.k9s.overrideAttrs (oldAttrs: { + patches = oldAttrs.patches or [ ] ++ [ ./remove-splash.patch ]; + }); + }) + ]; + + environment.persistence."/cache"."${home}/.kube/cache" = { }; + home-manager.users.${user} = { home.packages = with pkgs; [ kubectl @@ -11,32 +21,52 @@ kind ]; - programs.zsh = { - initExtra = '' - kubeswitch() { - local target="$HOME/.kube/$1" - local config="$HOME/.kube/config" + programs = { + k9s = { + enable = true; - if [[ -f "$target" && "$target" != "$config" ]]; then - ln -sf "$target" "$config" - echo "Switched kube context to $1" - p10k reload - else - echo "Invalid kube context: $1" - echo "Ensure the file exists in ~/.kube" - fi - } + settings.k9s = { + skipLatestRevCheck = true; + liveViewAutoRefresh = true; + refreshRate = 1; - _kubeswitch_completion() { - local dir="$HOME/.kube" - local config="$dir/config" - compadd -- ''${(f)"$(find "$dir" -maxdepth 1 \( -type f -o -type l \) -not -name 'config' -exec basename {} \;)"} - } + ui = { + skin = "matugen"; + logoless = true; + reactive = true; + }; + }; + }; - compdef _kubeswitch_completion kubeswitch - ''; + zsh = { + initExtra = '' + kubeswitch() { + local target="$HOME/.kube/$1" + local config="$HOME/.kube/config" - p10k.extraRightPromptElements = [ "kubecontext" ]; + if [[ -f "$target" && "$target" != "$config" ]]; then + ln -sf "$target" "$config" + echo "Switched kube context to $1" + p10k reload + else + echo "Invalid kube context: $1" + echo "Ensure the file exists in ~/.kube" + fi + } + + _kubeswitch_completion() { + local dir="$HOME/.kube" + local config="$dir/config" + compadd -- ''${(f)"$(find "$dir" -maxdepth 1 \( -type f -o -type l \) -not -name 'config' -exec basename {} \;)"} + } + + compdef _kubeswitch_completion kubeswitch + ''; + + p10k.extraRightPromptElements = [ "kubecontext" ]; + }; }; + + theme.template."${home}/.config/k9s/skins/matugen.yaml".source = ./theme.yaml; }; } diff --git a/hosts/common/configs/user/console/kubernetes/remove-splash.patch b/hosts/common/configs/user/console/kubernetes/remove-splash.patch new file mode 100644 index 0000000..7c082d0 --- /dev/null +++ b/hosts/common/configs/user/console/kubernetes/remove-splash.patch @@ -0,0 +1,123 @@ +diff --git a/internal/ui/splash.go b/internal/ui/splash.go +index bfe58e46..21683c53 100644 +--- a/internal/ui/splash.go ++++ b/internal/ui/splash.go +@@ -3,14 +3,6 @@ + + package ui + +-import ( +- "fmt" +- "strings" +- +- "github.com/derailed/k9s/internal/config" +- "github.com/derailed/tview" +-) +- + // LogoSmall K9s small log. + var LogoSmall = []string{ + ` ____ __.________ `, +@@ -30,42 +22,3 @@ var LogoBig = []string{ + `|____|__ \ /____//____ >\______ /_______ \___|`, + ` \/ \/ \/ \/ `, + } +- +-// Splash represents a splash screen. +-type Splash struct { +- *tview.Flex +-} +- +-// NewSplash instantiates a new splash screen with product and company info. +-func NewSplash(styles *config.Styles, version string) *Splash { +- s := Splash{Flex: tview.NewFlex()} +- s.SetBackgroundColor(styles.BgColor()) +- +- logo := tview.NewTextView() +- logo.SetDynamicColors(true) +- logo.SetTextAlign(tview.AlignCenter) +- s.layoutLogo(logo, styles) +- +- vers := tview.NewTextView() +- vers.SetDynamicColors(true) +- vers.SetTextAlign(tview.AlignCenter) +- s.layoutRev(vers, version, styles) +- +- s.SetDirection(tview.FlexRow) +- s.AddItem(logo, 10, 1, false) +- s.AddItem(vers, 1, 1, false) +- +- return &s +-} +- +-func (s *Splash) layoutLogo(t *tview.TextView, styles *config.Styles) { +- logo := strings.Join(LogoBig, fmt.Sprintf("\n[%s::b]", styles.Body().LogoColor)) +- fmt.Fprintf(t, "%s[%s::b]%s\n", +- strings.Repeat("\n", 2), +- styles.Body().LogoColor, +- logo) +-} +- +-func (s *Splash) layoutRev(t *tview.TextView, rev string, styles *config.Styles) { +- fmt.Fprintf(t, "[%s::b]Revision [red::b]%s", styles.Body().FgColor, rev) +-} +diff --git a/internal/ui/splash_test.go b/internal/ui/splash_test.go +deleted file mode 100644 +index 69b4b50d..00000000 +--- a/internal/ui/splash_test.go ++++ /dev/null +@@ -1,22 +0,0 @@ +-// SPDX-License-Identifier: Apache-2.0 +-// Copyright Authors of K9s +- +-package ui_test +- +-import ( +- "testing" +- +- "github.com/derailed/k9s/internal/config" +- "github.com/derailed/k9s/internal/ui" +- "github.com/stretchr/testify/assert" +-) +- +-func TestNewSplash(t *testing.T) { +- s := ui.NewSplash(config.NewStyles(), "bozo") +- +- x, y, w, h := s.GetRect() +- assert.Equal(t, 0, x) +- assert.Equal(t, 0, y) +- assert.Equal(t, 15, w) +- assert.Equal(t, 10, h) +-} +diff --git a/internal/view/app.go b/internal/view/app.go +index 4ac7e7c2..2b3a3fc5 100644 +--- a/internal/view/app.go ++++ b/internal/view/app.go +@@ -35,7 +35,6 @@ import ( + var ExitStatus = "" + + const ( +- splashDelay = 1 * time.Second + clusterRefresh = 15 * time.Second + clusterInfoWidth = 50 + clusterInfoPad = 15 +@@ -165,8 +164,7 @@ func (a *App) layout(ctx context.Context) { + } + main.AddItem(flash, 1, 1, false) + +- a.Main.AddPage("main", main, true, false) +- a.Main.AddPage("splash", ui.NewSplash(a.Styles, a.version), true, true) ++ a.Main.AddPage("main", main, true, true) + a.toggleHeader(!a.Config.K9s.IsHeadless(), !a.Config.K9s.IsLogoless()) + } + +@@ -520,10 +518,7 @@ func (a *App) Run() error { + a.Resume() + + go func() { +- <-time.After(splashDelay) + a.QueueUpdateDraw(func() { +- a.Main.SwitchToPage("main") +- // if command bar is already active, focus it + if a.CmdBuff().IsActive() { + a.SetFocus(a.Prompt()) + } diff --git a/hosts/common/configs/user/console/kubernetes/theme.yaml b/hosts/common/configs/user/console/kubernetes/theme.yaml new file mode 100644 index 0000000..21df85c --- /dev/null +++ b/hosts/common/configs/user/console/kubernetes/theme.yaml @@ -0,0 +1,117 @@ +k9s: + body: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + logoColor: "{{colors.primary.default.hex}}" + + prompt: + bgColor: "{{colors.surface_container.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + suggestColor: "{{colors.on_surface_variant.default.hex}}" + border: + default: "{{colors.primary.default.hex}}" + command: "{{colors.secondary.default.hex}}" + + info: + fgColor: "{{colors.primary.default.hex}}" + sectionColor: "{{colors.on_surface.default.hex}}" + + dialog: + fgColor: "{{colors.on_surface.default.hex}}" + bgColor: "{{colors.surface_container_high.default.hex}}" + buttonFgColor: "{{colors.on_secondary_container.default.hex}}" + buttonBgColor: "{{colors.secondary_container.default.hex}}" + buttonFocusFgColor: "{{colors.on_primary_container.default.hex}}" + buttonFocusBgColor: "{{colors.primary_container.default.hex}}" + fieldFgColor: "{{colors.on_surface.default.hex}}" + labelFgColor: "{{colors.on_surface.default.hex}}" + + frame: + border: + fgColor: "{{colors.outline.default.hex}}" + focusColor: "{{colors.primary.default.hex}}" + + menu: + fgColor: "{{colors.on_surface.default.hex}}" + numKeyColor: "{{colors.secondary.default.hex}}" + keyColor: "{{colors.tertiary.default.hex}}" + + crumbs: + bgColor: "{{colors.surface.default.hex}}" + activeColor: "{{colors.primary_container.default.hex}}" + fgColor: "{{colors.on_primary_container.default.hex}}" + + status: + newColor: "{{colors.on_surface.default.hex}}" + modifyColor: "{{colors.warning.default.hex}}" + addColor: "{{colors.primary.default.hex}}" + errorColor: "{{colors.error.default.hex}}" + pendingColor: "{{colors.secondary.default.hex}}" + highlightColor: "{{colors.primary.default.hex}}" + completedColor: "{{colors.surface_variant.default.hex}}" + killColor: "{{colors.error.default.hex}}" + + title: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + counterColor: "{{colors.primary.default.hex}}" + highlightColor: "{{colors.secondary.default.hex}}" + filterColor: "{{colors.tertiary.default.hex}}" + + help: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + keyColor: "{{colors.primary.default.hex}}" + numKeyColor: "{{colors.secondary.default.hex}}" + sectionColor: "{{colors.on_surface.default.hex}}" + + views: + charts: + bgColor: "{{colors.surface.default.hex}}" + chartBgColor: "{{colors.surface_container.default.hex}}" + defaultChartColors: + - c.primary + - c.secondary + dialBgColor: "{{colors.surface_container.default.hex}}" + defaultDialColors: + - c.primary + - c.secondary + resourceColors: + cpu: + - c.primary + - c.tertiary + mem: + - c.secondary + - c.error + + logs: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + indicator: + bgColor: "{{colors.surface_container.default.hex}}" + fgColor: "{{colors.on_surface_variant.default.hex}}" + toggleOffColor: "{{colors.outline.default.hex}}" + toggleOnColor: "{{colors.primary.default.hex}}" + + table: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + cursorBgColor: "{{colors.primary.default.hex}}" + cursorFgColor: "{{colors.on_primary.default.hex}}" + markColor: "{{colors.secondary.default.hex}}" + header: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.primary.default.hex}}" + sorterColor: "{{colors.secondary.default.hex}}" + + xray: + bgColor: "{{colors.surface.default.hex}}" + fgColor: "{{colors.on_surface.default.hex}}" + cursorColor: "{{colors.surface_variant.default.hex}}" + cursorTextColor: "{{colors.on_surface_variant.default.hex}}" + graphicColor: "{{colors.tertiary.default.hex}}" + + yaml: + colonColor: "{{colors.outline.default.hex}}" + keyColor: "{{colors.primary.default.hex}}" + valueColor: "{{colors.on_surface.default.hex}}"