Compare commits

..

7 Commits

Author SHA1 Message Date
f3e70c61cb v3.9.0
=====================================================================

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

- scwrypts runner has new arguments
  -q/--quiet   allows quiet-mode operation while still logging to logfiles
  -v/--verbose forces verbose mode
    --version  longform required (-v is now for "verbose" mode)

- scwrypts runner now auto-detects certain CLI usage, running in quiet,
  logged mode if pattern match successfully identifies a single scwrypt
  (or when using --name); use --verbose to override this behavior

- 'k exec' no longer requires double '--' if a '--' comes after
  - old : k exec -it my-pod-0 -- -- /bin/sh
  + new : k exec -it my-pod-0 -- /bin/sh
  + still works : k -- exec -it my-pod-0 -- /bin/sh

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

- fixed various plugins/kubectl auto-completion settings; arguments
  after '--' or profile number (e.g. 'k 1 get deployments') will now
  appropriately autocomplete in the indicated profile

- helm template functions now work on related .tpl files as well
  (renders from chart root)

- fixed some goofy UTF-8 icons in zsh/lib/utils/io

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

- (experimental) scwrypts zsh plugin for interactive command selection
  (like CTRL+SPACE), but allows you to build command arguments,
  providing help dialogue for the selected command

--- New Scripts --------------------------

- zsh/misc/tally ) helps keep tally-counts of things; helpful when
                   running long scripts "what iteration am I on"
2023-12-11 18:19:37 -07:00
72e831da33 v3.8.0
=====================================================================

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

- kubectl driver updates; getting better, but still need to fix
  autocomplete in certain circumstances

- added -y|--yes flags to scwrypts to auto-accept user-prompts (use with
  caution)

- figured out the whole mikefarah/yq vs kislyuk/yq thing; use YQ for
  compatiblity

--- Bug fixes ----------------------------

- helm template generation now loads values in a more appropriate order
  which prevents overwrite by the wrong values file
2023-11-22 15:54:16 -07:00
a03885e8db v3.7.8
=====================================================================

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

- --list-envs now shows all available environments
2023-11-13 16:19:05 -07:00
6cc10e3f4f v3.7.7
=====================================================================

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

- GitHub Actions now autodetects groups within the "$GITHUB_WORKSPACE"
2023-11-13 13:16:04 -07:00
4a1208942d v3.7.6
=====================================================================

Documentation update
2023-11-13 12:30:49 -07:00
91780024f0 v3.7.5
=====================================================================

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

- adding variables of the format `^SCWRYPTS_GROUP_LOADERS__[a-z_]\+=`
  will let those files be explicitly sourced during run (this should
  allow custom group usage in CI)
2023-11-13 12:27:15 -07:00
3ca4fe0c65 v3.7.4
=====================================================================

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

- fixed typo in Vundle.vim clone
2023-11-11 15:27:34 -07:00
23 changed files with 666 additions and 141 deletions

View File

@ -48,6 +48,8 @@ There are a few notable changes to this runtime:
- User yes/no prompts will **always be YES**
- Other user input will default to an empty string
- Logs will not be captured
- Setting the environment variable `SCWRYPTS_GROUP_LOADER__[a-z_]\+` will source the file indicated in the variable (this allows custom groups without needing to modify the `config.zsh` directly)
- In GitHub actions, `*.scwrypts.zsh` groups are detected automatically from the `$GITHUB_WORKSPACE`; set `SCWRYPTS_GITHUB_NO_AUTOLOAD=true` to disable
## Contributing

View File

@ -55,8 +55,7 @@ runs:
--name scwrypts/virtualenv/update-all \
--group scwrypts \
--type zsh \
;
#> $HOME/.scwrypts.virtualenv.log 2>&1
> $HOME/.scwrypts.virtualenv.log 2>&1
echo "CI_SCWRYPTS_READY=1" >> $GITHUB_ENV
exit 0

View File

@ -2,30 +2,45 @@
command -v compdef >/dev/null 2>&1 || return 0
#####################################################################
_k() {
local C=$(k meta get context)
local NS=$(k meta get namespace)
for CLI in kubectl helm flux
do
eval "_${CLI[1]}() {
local SUBSESSION=0
echo \${words[2]} | grep -q '^[0-9]\\+$' && SUBSESSION=\${words[2]}
local KUBEWORDS=(kubectl)
[ $C ] && KUBEWORDS+=(--context $C)
[ $NS ] && KUBEWORDS+=(--namespace $NS)
local PASSTHROUGH_WORDS=($CLI)
[[ \$CURRENT -gt 2 ]] && echo \${words[2]} | grep -qv '^[0-9]\\+$' && {
local KUBECONTEXT=\$(k \$SUBSESSION meta get context)
local NAMESPACE=\$(k \$SUBSESSION meta get namespace)
words="$KUBEWORDS ${words[@]:1}"
_kubectl
}
[ \$KUBECONTEXT ] \
&& PASSTHROUGH_WORDS+=($([[ $CLI =~ ^helm$ ]] && echo '--kube-context' || echo '--context') \$KUBECONTEXT) \
;
[ \$NAMESPACE ] \
&& PASSTHROUGH_WORDS+=(--namespace \$NAMESPACE) \
;
}
compdef _k k
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
#####################################################################
_h() {
local C=$(k meta get context)
local NS=$(k meta get namespace)
echo \"\$words\" | grep -q '\\s\\+$' && PASSTHROUGH_WORDS+=(' ')
local KUBEWORDS=(kubectl)
[ $C ] && KUBEWORDS+=(--context $C)
[ $NS ] && KUBEWORDS+=(--namespace $NS)
words=\"\$PASSTHROUGH_WORDS\"
_$CLI
}
"
words="$KUBEWORDS ${words[@]:1}"
_helm
}
compdef _h h
compdef _${CLI[1]} ${CLI[1]}
done

