=====================================================================

Excited to bring V5 to life. This includes some BREAKING CHANGES to
several aspects of ZSH-type scwrypts. Please refer to the readme
for upgrade details (specifically docs/upgrade/v4-to-v5.md)

--- New Features -------------------------

- ZSH testing library with basic mock capabilities

- new scwrypts environment file format includes metadata and more
  advanced features like optional parent env overrides, selection
  inheritence, and improved structurual flexibility

- speedup cache for non-CI runs of ZSH-type scwrypts

- ${scwryptsmodule} syntax now allows a consistent unique-naming
  scheme for functions in ZSH-type scwrypts while providing better
  insight into origin of API calls in other modules

- reusable, case-statement-driven argument parsers in ZSH-type scwrypts

--- Changes ------------------------------

- several utility function renames in ZSH-type scwrypts to improve
  consistency

- documentation comments included in ZSH libraries

- ZSH-type scwrypts now allow library modules to live alongside
  executables
  (zsh/lib still supported; autodetection determines default)

--- Bug Fixes ----------------------------

- hardened environment checking for REQUIRED_ENV variables; this removes
  the ability to overwrite variables in local function contexts
This commit is contained in:
2024-05-10 13:32:02 -06:00
committed by Wryn (yage) Wagner
parent 1b4060dd1c
commit 7f14edd039
271 changed files with 11459 additions and 10516 deletions

View File

@ -0,0 +1,47 @@
#####################################################################
command -v compdef >/dev/null 2>&1 || return 0
#####################################################################
for CLI in kubectl helm flux
do
eval "_${CLI[1]}() {
local SUBSESSION=0
local SUBSESSION_OFFSET=2
echo \${words[2]} | grep -q '^[0-9]\\+$' && SUBSESSION=\${words[2]} && SUBSESSION_OFFSET=3
local PASSTHROUGH_WORDS=($CLI)
[[ \$CURRENT -gt \${SUBSESSION_OFFSET} ]] && echo \${words[\${SUBSESSION_OFFSET}]} | grep -qv '^[0-9]\\+$' && {
local KUBECONTEXT=\$(k \$SUBSESSION meta get context)
local NAMESPACE=\$(k \$SUBSESSION meta get namespace)
[ \$KUBECONTEXT ] \
&& PASSTHROUGH_WORDS+=($([[ $CLI =~ ^helm$ ]] && echo '--kube-context' || echo '--context') \$KUBECONTEXT) \
;
[ \$NAMESPACE ] \
&& PASSTHROUGH_WORDS+=(--namespace \$NAMESPACE) \
;
}
local DELIMIT_COUNT=0
local WORD
for WORD in \${words[@]:1}
do
case \$WORD in
( [0-9]* ) continue ;;
( -- )
echo \$words | grep -q 'exec' && ((DELIMIT_COUNT+=1))
[[ \$DELIMIT_COUNT -eq 0 ]] && ((DELIMIT_COUNT+=1)) && continue
;;
esac
PASSTHROUGH_WORDS+=(\"\$WORD\")
done
echo \"\$words\" | grep -q '\\s\\+$' && PASSTHROUGH_WORDS+=(' ')
words=\"\${PASSTHROUGH_WORDS[@]}\"
_$CLI
}
"
compdef _${CLI[1]} ${CLI[1]}
done

View File

