From af8a884164bb50ad34c09719bdbdb2a1b01b917c Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Sat, 5 Jul 2025 22:54:55 +0200 Subject: [PATCH] kubeswitch: add module Signed-off-by: Ludovic Ortega Co-authored-by: Austin Horstman --- .github/labeler.yml | 1 + .../misc/news/2025/06/2025-06-13_18-14-02.nix | 10 ++ modules/programs/kubeswitch.nix | 115 ++++++++++++++++++ tests/darwinScrublist.nix | 1 + tests/modules/programs/kubeswitch/bash.nix | 14 +++ tests/modules/programs/kubeswitch/default.nix | 7 ++ .../programs/kubeswitch/empty-settings.nix | 7 ++ .../programs/kubeswitch/example-settings.nix | 35 ++++++ tests/modules/programs/kubeswitch/fish.nix | 16 +++ tests/modules/programs/kubeswitch/zsh.nix | 14 +++ 10 files changed, 220 insertions(+) create mode 100644 modules/misc/news/2025/06/2025-06-13_18-14-02.nix create mode 100644 modules/programs/kubeswitch.nix create mode 100644 tests/modules/programs/kubeswitch/bash.nix create mode 100644 tests/modules/programs/kubeswitch/default.nix create mode 100644 tests/modules/programs/kubeswitch/empty-settings.nix create mode 100644 tests/modules/programs/kubeswitch/example-settings.nix create mode 100644 tests/modules/programs/kubeswitch/fish.nix create mode 100644 tests/modules/programs/kubeswitch/zsh.nix diff --git a/.github/labeler.yml b/.github/labeler.yml index f25a8c52d..2ee28e2ae 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -207,6 +207,7 @@ - modules/programs/java.nix - modules/programs/jetbrains-remote.nix - modules/programs/kubecolor.nix + - modules/programs/kubeswitch.nix - modules/programs/lazydocker.nix - modules/programs/matplotlib.nix - modules/programs/mercurial.nix diff --git a/modules/misc/news/2025/06/2025-06-13_18-14-02.nix b/modules/misc/news/2025/06/2025-06-13_18-14-02.nix new file mode 100644 index 000000000..683f9668c --- /dev/null +++ b/modules/misc/news/2025/06/2025-06-13_18-14-02.nix @@ -0,0 +1,10 @@ +{ + time = "2025-06-13T16:14:02+00:00"; + condition = true; + message = '' + A new module is available: 'programs.kubeswitch'. + + The kubectx for operators. + kubeswitch (lazy: switch) is the single pane of glass for all of your kubeconfig files. + ''; +} diff --git a/modules/programs/kubeswitch.nix b/modules/programs/kubeswitch.nix new file mode 100644 index 000000000..3d3085bfa --- /dev/null +++ b/modules/programs/kubeswitch.nix @@ -0,0 +1,115 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.programs.kubeswitch; + + yamlFormat = pkgs.formats.yaml { }; +in +{ + meta.maintainers = [ lib.hm.maintainers.m0nsterrr ]; + + options.programs.kubeswitch = { + enable = lib.mkEnableOption "the kubectx for operators"; + + commandName = lib.mkOption { + type = lib.types.str; + default = "kswitch"; + description = "The name of the command to use"; + }; + + package = lib.mkPackageOption pkgs "kubeswitch" { }; + + enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; }; + + enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; }; + + enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; }; + + settings = lib.mkOption { + type = yamlFormat.type; + default = { }; + example = { + kind = "SwitchConfig"; + kubeconfigName = "*.myconfig"; + kubeconfigStores = [ + { + kind = "filesystem"; + kubeconfigName = "*.myconfig"; + paths = [ + "~/.kube/my-other-kubeconfigs/" + ]; + } + ]; + version = "v1alpha1"; + }; + description = '' + Configuration written to + {file}`~/.kube/switch-config.yaml`. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + home = { + packages = [ cfg.package ]; + + file.".kube/switch-config.yaml" = lib.mkIf (cfg.settings != { }) { + source = yamlFormat.generate "kubeswitch-settings" cfg.settings; + }; + }; + + programs = + let + generateKubeswitchShellFiles = + shell: + pkgs.runCommand "kubeswitch-${cfg.commandName}-shell-files-for-${shell}" + { + nativeBuildInputs = [ cfg.package ]; + } + '' + mkdir -p $out/share + switcher init "${shell}" | sed "s/switch(/${cfg.commandName}(/" > "$out/share/${cfg.commandName}_init.${shell}" + switcher --cmd "${cfg.commandName}" completion "${shell}" > "$out/share/${cfg.commandName}_completion.${shell}" + ''; + in + { + bash.initExtra = + let + kubeswitchBashFiles = generateKubeswitchShellFiles "bash"; + in + lib.mkIf cfg.enableBashIntegration '' + source ${kubeswitchBashFiles}/share/${cfg.commandName}_init.bash + source ${kubeswitchBashFiles}/share/${cfg.commandName}_completion.bash + ''; + + fish.interactiveShellInit = + let + shell_files = + pkgs.runCommand "kubeswitch-${cfg.commandName}-shell-files-for-fish" + { buildInputs = [ cfg.package ]; } + '' + mkdir -p $out/share + switcher init fish | sed "s/kubeswitch/${cfg.commandName}/" > $out/share/${cfg.commandName}_init.fish + switcher --cmd ${cfg.commandName} completion fish > $out/share/${cfg.commandName}_completion.fish + ''; + in + lib.mkIf cfg.enableFishIntegration '' + source ${shell_files}/share/${cfg.commandName}_init.fish + source ${shell_files}/share/${cfg.commandName}_completion.fish + ''; + + zsh.initContent = + let + kubeswitchZshFiles = generateKubeswitchShellFiles "zsh"; + in + lib.mkIf cfg.enableZshIntegration '' + source ${kubeswitchZshFiles}/share/${cfg.commandName}_init.zsh + source ${kubeswitchZshFiles}/share/${cfg.commandName}_completion.zsh + ''; + }; + }; +} diff --git a/tests/darwinScrublist.nix b/tests/darwinScrublist.nix index e80fceb22..f62c5061f 100644 --- a/tests/darwinScrublist.nix +++ b/tests/darwinScrublist.nix @@ -77,6 +77,7 @@ let "khard" "kitty" "kubecolor" + "kubeswitch" "lapce" "lazydocker" "lazygit" diff --git a/tests/modules/programs/kubeswitch/bash.nix b/tests/modules/programs/kubeswitch/bash.nix new file mode 100644 index 000000000..d5c1f20ec --- /dev/null +++ b/tests/modules/programs/kubeswitch/bash.nix @@ -0,0 +1,14 @@ +{ + programs = { + kubeswitch.enable = true; + bash.enable = true; + }; + + nmt.script = '' + assertFileExists home-files/.bashrc + assertFileRegex home-files/.bashrc \ + '^source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-bash/share/kswitch_init.bash$' + assertFileRegex home-files/.bashrc \ + '^source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-bash/share/kswitch_completion.bash$' + ''; +} diff --git a/tests/modules/programs/kubeswitch/default.nix b/tests/modules/programs/kubeswitch/default.nix new file mode 100644 index 000000000..da244d84e --- /dev/null +++ b/tests/modules/programs/kubeswitch/default.nix @@ -0,0 +1,7 @@ +{ + kubeswitch-bash = ./bash.nix; + kubeswitch-empty-settings = ./empty-settings.nix; + kubeswitch-example-settings = ./example-settings.nix; + kubeswitch-fish = ./fish.nix; + kubeswitch-zsh = ./zsh.nix; +} diff --git a/tests/modules/programs/kubeswitch/empty-settings.nix b/tests/modules/programs/kubeswitch/empty-settings.nix new file mode 100644 index 000000000..daf2fa524 --- /dev/null +++ b/tests/modules/programs/kubeswitch/empty-settings.nix @@ -0,0 +1,7 @@ +{ + programs.kubeswitch.enable = true; + + nmt.script = '' + assertPathNotExists home-files/.kube/switch-config.yaml + ''; +} diff --git a/tests/modules/programs/kubeswitch/example-settings.nix b/tests/modules/programs/kubeswitch/example-settings.nix new file mode 100644 index 000000000..20ace2eac --- /dev/null +++ b/tests/modules/programs/kubeswitch/example-settings.nix @@ -0,0 +1,35 @@ +{ + programs.kubeswitch = { + enable = true; + + settings = { + kind = "SwitchConfig"; + version = "v1alpha1"; + kubeconfigName = "*.myconfig"; + kubeconfigStores = [ + { + kind = "filesystem"; + kubeconfigName = "*.myconfig"; + paths = [ + "~/.kube/my-other-kubeconfigs/" + ]; + } + ]; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.kube/switch-config.yaml \ + ${builtins.toFile "example-settings-expected.yaml" '' + kind: SwitchConfig + kubeconfigName: '*.myconfig' + kubeconfigStores: + - kind: filesystem + kubeconfigName: '*.myconfig' + paths: + - ~/.kube/my-other-kubeconfigs/ + version: v1alpha1 + ''} + ''; +} diff --git a/tests/modules/programs/kubeswitch/fish.nix b/tests/modules/programs/kubeswitch/fish.nix new file mode 100644 index 000000000..0fa837472 --- /dev/null +++ b/tests/modules/programs/kubeswitch/fish.nix @@ -0,0 +1,16 @@ +{ ... }: + +{ + programs = { + kubeswitch.enable = true; + fish.enable = true; + }; + + nmt.script = '' + assertFileExists home-files/.config/fish/config.fish + assertFileRegex home-files/.config/fish/config.fish \ + '^\s*source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-fish/share/kswitch_init.fish$' + assertFileRegex home-files/.config/fish/config.fish \ + '^\s*source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-fish/share/kswitch_completion.fish$' + ''; +} diff --git a/tests/modules/programs/kubeswitch/zsh.nix b/tests/modules/programs/kubeswitch/zsh.nix new file mode 100644 index 000000000..f16efe662 --- /dev/null +++ b/tests/modules/programs/kubeswitch/zsh.nix @@ -0,0 +1,14 @@ +{ + programs = { + kubeswitch.enable = true; + zsh.enable = true; + }; + + nmt.script = '' + assertFileExists home-files/.zshrc + assertFileRegex home-files/.zshrc \ + '^source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-zsh/share/kswitch_init.zsh$' + assertFileRegex home-files/.zshrc \ + '^source /nix/store/[0-9a-z]*-kubeswitch-kswitch-shell-files-for-zsh/share/kswitch_completion.zsh$' + ''; +}