pkgs(kubenix): overhaul and drop support for the helm CLI (#24)

This is a relatively large re-design which

 - removes usage of the Helm CLI
 - expects users to override the default package
 - performs an interactive diff, confirm, apply by default
 - prunes removed resources
This commit is contained in:
Bryton Hall 2023-07-07 00:33:25 -04:00 committed by GitHub
parent ccfd0d16c1
commit 07ba711056
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 114 deletions

View file

@ -1,113 +1,99 @@
{
jq,
kubectl,
kubernetes-helm,
nix,
vals,
writeShellScriptBin,
}:
writeShellScriptBin "kubenix" ''
set -Eeuo pipefail
colordiff,
evalModules,
runCommand,
writeShellScript,
module ? {},
specialArgs ? {},
}: let
kubernetes =
(evalModules {
inherit module specialArgs;
})
.config
.kubernetes
or {};
in
runCommand "kubenix"
{
kubeconfig = kubernetes.kubeconfig or "";
result = kubernetes.result or "";
function _help() {
echo "
kubenix - Kubernetes management with Nix
# kubectl does some parsing which removes the -I flag so
# as workaround, we write to a script and call that
# https://github.com/kubernetes/kubernetes/pull/108199#issuecomment-1058405404
diff = writeShellScript "kubenix-diff" ''
${colordiff}/bin/colordiff --nobanner -N -u -I ' kubenix/hash: ' -I ' generation: ' $@
'';
} ''
set -euo pipefail
mkdir -p $out/bin
commands:
apply - create resources in target cluster
diff - show a diff between configured and live resources
render - print resource manifests to stdout
# write the manifests for use with `nix build`
ln -s $result $out/manifest.json
options:
-h --help - show this menu
-v --verbose - increase output details
"
}
# create a script for `nix run`
cat <<EOF> $out/bin/kubenix
set -uo pipefail
# path to nix binary (useful to inject flags, e.g.)
_nix="${nix}/bin/nix"
export KUBECONFIG=$kubeconfig
export KUBECTL_EXTERNAL_DIFF=$diff
SYSTEM=$($_nix show-config --json | jq -r '.system.value')
function _help() {
echo "
kubenix - Kubernetes management with Nix
function _helm() {
$_nix eval ".#kubenix.$SYSTEM.config.kubernetes.helm" --json | jq -c '.releases[] | del(.objects)' | while read -r release; do
values=$(mktemp)
echo "$release" | jq -r '.values' | ${vals}/bin/vals eval > $values
commands:
"" - run diff, prompt for confirmation, then apply
apply - create resources in target cluster
diff - show a diff between configured and live resources
render - print resource manifests to stdout
name=$(echo "$release" | jq -r '.name')
chart=$(echo "$release" | jq -r '.chart')
namespace=$(echo "$release" | jq -r '.namespace // "default"')
options:
-h --help - show this menu
"
}
args="-n $namespace $name $chart -f $values"
function _kubectl() {
${vals}/bin/vals eval -fail-on-missing-key-in-map < $result | ${kubectl}/bin/kubectl \$@
}
# only apply when there are changes
if [[ "$1" == "upgrade" ]]; then
if ${kubernetes-helm}/bin/helm diff upgrade $args --allow-unreleased --detailed-exitcode 2> /dev/null; then
continue
fi
fi
# if no args given, add empty string
[ \$# -eq 0 ] && set -- ""
${kubernetes-helm}/bin/helm $@ $args
done
}
# parse arguments
while test \$# -gt 0; do
case "\$1" in
function _kubectl() {
MANIFESTS=$(mktemp)
# TODO: find a better filter, not just not-helm, not-crd
resources=$($_nix build ".#kubenix.$SYSTEM.config.kubernetes.result" --json | jq -r '.[0].outputs.out')
cat $resources | jq '.items[]
| select(.metadata.labels."app.kubernetes.io/managed-by" != "Helm")
| select(.kind != "CustomResourceDefinition")' > $MANIFESTS
-h|--help)
_help
exit 0;;
[ -s "$MANIFESTS" ] || return 0
"")
_kubectl diff -f - --prune
if [[ "\$?" -eq 1 ]]; then
read -p 'apply? [y/N]: ' response
[[ \$response == "y" ]] && _kubectl apply -f - --prune --all
fi
shift;;
case $1 in
render)
cat $MANIFESTS;;
*)
cat $MANIFESTS | ${vals}/bin/vals eval | ${kubectl}/bin/kubectl $@ -f - || true;;
esac
}
render)
${vals}/bin/vals eval < $result
shift;;
# if no args given, add empty string
[ $# -eq 0 ] && set -- ""
apply|diff)
_kubectl \$@ -f - --prune
shift;;
# use kubeconfig, if given
kubeconfig=$($_nix eval ".#kubenix.$SYSTEM.config.kubernetes.kubeconfig" --raw)
[ -n "$kubeconfig" ] && export KUBECONFIG=$kubeconfig
*)
_kubectl \$@
shift;;
# parse arguments
while test $# -gt 0; do
case "$1" in
esac
done
apply)
_kubectl apply
_helm upgrade --atomic --install --create-namespace
shift;;
diff)
_kubectl diff
_helm diff upgrade --allow-unreleased
shift;;
render)
_kubectl render
_helm template
shift;;
-h|--help|"")
_help
exit 0;;
-v|--verbose)
_nix="$_nix --show-trace"
set -x
shift;;
*)
_help
exit 1;;
esac
done
''
EOF
chmod +x $out/bin/kubenix
''