View File

@ -3,6 +3,7 @@
unalias k h >/dev/null 2>&1
k() { _SCWRYPTS_KUBECTL_DRIVER kubectl $@; }
h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; }
f() { _SCWRYPTS_KUBECTL_DRIVER flux $@; }
_SCWRYPTS_KUBECTL_DRIVER() {
@ -57,7 +58,7 @@ _SCWRYPTS_KUBECTL_DRIVER() {
"
local USAGE__description="
Provides 'k' (kubectl) and 'h' (helm) shorthands to the respective
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.
@ -100,18 +101,20 @@ _SCWRYPTS_KUBECTL_DRIVER() {
--subsession ) SUBSESSION=$2; shift 1 ;;
-n | --namespace )
echo "TODO: set namespace ('$2')" >&2
USER_ARGS+=(--namespace $2); shift 1
;;
-k | --context | --kube-context )
echo "TODO: set context ('$2')" >&2
[[ $CLI =~ ^helm$ ]] && USER_ARGS+=(--kube-context $2)
[[ $CLI =~ ^kubectl$ ]] && USER_ARGS+=(--context $2)
_SCWRYPTS_KUBECTL_DRIVER kubectl meta set namespace $2
shift 1
;;
-- ) shift 1; break ;;
-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 ] && {
@ -149,6 +152,7 @@ _SCWRYPTS_KUBECTL_DRIVER() {
[ $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 ] || ERROR "missing kubectl 'context'"

View File

@ -30,8 +30,15 @@ SCWRYPTS_KUBECTL_CUSTOM_COMMAND_PARSE__meta() {
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) ;;
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 $?
;;
* ) ERROR "cannot set '$2'" ;;
esac
@ -94,7 +101,7 @@ SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta() {
;;
set )
scwrypts -n --name set-$2 --type zsh --group kubectl -- --subsession $SUBSESSION >/dev/null \
scwrypts -n --name set-$2 --type zsh --group kubectl -- $3 --subsession $SUBSESSION >/dev/null \
&& SUCCESS "$2 set"
;;

View File

@ -21,7 +21,6 @@ KUBECTL() {
kubectl ${KUBECTL_ARGS[@]} $@
}
#####################################################################
KUBECTL__GET_CONTEXT() { REDIS get --prefix "current:context"; }
@ -87,3 +86,73 @@ KUBECTL__LIST_NAMESPACES() {
echo default
KUBECTL get namespaces -o name | sed 's/^namespace\///' | sort
}
#####################################################################
KUBECTL__SERVE() {
[ $CONTEXT ] || local CONTEXT=$(KUBECTL__GET_CONTEXT)
[ $CONTEXT ] || ERROR 'must configure a context in which to serve'
[ $NAMESPACE ] || local NAMESPACE=$(KUBECTL__GET_NAMESPACE)
[ $NAMESPACE ] || ERROR 'must configure a namespace in which to serve'
CHECK_ERRORS --no-fail --no-usage || return 1
[ $SERVICE ] && SERVICE=$(KUBECTL__LIST_SERVICES | jq -c "select (.service == \"$SERVICE\")" || echo $SERVICE)
[ $SERVICE ] || local SERVICE=$(KUBECTL__SELECT_SERVICE)
[ $SERVICE ] || ERROR 'must provide or select a service'
KUBECTL__LIST_SERVICES | grep -q "^$SERVICE$"\
|| ERROR "no service '$SERVICE' in '$CONFIG/$NAMESPACE'"
CHECK_ERRORS --no-fail --no-usage || return 1
##########################################
SERVICE_PASSWORD="$(KUBECTL__GET_SERVICE_PASSWORD)"
KUBECTL__SERVICE_PARSE
INFO "attempting to serve ${NAMESPACE}/${SERVICE_NAME}:${SERVICE_PORT}"
[ $SERVICE_PASSWORD ] && INFO "password : $SERVICE_PASSWORD"
KUBECTL port-forward service/$SERVICE_NAME $SERVICE_PORT
}
KUBECTL__SELECT_SERVICE() {
[ $NAMESPACE ] || local NAMESPACE=$(KUBECTL__GET_NAMESPACE)
[ $NAMESPACE ] || return 1
local SERVICES=$(KUBECTL__LIST_SERVICES)
local SELECTED=$({
echo "namespace service port"
echo $SERVICES \
| jq -r '.service + " " + .port' \
| sed "s/^/$NAMESPACE /" \
;
} \
| column -t \
| FZF 'select a service' --header-lines=1 \
| awk '{print $2;}' \
)
echo $SERVICES | jq -c "select (.service == \"$SELECTED\")"
}
KUBECTL__LIST_SERVICES() {
KUBECTL get service --no-headers\
| awk '{print "{\"service\":\""$1"\",\"ip\":\""$3"\",\"port\":\""$5"\"}"}' \
| jq -c 'select (.ip != "None")' \
;
}
KUBECTL__GET_SERVICE_PASSWORD() {
[ $PASSWORD_SECRET ] && [ $PASSWORD_KEY ] || return 0
KUBECTL get secret $PASSWORD_SECRET -o jsonpath="{.data.$PASSWORD_KEY}" \
| base64 --decode
}
KUBECTL__SERVICE_PARSE() {
SERVICE_NAME=$(echo $SERVICE | jq -r .service)
SERVICE_PORT=$(echo $SERVICE | jq -r .port | sed 's|/.*$||')
}

58
plugins/kubectl/serve Executable file
View File

@ -0,0 +1,58 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
local USAGE="
usage: [service] [...options...]
args:
service (optional) name of the service to forward locally
options:
--context override context
--namespace override namespace
--subsession REDIS subsession (default 0)
to show a required password on screen, use both:
--password-secret Secret resource
--password-key key within Secret's 'data'
-h, --help show this dialogue and exit
"
local CONTEXT NAMESPACE SERVICE
local SUBSESSION=0
while [[ $# -gt 0 ]]
do
case $1 in
--context ) CONTEXT=$2; shift 1 ;;
--namespace ) NAMESPACE=$2; shift 1 ;;
--subsession ) SUBSESSION=$2; shift 1 ;;
--password-secret ) PASSWORD_SECRET=$2; shift 1 ;;
--password-key ) PASSWORD_KEY=$2; shift 1 ;;
-h | --help ) USAGE; return 0 ;;
* )
[ $SERVICE ] && ERROR "unexpected argument '$2'"
SERVICE=$1
;;
esac
shift 1
done
CHECK_ERRORS
KUBECTL__SERVE
}
#####################################################################
MAIN $@