@ -0,0 +1,198 @@
[[ $SCWRYPTS_KUBECTL_DRIVER_READY -eq 1 ]] && return 0
unalias k h f >/dev/null 2>&1
k() { _SCWRYPTS_KUBECTL_DRIVER kubectl $@; }
h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; }
f() { _SCWRYPTS_KUBECTL_DRIVER flux $@; }
_SCWRYPTS_KUBECTL_DRIVER() {
[ ! $SCWRYPTS_ENV ] && {
echo.error "must set SCWRYPTS_ENV in order to use '$(echo $CLI | head -c1)'"
return 1
}
which kube.redis >/dev/null 2>&1 \
|| eval "$(scwrypts -n --name meta/get-static-redis-definition --type zsh --group kube)"
local CLI="$1"; shift 1
local SCWRYPTS_GROUP CUSTOM_COMMANDS=(meta)
for SCWRYPTS_GROUP in ${SCWRYPTS_GROUPS[@]}
do
CUSTOM_COMMANDS+=($(eval echo '$SCWRYPTS_KUBECTL_CUSTOM_COMMANDS__'$SCWRYPTS_GROUP))
done
##########################################
local USAGE="
usage: - [...args...] [...options...] -- [...$CLI options...]
args: -
options: -
--subsession [0-9] use indicated subsession (use for script clarity instead of positional arg)
-h, --help display this help dialogue
-v, --verbose output debugging information
description: -
"
local USAGE__usage=$(echo $CLI | head -c1)
local USAGE__args="$(
{
echo "$(utils.colors.print green '[0-9]')^if the first argument is a number 0-9, uses or creates a subsession (default 0)"
echo " ^ "
for C in ${CUSTOM_COMMANDS[@]}
do
echo "$(utils.colors.print green ${C})^$(SCWRYPTS_KUBECTL_CUSTOM_COMMAND_DESCRIPTION__$C 2>/dev/null)"
done
} | column -ts '^'
)"
local USAGE__options="
-n, --namespace set the namespace
-k, --context set the context
"
local USAGE__description="
Provides 'k' (kubectl), 'h' (helm), and 'f' (flux) shorthands to the respective
utility. These functions leverage redis and scwrypts environments to
allow quick selection of contexts and namespaces usable across all
active shell instances.
The scwrypts group 'kubectl' has simple selection executables for
kubecontext and namespace, but also provides the library to enable
enriched, use-case-sensitive setup of kubernetes context.
All actions are scoped to the current SCWRYPTS_ENV
currently : $(utils.colors.print yellow ${SCWRYPTS_ENV})
"
##########################################
local USER_ARGS=()
local CUSTOM_COMMAND=0
local VERBOSE=0
local HELP=0
local ERRORS=0
local COMMAND_SWITCH_CASE="@($(echo $CUSTOM_COMMANDS | sed 's/ /|/g'))"
[ ! $SUBSESSION ] && local SUBSESSION=0
[[ $1 =~ ^[0-9]$ ]] && SUBSESSION=$1 && shift 1
while [[ $# -gt 0 ]]
do
case $1 in
meta )
CUSTOM_COMMAND=$1
SCWRYPTS_KUBECTL_CUSTOM_COMMAND_PARSE__$1 ${@:2}
break
;;
-v | --verbose ) VERBOSE=1 ;;
-h | --help ) HELP=1 ;;
--subsession ) SUBSESSION=$2; shift 1 ;;
-n | --namespace )
_SCWRYPTS_KUBECTL_DRIVER kubectl meta set namespace $2
shift 1
;;
-k | --context | --kube-context )
_SCWRYPTS_KUBECTL_DRIVER kubectl meta set context $2
shift 1
;;
-- )
echo $USER_ARGS | grep -q 'exec' && USER_ARGS+=(--)
shift 1
break
;;
* )
[ ! $CUSTOM_COMMAND ] && {
for C in ${CUSTOM_COMMANDS[@]}
do
[[ $1 =~ ^$C$ ]] && {
SCWRYPTS_KUBECTL_CUSTOM_COMMAND_PARSE__$1 ${@:2}
break
}
done
}
USER_ARGS+=($1)
;;
esac
shift 1
done
while [[ $# -gt 0 ]]; do USER_ARGS+=($1); shift 1; done
utils.check-errors || return 1
[[ $HELP -eq 1 ]] && { utils.io.usage; return 0; }
#####################################################################
local STRICT=$(_SCWRYPTS_KUBECTL_SETTINGS get strict || echo 1)
case $CUSTOM_COMMAND in
0 )
local CLI_ARGS=()
local CONTEXT=$(k meta get context)
local NAMESPACE=$(k meta get namespace)
[ $CONTEXT ] && [[ $CLI =~ ^helm$ ]] && CLI_ARGS+=(--kube-context $CONTEXT)
[ $CONTEXT ] && [[ $CLI =~ ^kubectl$ ]] && CLI_ARGS+=(--context $CONTEXT)
[ $CONTEXT ] && [[ $CLI =~ ^flux$ ]] && CLI_ARGS+=(--context $CONTEXT)
[[ $STRICT -eq 1 ]] && {
[ $CONTEXT ] || echo.error "missing kubectl 'context'"
[ $NAMESPACE ] || echo.error "missing kubectl 'namespace'"
utils.check-errors --no-fail --no-usage || {
echo.error "with 'strict' settings enabled, context and namespace must be set!"
echo.reminder "
these values can be set directly with
$(echo $CLI | head -c1) meta set (namespace|context)
"
return 2
}
}
[ $NAMESPACE ] && CLI_ARGS+=(--namespace $NAMESPACE)
[[ $VERBOSE -eq 1 ]] && {
echo.reminder "
context '$CONTEXT'
namespace '$NAMESPACE'
environment '$SCWRYPTS_ENV'
subsession '$SUBSESSION'
"
echo.status "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}"
} || {
[[ $(_SCWRYPTS_KUBECTL_SETTINGS get context) =~ ^show$ ]] && {
echo.reminder "$SCWRYPTS_ENV.$SUBSESSION : $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}"
}
}
$CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}
;;
* ) SCWRYPTS_KUBECTL_CUSTOM_COMMAND__$CUSTOM_COMMAND ${USER_ARGS[@]} ;;
esac
}
_SCWRYPTS_KUBECTL_SETTINGS() {
# (get setting-name) or (set setting-name setting-value)
kube.redis h$1 ${SCWRYPTS_ENV}:kubectl:settings ${@:2} | grep .
}
#####################################################################
source ${0:a:h}/kubectl.completion.zsh
source ${0:a:h}/meta.zsh