View File

@ -17,6 +17,8 @@ MAIN() {
options:
--subsession REDIS subsession (default 0)
-h, --help show this dialogue and exit
"
local CONTEXT
local SUBSESSION=0
@ -26,6 +28,8 @@ MAIN() {
case $1 in
--subsession ) SUBSESSION=$2; shift 1 ;;
-h | --help ) USAGE; return 0 ;;
* )
[ $CONTEXT ] && ERROR "unexpected argument '$2'"
CONTEXT=$1

View File

@ -17,6 +17,8 @@ MAIN() {
options:
--subsession REDIS subsession (default 0)
-h, --help show this dialogue and exit
"
local NAMESPACE
local SUBSESSION=0
@ -26,6 +28,8 @@ MAIN() {
case $1 in
--subsession ) SUBSESSION=$2; shift 1 ;;
-h | --help ) USAGE; return 0 ;;
* )
[ $NAMESPACE ] && ERROR "unexpected argument '$2'"
NAMESPACE=$1

158
run
View File

@ -6,22 +6,35 @@ source "${0:a:h}/zsh/lib/import.driver.zsh" || exit 42
__RUN() {
local USAGE='
usage: scwrypts [OPTIONS ...] SCRIPT -- [SCRIPT OPTIONS ...]
usage: scwrypts [... options ...] [patterns] -- [...script options...]
OPTIONS
-g, --group <group-name> only use scripts from the indicated group
-t, --type <type-name> only use scripts of the indicated type
options:
selection
-m, --name <scwrypt-name> only run the script if there is an exact match
(requires type and group)
-g, --group <group-name> only use scripts from the indicated group
-t, --type <type-name> only use scripts of the indicated type
runtime
-y, --yes auto-accept all [yn] prompts through current scwrypt
-e, --env <env-name> set environment; overwrites SCWRYPTS_ENV
-n, --no-log skip logging and run in quiet mode
-q, --quiet run in quiet mode
-n, --no-log skip the log file and run in quiet mode
-v, --verbose override quiet mode settings and print all debug dialogue
--update update scwrypts library to latest version
-v, --version print out scwrypts version and exit
-l, --list print out command list and exit
alternate commands
-h, --help display this message and exit
-l, --list print out command list and exit
--list-envs print out environment list and exit
--update update scwrypts library to latest version
--version print out scwrypts version and exit
patterns:
- a list of glob patterns to loose-match a scwrypt by name
script options:
- everything after "--" is forwarded to the scwrypt you run
(usually "-- --help" will provide more information)
'
cd "$SCWRYPTS_ROOT"
@ -30,58 +43,29 @@ __RUN() {
local VARSPLIT SEARCH_GROUP SEARCH_TYPE SEARCH_NAME
local ALLOW_LOGFILE=1
local VERBOSE=1
[ $CI ] && [ ! $SCWRYPTS_CI_FORCE_NON_VERBOSE ] && VERBOSE=2
local ERROR=0
while [[ $# -gt 0 ]]
do
case $1 in
-t | --type )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_TYPE=$2
shift 2
;;
-g | --group )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_GROUP=$2
shift 2
;;
-m | --name )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_NAME=$2
shift 2
;;
-[a-z][a-z]* )
VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/')
set -- $(echo " $VARSPLIT ") ${@:2}
;;
-h | --help )
USAGE
return 0
;;
-n | --no-log )
[ ! $SUBSCWRYPT ] && SUBSCWRYPT=0
shift 1
;;
-e | --env )
[ ! $2 ] && ERROR "missing value for argument $1" && break
[ ! $SUBSCWRYPTS ] \
&& [ $ENV_NAME ] \
&& WARNING 'overwriting session environment' \
;
ENV_NAME="$2"
STATUS "using CLI environment '$ENV_NAME'"
shift 2
;;
-l | --list )
SCWRYPTS__GET_AVAILABLE_SCWRYPTS
return 0
;;
-v | --version )
echo scwrypts $(cd "$SCWRYPTS__ROOT__scwrypts"; git describe --tags)
-h | --help ) USAGE; return 0 ;;
-l | --list ) SCWRYPTS__GET_AVAILABLE_SCWRYPTS; return 0 ;;
--list-envs ) SCWRYPTS__GET_ENV_NAMES; return 0 ;;
--version )
echo scwrypts $(git -C "$SCWRYPTS__ROOT__scwrypts" describe --tags)
return 0
;;
--update )
cd "$SCWRYPTS__ROOT__scwrypts"
git fetch --quiet origin main
@ -104,24 +88,53 @@ __RUN() {
}
return 0
;;
-- )
shift 1
break # pass arguments after '--' to the scwrypt
;;
--* )
ERROR "unrecognized argument '$1'"
-m | --name )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_NAME=$2
shift 1
;;
* )
SEARCH_PATTERNS+=($1)
-g | --group )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_GROUP=$2
shift 1
;;
-t | --type )
[ ! $2 ] && ERROR "missing value for argument $1" && break
SEARCH_TYPE=$2
shift 1
;;
-y | --yes ) export __SCWRYPTS_YES=1 ;;
-q | --quiet ) VERBOSE=0 ;;
-n | --no-log ) VERBOSE=0 ; [ ! $SUBSCWRYPT ] && SUBSCWRYPT=0 ;;
-v | --verbose ) VERBOSE=2 ;;
-e | --env )
[ ! $2 ] && ERROR "missing value for argument $1" && break
[ ! $SUBSCWRYPTS ] \
&& [ $ENV_NAME ] \
&& WARNING 'overwriting session environment' \
;
ENV_NAME="$2"
STATUS "using CLI environment '$ENV_NAME'"
shift 1
;;
-- ) shift 1; break ;; # pass arguments after '--' to the scwrypt
--* ) ERROR "unrecognized argument '$1'" ;;
* ) SEARCH_PATTERNS+=($1) ;;
esac
shift 1
done
[ $SEARCH_NAME ] && {
[ ! $SEARCH_TYPE ] && ERROR '--name requires --type argument'
[ ! $SEARCH_GROUP ] && ERROR '--name requires --group argument'
[ $SEARCH_TYPE ] || ERROR '--name requires --type argument'
[ $SEARCH_GROUP ] || ERROR '--name requires --group argument'
}
CHECK_ERRORS
@ -195,9 +208,12 @@ __RUN() {
local TYPE="$SEARCH_TYPE"
local GROUP="$SEARCH_GROUP"
[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -eq 2 ]] \
&& SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | tail -n1) \
|| SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | FZF "select a script to run" --header-lines 1)
[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -eq 2 ]] && {
SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | tail -n1)
[[ $VERBOSE -eq 2 ]] || VERBOSE=0
} || {
SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | FZF "select a script to run" --header-lines 1)
}
[ $SCWRYPT_SELECTION ] || exit 2
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
@ -218,6 +234,7 @@ __RUN() {
[[ $ENV_REQUIRED -eq 1 ]] && {
[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV)
for GROUP in ${SCWRYPTS_GROUPS[@]}
do
local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME" "$GROUP")
@ -239,7 +256,8 @@ __RUN() {
##########################################
[ ! $SUBSCWRYPT ] \
: \
&& [ ! $SUBSCWRYPT ] \
&& [[ $ENV_NAME =~ prod ]] \
&& { __VALIDATE_UPSTREAM_TIMELINE || ABORT; }
@ -253,6 +271,7 @@ __RUN() {
local LOGFILE=$(__GET_LOGFILE)
local HEADER=$(
[[ $VERBOSE -gt 0 ]] || return 0
[ $SUBSCWRYPT ] && return 0
echo '====================================================================='
echo "script : $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME"
@ -274,14 +293,14 @@ __RUN() {
{
[ $HEADER ] && echo $HEADER
echo '\033[1;33m--- BEGIN OUTPUT -------------------------\033[0m'
[[ $VERBOSE -gt 0 ]] && echo '\033[1;33m--- BEGIN OUTPUT -------------------------\033[0m'
(eval "$RUN_STRING $(printf "%q " "$@")")
EXIT_CODE=$?
echo '\033[1;33m--- END OUTPUT ---------------------------\033[0m'
[[ $VERBOSE -gt 0 ]] && echo '\033[1;33m--- END OUTPUT ---------------------------\033[0m'
[[ $EXIT_CODE -eq 0 ]] && EXIT_COLOR='32m' || EXIT_COLOR='31m'
echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m"
[[ $VERBOSE -gt 0 ]] && echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m"
} 2>&1 | tee --append "$LOGFILE"
exit $(\
@ -323,10 +342,9 @@ __VALIDATE_UPSTREAM_TIMELINE() {
}
__GET_LOGFILE() {
[ $SUBSCWRYPT ] \
|| [[ $SCWRYPT_NAME =~ scwrypts/logs ]] \
|| [[ $SCWRYPT_NAME =~ interactive ]] \
&& return 0
[ $SUBSCWRYPT ] && return 0
[[ $SCWRYPT_NAME =~ scwrypts/logs ]] && return 0
[[ $SCWRYPT_NAME =~ interactive ]] && return 0
echo "$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log"
}

View File

@ -6,7 +6,7 @@ SCWRYPTS__ZSH_PLUGIN() {
local NAME
local TYPE
local GROUP
zle clear-command-line
LBUFFER= RBUFFER=
[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; }
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
@ -14,13 +14,40 @@ SCWRYPTS__ZSH_PLUGIN() {
which scwrypts >/dev/null 2>&1\
&& RBUFFER="scwrypts" || RBUFFER="$SCWRYPTS_ROOT/scwrypts"
RBUFFER+=" --name $NAME --group $GROUP --type $TYPE"
RBUFFER+=" --name $NAME --group $GROUP --type $TYPE --verbose"
zle accept-line
}
zle -N scwrypts SCWRYPTS__ZSH_PLUGIN
bindkey $SCWRYPTS_SHORTCUT scwrypts
#####################################################################
SCWRYPTS__ZSH_BUILDER_PLUGIN() {
local SCWRYPT_SELECTION=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS | FZF 'select a script' --header-lines 1)
local NAME
local TYPE
local GROUP
LBUFFER= RBUFFER=
[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; }
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
scwrypts --name $NAME --group $GROUP --type $TYPE -- --help >&2 || {
zle accept-line
return 0
}
echo
zle reset-prompt
which scwrypts >/dev/null 2>&1\
&& LBUFFER="scwrypts" || LBUFFER="$SCWRYPTS_ROOT/scwrypts"
LBUFFER+=" --name $NAME --group $GROUP --type $TYPE -- "
}
zle -N scwrypts-builder SCWRYPTS__ZSH_BUILDER_PLUGIN
bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder
#####################################################################
SCWRYPTS__ZSH_PLUGIN_ENV() {
local RESET='reset'

View File

@ -7,4 +7,4 @@ use cloud/aws/eks
CHECK_ENVIRONMENT
#####################################################################
EKS_CLUSTER_LOGIN $@
EKS__CLUSTER_LOGIN $@

View File

@ -1,19 +1,44 @@
#####################################################################
DEPENDENCIES+=(
kubectl
)
REQUIRED_ENV+=(
AWS_ACCOUNT
AWS_REGION
)
DEPENDENCIES+=(kubectl yq)
REQUIRED_ENV+=()
use cloud/aws/cli
#####################################################################
EKS_CLUSTER_LOGIN() {
EKS__KUBECTL() { EKS kubectl $@; }
EKS__FLUX() { EKS flux $@; }
#####################################################################
EKS() {
local USAGE="
usage: cli [...kubectl args...]
args:
cli a kubectl-style CLI (e.g. kubectl, helm, flux, etc)
Allows access to kubernetes CLI commands by configuring environment
to point to a specific cluster.
"
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT CLUSTER_NAME) DEPENDENCIES=(kubectl $1) CHECK_ENVIRONMENT || return 1
local CONTEXT="arn:aws:eks:${AWS_REGION}:${AWS_ACCOUNT}:cluster/${CLUSTER_NAME}"
local CONTEXT_ARGS=()
case $1 in
helm ) CONTEXT_ARGS+=(--kube-context $CONTEXT) ;;
* ) CONTEXT_ARGS+=(--context $CONTEXT) ;;
esac
$1 ${CONTEXT_ARGS[@]} ${@:2}
}
#####################################################################
EKS__CLUSTER_LOGIN() {
local USAGE="
usage: [...options...]
@ -25,6 +50,7 @@ EKS_CLUSTER_LOGIN() {
cluster in EKS. Also creates the kubeconfig entry if it does not
already exist.
"
REQUIRED_ENV=(AWS_ACCOUNT AWS_REGION) CHECK_ENVIRONMENT || return 1
local CLUSTER_NAME

View File

@ -0,0 +1,116 @@
#####################################################################
DEPENDENCIES+=(eksctl)
REQUIRED_ENV+=()
use cloud/aws/eks
#####################################################################
EKSCTL() {
REQUIRED_ENV=(AWS_PROFILE AWS_REGION) CHECK_ENVIRONMENT || return 1
AWS_PROFILE=$AWS_PROFILE AWS_REGION=$AWS_REGION \
eksctl $@
}
EKSCTL__CREATE_IAMSERVICEACCOUNT() {
local USAGE="
usage: serviceaccount-name namespace [...options...] -- [...'eksctl create iamserviceaccount' args...]
options:
--serviceaccount (required) target k8s:ServiceAccount
--namespace (required) target k8s:Namespace
--role-name (required) name of the IAM role to assign
--force don't check for existing serviceaccount and override any existing configuration
eksctl create iamserviceaccount args:
$(eksctl create iamserviceaccount --help 2>&1 | grep -v -- '--name' | grep -v -- '--namespace' | grep -v -- '--role-name' | sed 's/^/ /')
"
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT CLUSTER_NAME) CHECK_ENVIRONMENT || return 1
local SERVICEACCOUNT NAMESPACE ROLE_NAME
local FORCE=0
local EKSCTL_ARGS=()
while [[ $# -gt 0 ]]
do
case $1 in
--serviceaccount ) SERVICEACCOUNT=$2; shift 1 ;;
--namespace ) NAMESPACE=$2; shift 1 ;;
--role-name ) ROLE_NAME=$2; shift 1 ;;
--force ) FORCE=1 ;;
-- ) shift 1; break ;;
* ) ERROR "unknown argument '$1'" ;;
esac
shift 1
done
while [[ $# -gt 0 ]]; do EKSCTL_ARGS+=($1); shift 1; done
[ $SERVICEACCOUNT ] || ERROR "--serviceaccount is required"
[ $NAMESPACE ] || ERROR "--namespace is required"
[ $ROLE_NAME ] || ERROR "--role-name is required"
CHECK_ERRORS --no-fail || return 1
##########################################
[[ $FORCE -eq 0 ]] && {
_EKS__CHECK_IAMSERVICEACCOUNT_EXISTS
local EXISTS_STATUS=$?
case $EXISTS_STATUS in
0 )
SUCCESS "'$NAMESPACE/$SERVICEACCOUNT' already configured with '$ROLE_NAME'"
return 0
;;
1 ) ;; # role does not exist yet; continue with rollout
2 )
ERROR "'$NAMESPACE/$SERVICEACCOUNT' has been configured with a different role than '$ROLE_NAME'"
REMINDER "must use --force flag to overwrite"
return 2
;;
esac
}
STATUS "creating iamserviceaccount" \
&& EKSCTL create iamserviceaccount \
--cluster $CLUSTER_NAME \
--namespace $NAMESPACE \
--name $SERVICEACCOUNT \
--role-name $ROLE_NAME \
--override-existing-serviceaccounts \
--approve \
${EKSCTL_ARGS[@]} \
&& SUCCESS "successfully configured '$NAMESPACE/$SERVICEACCOUNT' with IAM role '$ROLE_NAME'" \
|| { ERROR "unable to configure '$NAMESPACE/$SERVICEACCOUNT' with IAM role '$ROLE_NAME' (check cloudformation dashboard for details)"; return 3; }
}
_EKS__CHECK_IAMSERVICEACCOUNT_EXISTS() {
STATUS "checking for existing role-arn"
local CURRENT_ROLE_ARN=$(
EKS__KUBECTL --namespace $NAMESPACE get serviceaccount $SERVICEACCOUNT -o yaml \
| YQ -r '.metadata.annotations["eks.amazonaws.com/role-arn"]' \
| grep -v '^null$' \
)
[ $CURRENT_ROLE_ARN ] || {
STATUS "serviceaccount does not exist or has no configured role"
return 1
}
[[ $CURRENT_ROLE_ARN =~ "$ROLE_NAME$" ]] || {
STATUS "serviceaccount current role does not match desired role:
CURRENT : $CURRENT_ROLE_ARN
DESIRED : arn:aws:iam::${AWS_ACCOUNT}:role/$ROLE_NAME
"
return 2
}
STATUS "serviceaccount current role matches desired role"
return 0
}

Binary file not shown.

View File

@ -47,6 +47,26 @@ do
}
done
#####################################################################
for GROUP_LOADER in $(env | sed -n 's/^SCWRYPTS_GROUP_LOADER__[a-z_]\+=//p')
do
[ -f "$GROUP_LOADER" ] && source "$GROUP_LOADER"
done
: \
&& [ ! "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] \
&& [ $GITHUB_WORKSPACE ] \
&& [ ! $SCWRYPTS_GITHUB_NO_AUTOLOAD ] \
&& SCWRYPTS_AUTODETECT_GROUP_BASEDIR="$GITHUB_WORKSPACE"
[ "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && [ -d "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && {
for GROUP_LOADER in $(find "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" -type f -name \*scwrypts.zsh)
do
[ -f "$GROUP_LOADER" ] && source "$GROUP_LOADER"
done
}
#####################################################################
[ $NO_EXPORT_CONFIG ] || __SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt
true

View File

@ -4,6 +4,7 @@ DEPENDENCIES+=(helm kubeval)
REQUIRED_ENV+=()
use helm/validate
use scwrypts
#####################################################################
@ -17,6 +18,8 @@ HELM__TEMPLATE__GET() {
--colorize use 'bat' to colorize output
--raw remove scwrypts-added fluff and only output helm template details
-h, --help show this help dialogue
Smart helm-template generator which auto-detects the chart
and sample values for testing and developing helm charts.
"
@ -35,8 +38,11 @@ HELM__TEMPLATE__GET() {
;;
--raw ) RAW=1 ;;
-h | --help ) USAGE; return 0 ;;
-- ) shift 1; break ;;
* ) HELM_ARGS+=($1) ;;
esac
shift 1
@ -60,6 +66,7 @@ HELM__TEMPLATE__GET() {
[ ! $TEMPLATE_OUTPUT ] && EXIT_CODE=1
[[ $RAW -eq 1 ]] && {
[ $USE_CHART_ROOT ] && [[ $USE_CHART_ROOT -eq 1 ]] || HELM_ARGS+=(--show-only $(echo $TEMPLATE_FILENAME | sed "s|^$CHART_ROOT/||"))
[[ $COLORIZE -eq 1 ]] \

View File

@ -27,13 +27,20 @@ HELM__VALIDATE() {
return 1
}
CHART_NAME=$(yq -r .name "$CHART_ROOT/Chart.yaml")
CHART_NAME=$(YQ -r .name "$CHART_ROOT/Chart.yaml")
[[ $TEMPLATE_FILENAME =~ values*.yaml$ ]] && {
[[ $TEMPLATE_FILENAME =~ values.*.yaml$ ]] && {
HELM_ARGS+=(--values $TEMPLATE_FILENAME)
USE_CHART_ROOT=1
}
[[ $TEMPLATE_FILENAME =~ tests/.*.yaml$ ]] && {
HELM_ARGS+=(--values $TEMPLATE_FILENAME)
USE_CHART_ROOT=1
}
[[ $TEMPLATE_FILENAME =~ .tpl$ ]] \
&& USE_CHART_ROOT=1
[[ $(dirname $TEMPLATE_FILENAME) =~ ^$CHART_ROOT$ ]] \
&& USE_CHART_ROOT=1
@ -54,9 +61,18 @@ _HELM__GET_CHART_ROOT() {
}
_HELM__GET_DEFAULT_VALUES_ARGS() {
for F in \
"$CHART_ROOT/tests/default.yaml" \
"$CHART_ROOT/values.test.yaml" \
"$CHART_ROOT/values.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS=(--values "$F" $HELM_ARGS)
done
for LOCAL_REPOSITORY in $(\
cat "$CHART_ROOT/Chart.yaml" \
| yq -r '.dependencies[] | .repository' \
| YQ -r '.dependencies[] | .repository' \
| grep '^file://' \
| sed 's|file://||' \
)
@ -67,22 +83,13 @@ _HELM__GET_DEFAULT_VALUES_ARGS() {
;
for F in \
"$LOCAL_REPOSITORY_ROOT/values.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.test.yaml" \
"$LOCAL_REPOSITORY_ROOT/tests/default.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.test.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS+=(--values "$F")
[ -f "$F" ] && HELM_ARGS=(--values "$F" $HELM_ARGS)
done
done
for F in \
"$CHART_ROOT/values.yaml" \
"$CHART_ROOT/values.test.yaml" \
"$CHART_ROOT/tests/default.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS+=(--values "$F")
done
}

View File

@ -0,0 +1,106 @@
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
#####################################################################
TALLY_USE_REDIS=false # maybe someday
TALLY_PATH="$SCWRYPTS_DATA_PATH/tally"
#####################################################################
TALLY() {
local USAGE="
usage: [...options...]
options:
-c, --increment-count increment the tally by this much (default 1)
-n, --tally-name name of tally system (default 'default')
-g, --get only output the current value
-s, --set set the tally to a specific value
-r, --reset set the tally back to zero
--raw only output the tally value
-h, --help print this dialogue and exit
Simple tally mark system; keep track of a count.
"
local INCREMENT_COUNT=1
local TALLY_NAME=default
local RAW=false
local SET_VALUE=
while [[ $# -gt 0 ]]
do
case $1 in
-c | --increment-count ) INCREMENT_COUNT=$2; shift 1 ;;
-n | --tally-name ) TALLY_NAME=$2; shift 1 ;;
-g | --get ) INCREMENT_COUNT=0 ;;
-s | --set ) SET_VALUE=$2; shift 1 ;;
-r | --reset ) SET_VALUE=0 ;;
--raw ) RAW=true ;;
-h | --help ) USAGE; return 0 ;;
* ) ERROR "unknown argument '$1'" ;;
esac
shift 1
done
[ $TALLY_NAME ] && echo "$TALLY_NAME" | grep -qv '/' \
|| ERROR "invalid tally name '$TALLY_NAME'"
local TALLY_FILENAME="$TALLY_PATH/$TALLY_NAME.txt"
CHECK_ERRORS --no-fail || return 1
##########################################
local NEW_VALUE CURRENT_VALUE=0
[ $SET_VALUE ] && NEW_VALUE=$SET_VALUE || {
[ -f "$TALLY_FILENAME" ] && {
CURRENT_VALUE=$(cat "$TALLY_FILENAME" | tail -n1 | grep '^[0-9]\+')
}
[ $CURRENT_VALUE ] || {
ERROR "malformed tally file '$TALLY_FILENAME'; aborting"
return 1
}
NEW_VALUE=$(($CURRENT_VALUE + $INCREMENT_COUNT))
}
##########################################
local TALLY_DIR="$(dirname "$TALLY_FILENAME")"
[ -d "$TALLY_DIR" ] || mkdir -p "$TALLY_DIR"
[ -d "$TALLY_DIR" ] || {
ERROR "unable to write to '$TALLY_DIR'; aborting"
return 1
}
echo "# autogenerated tally file; avoid direct modification\n$NEW_VALUE" > "$TALLY_FILENAME" || {
ERROR "failed to write to '$TALLY_FILENAME': aborting"
return 1
}
##########################################
case $RAW in
true ) printf "$NEW_VALUE" ;;
false )
case $TALLY_NAME in
default ) INFO "current tally : $NEW_VALUE" ;;
* ) INFO "$TALLY_NAME : $NEW_VALUE" ;;
esac
esac
}