View File

@ -0,0 +1,149 @@
SCWRYPTS_KUBECTL_CUSTOM_COMMAND_PARSE__meta() {
USAGE__usage+=" meta"
USAGE__args="
- get output value of meta variable
- set interactively configure value of meta variable
- clear clear current subsession variables
(settings args)
- show output context for every command
- hide (default) hide output context for every command
- strict (default) require context *and* namespace to be set
- loose do not require context and namespace to be set
"
USAGE__options=''
USAGE__description=$(SCWRYPTS_KUBECTL_CUSTOM_COMMAND_DESCRIPTION__meta)
META_SUBARGS="
- namespace
- context
"
while [[ $# -gt 0 ]]
do
case $1 in
( -h | --help ) HELP=1 ;;
( set )
USAGE__usage+=" set"
USAGE__args="set (namespace|context)"
USAGE__description="interactively set a namespace or context for '$SCWRYPTS_ENV'"
case $2 in
( namespace | context ) USER_ARGS+=($1 $2 $3); [ $3 ] && shift 1 ;;
( -h | --help ) HELP=1 ;;
( '' )
: \
&& SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta set context \
&& SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta set namespace \
;
return $?
;;
( * ) echo.error "cannot set '$2'" ;;
esac
shift 1
;;
( get )
USAGE__usage+=" get"
USAGE__args="get (namespace|context|all)"
USAGE__description="output the current namespace or context for '$SCWRYPTS_ENV'"
case $2 in
( namespace | context | all ) USER_ARGS+=($1 $2) ;;
( -h | --help ) HELP=1 ;;
( * ) echo.error "cannot get '$2'" ;;
esac
shift 1
;;
( copy )
USAGE__usage+=" copy"
USAGE__args+="copy [0-9]"
USAGE__description="copy current subsession ($SUBSESSION) to target subsession id"
case $2 in
( [0-9] ) USER_ARGS+=($1 $2) ;;
( -h | --help ) HELP=1 ;;
( * ) echo.error "target session must be a number [0-9]" ;;
esac
shift 1
;;
( clear | show | hide | strict | loose ) USER_ARGS+=($1) ;;
( * ) echo.error "no meta command '$1'"
esac
shift 1
done
}
SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta() {
case $1 in
( get )
[[ $2 =~ ^all$ ]] && {
local CONTEXT=$(kube.redis get --prefix current:context | grep . || utils.colors.print bright-red "none set")
local NAMESPACE=$(kube.redis get --prefix current:namespace | grep . || utils.colors.print bright-red "none set")
echo "
environment : $SCWRYPTS_ENV
context : $CONTEXT
namespace : $NAMESPACE
CLI settings
command context : $(_SCWRYPTS_KUBECTL_SETTINGS get context)
strict mode : $([[ $STRICT -eq 1 ]] && utils.colors.print green on || utils.colors.print bright-red off)
" | sed 's/^ \+//' >&2
return 0
}
kube.redis get --prefix current:$2
;;
( set )
: \
&& scwrypts -n --name set-$2 --type zsh --group kube -- $3 --subsession $SUBSESSION >/dev/null \
&& k $SUBSESSION meta get $2 \
;
;;
( copy )
: \
&& echo.status "copying $1 to $2" \
&& scwrypts -n --name set-context --type zsh --group kube -- --subsession $2 $(k $1 meta get context | grep . || echo 'reset') \
&& scwrypts -n --name set-namespace --type zsh --group kube -- --subsession $2 $(k $1 meta get namespace | grep . || echo 'reset') \
&& echo.success "subsession $1 copied to $2" \
;
;;
( clear )
scwrypts -n --name set-context --type zsh --group kube -- --subsession $SUBSESSION reset >/dev/null \
&& echo.success "subsession $SUBSESSION reset to default"
;;
( show )
_SCWRYPTS_KUBECTL_SETTINGS set context show >/dev/null \
&& echo.success "now showing full command context"
;;
( hide )
_SCWRYPTS_KUBECTL_SETTINGS set context hide >/dev/null \
&& echo.success "now hiding command context"
;;
( loose )
_SCWRYPTS_KUBECTL_SETTINGS set strict 0 >/dev/null \
&& echo.warning "now running in 'loose' mode"
;;
( strict )
_SCWRYPTS_KUBECTL_SETTINGS set strict 1 >/dev/null \
&& echo.success "now running in 'strict' mode"
;;
esac
}
SCWRYPTS_KUBECTL_CUSTOM_COMMAND_DESCRIPTION__meta() {
[ $CLI ] || CLI='kubectl'
echo "operations for $CLI session variables and other CLI settings"
}