View File

@ -17,6 +17,13 @@ __CHECK_DEPENDENCY() {
$E "application '$1' "$([[ $OPTIONAL -eq 1 ]] && echo preferred || echo required)" but not available on PATH $(__CREDITS $1)"
return 1
}
[[ $DEPENDENCY =~ ^yq$ ]] && {
yq --version | grep -q mikefarah \
|| WARNING 'detected kislyuk/yq but mikefarah/yq is preferred (compatibility may vary)'
}
return 0
}
__CHECK_COREUTILS() {
@ -36,7 +43,7 @@ __CHECK_COREUTILS() {
done
[[ $NON_GNU_DEPENDENCY_COUNT -gt 0 ]] && {
WARNING 'scripts rely on GNU coreutils; functionality may be limited'
WARNING 'scripts rely on GNU coreutils; compatibility may vary'
IS_MACOS && REMINDER 'GNU coreutils can be installed and linked through Homebrew'
}

View File

@ -43,11 +43,11 @@ SUCCESS() { PREFIX="SUCCESS ✔" COLOR=$__GREEN PRINT "$@"; }
WARNING() { PREFIX="WARNING " COLOR=$__ORANGE PRINT "$@"; }
STATUS() { PREFIX="STATUS " COLOR=$__BLUE PRINT "$@"; }
REMINDER() { PREFIX="REMINDER " COLOR=$__PURPLE PRINT "$@"; }
INFO() { PREFIX="INFO " COLOR=$__WHITE PRINT "$@"; }
INFO() { PREFIX="INFO " COLOR=$__WHITE PRINT "$@"; }
PROMPT() {
PREFIX="PROMPT " COLOR=$__CYAN PRINT "$@"
PREFIX="USER " COLOR=$__CYAN PRINT '' --no-line-end
PREFIX="USER " COLOR=$__CYAN PRINT '' --no-line-end
}
FAIL() { ERROR "${@:2}"; exit $1; }
@ -142,6 +142,7 @@ INPUT() {
Yn() {
PROMPT "$@ [Yn]"
[ $CI ] && { echo y; return 0; }
[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
local Yn; READ -k Yn; echo >&2
[[ $Yn =~ [nN] ]] && return 1 || return 0
@ -150,6 +151,7 @@ Yn() {
yN() {
PROMPT "$@ [yN]"
[ $CI ] && { echo y; return 0; }
[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
local yN; READ -k yN; echo >&2
[[ $yN =~ [yY] ]] && return 0 || return 1
@ -218,3 +220,12 @@ EDIT() {
$EDITOR $@ </dev/tty >/dev/tty
SUCCESS "finished editing '$1'!"
}
YQ() {
yq --version | grep -q mikefarah || {
yq $@
return $?
}
yq eval '... comments=""' | yq $@
}

17
zsh/misc/tally Executable file
View File

@ -0,0 +1,17 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use misc/tally
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
unset USAGE
TALLY $@
}
#####################################################################
MAIN $@

View File

@ -10,8 +10,9 @@ CHECK_ENVIRONMENT
PLUGIN_INSTALL() {
[ -d "$HOME/.vim/bundle/Vundle.vim" ] || {
mkdir -p "$HOME/.vim/bundle/"
git clone https://github.com/VundleVim/Vundle.vim.git "$HOME/vim/budle/Vundle.vim"
git clone https://github.com/VundleVim/Vundle.vim.git "$HOME/.vim/bundle/Vundle.vim"
}
VUNDLE__PLUGIN_INSTALL || return 1
VUNDLE__REBUILD_PLUGINS || return 2
}