Compare commits

..

5 Commits

Author SHA1 Message Date
ab567f6950 v3.6.0
=====================================================================

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

- Introducing an optional plugin for `kubectl` facilitation! Check out
  'plugins/kubectl/README.md' for more details.

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

- The function which lists all available scwrypts now ignores
  directories with a top-level base called "plugins." If this is a name
  conflict, you will need to define your own
  `SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__<group>` function!

  (ref the changes in 'zsh/lib/scwrypts/run.module.zsh')
2023-08-28 20:31:04 -06:00
e199e9bf91 v3.5.0
=====================================================================

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

- AWS (the cli wrapper) now checks for it's required variables *on run*.
  This accomodates scwrypts which may need to run in multiple regions,
  but make the downstream scwrypt responsible for adding AWS_REGION to
  the REQUIRED_ENV list!

- Got rid of all kinds of hackiness surrounding postgres password evals
  between both the postgres library and the rds library

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

- scwrypts --update now pulls tags for proper versioning
2023-08-24 17:11:34 -06:00
4c161aba49 v3.4.0
=====================================================================

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

- Allow the group variable `REQUIRED_ENVIRONMENT_REGEX` to enforce that
  only some environments can run within the group
2023-08-22 14:20:03 -06:00
3ea2e0cd8f v3.3.3
=====================================================================

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

- load static config files in all scwrypts contexts; not just groups
2023-08-18 12:40:14 -06:00
e0cbf58b3c v3.3.2
=====================================================================

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

- when using color, display properly in fzf
2023-08-11 08:39:30 -06:00
29 changed files with 635 additions and 90 deletions

View File

@ -0,0 +1,2 @@
#!/bin/zsh
export SCWRYPTS_KUBECTL_REDIS=

View File

@ -0,0 +1 @@
SCWRYPTS_KUBECTL_REDIS | (currently only 'managed') 'managed' or 'custom' redis configuration

View File

@ -0,0 +1,4 @@
export SCWRYPTS_KUBECTL_REDIS_HOST__managed=127.0.0.1
export SCWRYPTS_KUBECTL_REDIS_PORT__managed=26379
export SCWRYPTS_KUBECTL_REDIS_AUTH__managed=
export SCWRYPTS_KUBECTL_REDIS_KEY_PREFIX__managed=

10
plugins/kubectl/README.md Normal file
View File

@ -0,0 +1,10 @@
# Kubernetes `kubectl` Helper Plugin
Leverages a local `redis` application to quickly and easily set an alias `k` for `kubectl --context <some-context> --namespace <some-namespace>`.
Much like scwrypts environments, `k` aliases are *only* shared amongst session with the same `SCWRYPTS_ENV` to prevent accidental cross-contamination.
## Getting Started
Enable the plugin in `~/.config/scwrypts/config.zsh` by adding `SCWRYPTS_PLUGIN_ENABLED__KUBECTL=1`.
Use `k` as your new `kubectl` and checkout `k --help` and `k meta --help`.

16
plugins/kubectl/get-context Executable file
View File

@ -0,0 +1,16 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
KUBECTL__GET_CONTEXT
}
#####################################################################
MAIN $@

16
plugins/kubectl/get-namespace Executable file
View File

@ -0,0 +1,16 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
KUBECTL__GET_NAMESPACE
}
#####################################################################
MAIN $@

View File

@ -0,0 +1,31 @@
#####################################################################
command -v compdef >/dev/null 2>&1 || return 0
#####################################################################
_k() {
local C=$(k meta get context)
local NS=$(k meta get namespace)
local KUBEWORDS=(kubectl)
[ $C ] && KUBEWORDS+=(--context $C)
[ $NS ] && KUBEWORDS+=(--namespace $NS)
words="$KUBEWORDS ${words[@]:1}"
_kubectl
}
compdef _k k
#####################################################################
_h() {
local C=$(k meta get context)
local NS=$(k meta get namespace)
local KUBEWORDS=(kubectl)
[ $C ] && KUBEWORDS+=(--context $C)
[ $NS ] && KUBEWORDS+=(--namespace $NS)
words="$KUBEWORDS ${words[@]:1}"
_helm
}
compdef _h h

View File

@ -0,0 +1,173 @@
[[ $SCWRYPTS_KUBECTL_DRIVER_READY -eq 1 ]] && return 0
k() { _SCWRYPTS_KUBECTL_DRIVER kubectl $@; }
h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; }
_SCWRYPTS_KUBECTL_DRIVER() {
[ ! $SCWRYPTS_ENV ] && {
ERROR "must set SCWRYPTS_ENV in order to use '$(echo $CLI | head -c1)'"
return 1
}
which REDIS >/dev/null 2>&1 \
|| eval "$(scwrypts -n --name meta/get-static-redis-definition --type zsh --group kubectl)"
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_ARGS="$(for C in ${CUSTOM_COMMANDS[@]}; do echo " - $C"; done)"
local USAGE_OPTIONS="
-n, --namespace set the namespace for commands in '$SCWRYPTS_ENV'
-k, --context set the context for commands in '$SCWRYPTS_ENV'
"
local DESCRIPTION="
Provides 'k' (kubectl) and 'h' (helm) 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.
"
local USAGE="
usage: $(echo $CLI | head -c1) [...args...] [...options...] -- [...$CLI options...]
args: -
options: -
-h, --help display this help dialogue
-v, --verbose output debugging information
DESCRIPTION
"
##########################################
local USER_ARGS=()
local CUSTOM_COMMAND=0
PARAMETER_OVERRIDES+=
local VERBOSE=0
while [[ $# -gt 0 ]]
do
case $1 in
-v | --verbose ) VERBOSE=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)
shift 1
;;
meta )
CUSTOM_COMMAND=meta
USAGE_ARGS=" - get\n - set"
USAGE_OPTIONS=''
DESCRIPTION="perform meta-operations on $(echo $CLI | head -c1) for '$SCWRYPTS_ENV'"
case $2 in
-h | --help ) HELP=1 ;;
set )
USAGE_ARGS=" set (namespace|context)"
DESCRIPTION="interactively set a namespace or context for '$SCWRYPTS_ENV'"
case $3 in
namespace | context ) USER_ARGS+=($2 $3) ;;
-h | --help ) HELP=1 ;;
* ) ERROR "cannot set '$3'" >&2 ;;
esac
shift 1
;;
get )
USAGE_ARGS=" get (namespace|context)"
DESCRIPTION="output the current namespace or context for '$SCWRYPTS_ENV'"
case $3 in
namespace | context ) USER_ARGS+=($2 $3) ;;
-h | --help ) HELP=1 ;;
* ) ERROR "cannot get '$3'" >&2 ;;
esac
shift 1
;;
esac
shift 1
;;
-h | --help ) HELP=1 ;;
-- ) shift 1; break ;;
* ) USER_ARGS+=($1) ;;
esac
shift 1
done
while [[ $# -gt 0 ]]; do USER_ARGS+=($1); shift 1; done
CHECK_ERRORS --no-fail 2>&1 | sed 's/scwrypts -- //' >&2 || return 1
[[ $HELP -eq 1 ]] && {
[[ ! $CUSTOM_COMMAND =~ ^0$ ]] \
&& USAGE=$(echo $USAGE | sed "s/[[]\\.\\.\\.args\\.\\.\\.[]]/$CUSTOM_COMMAND &/")
USAGE=$(echo $USAGE | perl -pe "
s/args: -/args:\n$USAGE_ARGS/;
s^options: -^options:$USAGE_OPTIONS^;
s/DESCRIPTION/$DESCRIPTION/;
")
USAGE 2>&1 | sed 's/scwrypts -- //' >&2
return 0
}
#####################################################################
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)
[ $NAMESPACE ] && CLI_ARGS+=(--namespace $NAMESPACE)
[[ $VERBOSE -eq 1 ]] && {
INFO "
using context '$CONTEXT'
using namespace '$NAMESPACE'
"
STATUS "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}"
}
$CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}
;;
* ) eval 'SCWRYPTS_KUBECTL_CUSTOM_COMMAND__'$CUSTOM_COMMAND ${USER_ARGS[@]} ;;
esac
}
SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta() {
case $1 in
get ) REDIS get --prefix current:$2; return 0 ;;
set ) scwrypts --name set-$2 --type zsh --group kubectl ;;
esac
}
#####################################################################
source ${0:a:h}/kubectl.driver.completion.zsh

View File

@ -0,0 +1,11 @@
SCWRYPTS_GROUPS+=(kubectl)
export SCWRYPTS_TYPE__kubectl=zsh
export SCWRYPTS_ROOT__kubectl="$SCWRYPTS_ROOT__scwrypts/plugins/kubectl"
export SCWRYPTS_COLOR__kubectl='\033[0;31m'
SCWRYPTS_STATIC_CONFIG__kubectl+=(
"$SCWRYPTS_ROOT__kubectl/.config/static/redis.zsh"
)
source "$SCWRYPTS_ROOT__kubectl/kubectl.driver.zsh"

View File

@ -0,0 +1,79 @@
#####################################################################
DEPENDENCIES+=(
kubectl
)
REQUIRED_ENV+=()
use redis --group kubectl
#####################################################################
KUBECTL() {
local NAMESPACE=$(REDIS get --prefix "current:namespace")
local CONTEXT=$(KUBECTL__GET_CONTEXT)
local KUBECTL_ARGS=()
[ $NAMESPACE ] && KUBECTL_ARGS+=(--namespace $NAMESPACE)
[ $CONTEXT ] && KUBECTL_ARGS+=(--context $CONTEXT)
kubectl ${KUBECTL_ARGS[@]} $@
}
#####################################################################
KUBECTL__GET_CONTEXT() { REDIS get --prefix "current:context"; }
KUBECTL__SET_CONTEXT() {
local CONTEXT=$1
[ ! $CONTEXT ] && return 1
[[ $CONTEXT =~ default ]] && {
: \
&& REDIS del --prefix "current:context" \
&& KUBECTL__SET_NAMESPACE default \
;
return $?
}
: \
&& REDIS set --prefix "current:context" "$CONTEXT" \
&& KUBECTL__SET_NAMESPACE default \
;
}
KUBECTL__SELECT_CONTEXT() {
KUBECTL__LIST_CONTEXTS | FZF 'select a context'
}
KUBECTL__LIST_CONTEXTS() {
echo default
KUBECTL config get-contexts -o name | sort
}
#####################################################################
KUBECTL__GET_NAMESPACE() { REDIS get --prefix "current:namespace"; }
KUBECTL__SET_NAMESPACE() {
local NAMESPACE=$1
[ ! $NAMESPACE ] && return 1
[[ $NAMESPACE =~ default ]] && {
REDIS del --prefix "current:namespace"
return $?
}
REDIS set --prefix "current:namespace" "$NAMESPACE"
}
KUBECTL__SELECT_NAMESPACE() {
KUBECTL__LIST_NAMESPACES | FZF 'select a namespace'
}
KUBECTL__LIST_NAMESPACES() {
echo default
KUBECTL get namespaces -o name | sed 's/^namespace\///' | sort
}

View File

@ -0,0 +1,90 @@
#####################################################################
DEPENDENCIES+=(
redis-cli
docker
)
# TODO; allow custom redis configuration
export SCWRYPTS_KUBECTL_REDIS=managed
REQUIRED_ENV+=(
SCWRYPTS_KUBECTL_REDIS
)
#####################################################################
REDIS() {
[ ! $USAGE ] && local USAGE="
usage: [...options...]
options:
-p, --prefix apply dynamic prefix to the next command line argument
--get-prefix output key prefix for current session
--get-static-definition output the static ZSH function definition for REDIS
other arguments are passed through to redis-cli
"
local REDIS_ARGS=() USER_ARGS=()
local REDIS_PREFIX=$(eval echo '$SCWRYPTS_KUBECTL_REDIS_KEY_PREFIX__'$SCWRYPTS_KUBECTL_REDIS)
local ECHO_STATIC_DEFINITION=0
while [[ $# -gt 0 ]]
do
case $1 in
-p | --prefix ) USER_ARGS+=("${SCWRYPTS_ENV}:${REDIS_PREFIX}$2"); shift 1 ;;
--get-prefix ) echo $REDIS_PREFIX; return 0 ;;
--get-static-definition ) ECHO_STATIC_DEFINITION=1 ;;
* ) USER_ARGS+=($1) ;;
esac
shift 1
done
local REDIS_HOST=$(eval echo '$SCWRYPTS_KUBECTL_REDIS_HOST__'$SCWRYPTS_KUBECTL_REDIS)
local REDIS_PORT=$(eval echo '$SCWRYPTS_KUBECTL_REDIS_PORT__'$SCWRYPTS_KUBECTL_REDIS)
local REDIS_AUTH=$(eval echo '$SCWRYPTS_KUBECTL_REDIS_AUTH__'$SCWRYPTS_KUBECTL_REDIS)
[ $REDIS_HOST ] && REDIS_ARGS+=(-h $REDIS_HOST)
[ $REDIS_PORT ] && REDIS_ARGS+=(-p $REDIS_PORT)
[ $REDIS_AUTH ] && REDIS_ARGS+=(-a $REDIS_AUTH)
REDIS_ARGS+=(--raw)
[[ $ECHO_STATIC_DEFINITION -eq 1 ]] && {
echo "REDIS() {\
local USER_ARGS=(); \
while [[ \$# -gt 0 ]]; \
do \
case \$1 in
-p | --prefix ) USER_ARGS+=(\"\${SCWRYPTS_ENV}:${REDIS_PREFIX}\$2\"); shift 1 ;; \
* ) USER_ARGS+=(\$1) ;; \
esac; \
shift 1; \
done; \
redis-cli ${REDIS_ARGS[@]} \${USER_ARGS[@]}; \
}" | sed 's/\s\+/ /g'
return 0
}
redis-cli ${REDIS_ARGS[@]} ${USER_ARGS[@]}
}
REDIS ping | grep -qi pong || {
RPID=$(docker ps -a | grep scwrypts-kubectl-redis | awk '{print $1;}')
[ $RPID ] && STATUS 'refreshing redis instance' && docker rm -f $RPID
unset RPID
docker run \
--detach \
--name scwrypts-kubectl-redis \
--publish $SCWRYPTS_KUBECTL_REDIS_PORT__managed:6379 \
redis >/dev/null 2>&1
STATUS 'awaiting redis connection'
until REDIS ping 2>/dev/null | grep -qi pong; do sleep 0.5; done
}

View File

@ -0,0 +1,11 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use redis --group kubectl
CHECK_ENVIRONMENT
#####################################################################
echo $(REDIS --get-static-definition)

28
plugins/kubectl/set-context Executable file
View File

@ -0,0 +1,28 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
local USAGE="
usage: [context]
args:
context the full name of the kubeconfig context to set
"
local CONTEXT="$1"
[ $CONTEXT ] || $(KUBECTL__SELECT_CONTEXT)
[ $CONTEXT ] || ERROR 'must provide or select a valid kube context'
CHECK_ERRORS
KUBECTL__SET_CONTEXT $CONTEXT
}
#####################################################################
MAIN $@

28
plugins/kubectl/set-namespace Executable file
View File

@ -0,0 +1,28 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
local USAGE="
usage: [namespace]
args:
namespace the full name of the namespace to set
"
local NAMESPACE="$1"
[ $NAMESPACE ] || $(KUBECTL__SELECT_NAMESPACE)
[ $NAMESPACE ] || ERROR 'must provide or select a valid namespace'
CHECK_ERRORS
KUBECTL__SET_NAMESPACE $NAMESPACE
}
#####################################################################
MAIN $@

20
run
View File

@ -85,6 +85,7 @@ __RUN() {
--update )
cd "$SCWRYPTS__ROOT__scwrypts"
git fetch --quiet origin main
git fetch --quiet origin main --tags
local SYNC_STATUS=$?
git diff --exit-code origin/main -- . >&2
@ -208,6 +209,12 @@ __RUN() {
##########################################
local ENV_REQUIRED=$(__CHECK_ENV_REQUIRED && echo 1 || echo 0)
local REQUIRED_ENVIRONMENT_REGEX=$(eval echo '$SCWRYPTS_REQUIRED_ENVIRONMENT_REGEX__'$SCWRYPT_GROUP)
[ $REQUIRED_ENVIRONMENT_REGEX ] && {
[[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \
|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)"
}
[[ $ENV_REQUIRED -eq 1 ]] && {
[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV)
@ -215,15 +222,20 @@ __RUN() {
do
local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME" "$GROUP")
source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$GROUP/$ENV_NAME'"
for f in $(eval 'echo $SCWRYPTS_STATIC_CONFIG__'$GROUP)
do
source "$f" || FAIL 5 "invalid static config '$f'"
done
done
export ENV_NAME
}
for f in $(eval 'echo $SCWRYPTS_STATIC_CONFIG__'$SCWRYPT_GROUP)
do
source "$f" || FAIL 5 "invalid static config '$f'"
done
[ $REQUIRED_ENVIRONMENT_REGEX ] && {
[[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \
|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)"
}
##########################################

View File

@ -12,13 +12,7 @@ CREATE_BACKUP() {
local DB_HOST DB_PORT DB_NAME DB_USER DB_PASS
RDS__GET_DATABASE_CREDENTIALS $@ || return 1
PG_DUMP \
--host $DB_HOST \
--port $DB_PORT \
--name $DB_NAME \
--user $DB_USER \
--pass $DB_PASS \
;
PG_DUMP
}
#####################################################################

View File

@ -12,13 +12,7 @@ RDS_INTERACTIVE_LOGIN() {
local DB_HOST DB_PORT DB_NAME DB_USER DB_PASS
RDS__GET_DATABASE_CREDENTIALS $@ || return 1
POSTGRES__LOGIN_INTERACTIVE \
--host $DB_HOST \
--port $DB_PORT \
--name $DB_NAME \
--user $DB_USER \
--pass $DB_PASS \
;
POSTGRES__LOGIN_INTERACTIVE
}

View File

@ -12,13 +12,7 @@ LOAD_BACKUP() {
local DB_HOST DB_PORT DB_NAME DB_USER DB_PASS
RDS__GET_DATABASE_CREDENTIALS $@ || return 1
PG_RESTORE \
--host $DB_HOST \
--port $DB_PORT \
--name $DB_NAME \
--user $DB_USER \
--pass $DB_PASS \
;
PG_RESTORE
}

View File

@ -4,15 +4,13 @@ DEPENDENCIES+=(
aws
)
REQUIRED_ENV+=(
AWS_ACCOUNT
AWS_PROFILE
AWS_REGION
)
REQUIRED_ENV+=()
#####################################################################
AWS() {
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT AWS_PROFILE) CHECK_ENVIRONMENT || return 1
aws \
--profile $AWS_PROFILE \
--region $AWS_REGION \

View File

@ -86,14 +86,9 @@ RDS__GET_DATABASE_CREDENTIALS() {
user-input ) _RDS_AUTH__userinput ;;
esac
STATUS
STATUS "host : $DB_HOST"
STATUS "type : $DB_TYPE"
STATUS "port : $DB_PORT"
STATUS "database : $DB_NAME"
STATUS "username : $DB_USER"
[[ $PRINT_PASSWORD -eq 1 ]] && STATUS "password : $DB_PASS"
STATUS
[[ $PRINT_PASSWORD -eq 1 ]] && INFO "password : $DB_PASS"
return 0
}
_RDS_AUTH__iam() {
@ -108,10 +103,10 @@ _RDS_AUTH__iam() {
_RDS_AUTH__secretsmanager() {
local CREDENTIALS=$(_RDS__GET_SECRETSMANAGER_CREDENTIALS)
echo $CREDENTIALS | jq -e '.pass' >/dev/null 2>&1 \
&& DB_PASS="'$(echo $CREDENTIALS | jq -r '.pass' | sed "s/'/'\"'\"'/g")'"
&& DB_PASS="$(echo $CREDENTIALS | jq -r '.pass')"
echo $CREDENTIALS | jq -e '.password' >/dev/null 2>&1 \
&& DB_PASS="'$(echo $CREDENTIALS | jq -r '.password' | sed "s/'/'\"'\"'/g")'"
&& DB_PASS="$(echo $CREDENTIALS | jq -r '.password')"
echo $CREDENTIALS | jq -e '.user' >/dev/null 2>&1 \
&& DB_USER=$(echo $CREDENTIALS | jq -r '.user')

Binary file not shown.

View File

@ -38,5 +38,11 @@ SCWRYPTS_GROUPS=($(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u))
source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \
|| FAIL 69 'failed to set up scwrypts group; aborting'
#####################################################################
[[ $SCWRYPTS_PLUGIN_ENABLED__kubectl -eq 1 ]] && {
source "$SCWRYPTS_ROOT/plugins/kubectl/kubectl.scwrypts.zsh"
}
#####################################################################
__SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt

View File

@ -4,7 +4,6 @@ DEPENDENCIES+=(
pg_dump
pg_restore
psql
pgcli
)
REQUIRED_ENV+=()
@ -12,22 +11,22 @@ REQUIRED_ENV+=()
#####################################################################
PSQL() {
[[ ${#ARGS[@]} -eq 0 ]] && POSTGRES__SET_LOGIN_ARGS $@
eval PGPASSWORD=$_PASS psql ${_ARGS[@]}
POSTGRES__SET_LOGIN_ARGS $@
eval PGPASSWORD=$(printf '%q ' "$DB_PASS") psql ${PSQL_ARGS[@]}
}
#####################################################################
PG_DUMP() {
local _HOST _NAME _PORT _USER _FILE
local DATA_DIR _PASS _ARGS=()
local DATA_DIR
POSTGRES__SET_LOGIN_ARGS --verbose $@
local OUTPUT_FILE="$DATA_DIR/backup.$(date '+%Y-%m-%d.%H-%M')"
STATUS "
making backup of : $_USER@$_HOST:$_PORT/$_NAME
making backup of : $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME
(compressed) : '$OUTPUT_FILE.dump'
(safe-raw) : '$OUTPUT_FILE.sql'
@ -36,23 +35,33 @@ PG_DUMP() {
: \
&& STATUS "creating compressed backup..." \
&& eval PGPASSWORD=$_PASS pg_dump ${_ARGS[@]} --format custom --file "$OUTPUT_FILE.dump" \
&& eval PGPASSWORD=$(printf '%q ' "$DB_PASS") psql ${PSQL_ARGS[@]} \
--format custom \
--file "$OUTPUT_FILE.dump" \
--verbose \
&& SUCCESS "completed compressed backup" \
&& STATUS "creating raw backup..." \
&& eval PGPASSWORD=$_PASS pg_dump ${_ARGS[@]} > "$OUTPUT_FILE.raw.sql" \
&& pg_restore -f "$OUTPUT_FILE.raw.sql" "$OUTPUT_FILE.dump" \
&& SUCCESS "completed raw backup" \
&& STATUS "creating single-transaction raw backup..." \
&& { echo "BEGIN;"; cat "$OUTPUT_FILE.raw.sql"; echo "END;" } > "$OUTPUT_FILE.sql" \
&& { echo "BEGIN;\n"; cat "$OUTPUT_FILE.raw.sql"; echo "\nEND;" } > "$OUTPUT_FILE.sql" \
&& SUCCESS "completed single-transaction raw backup" \
|| { ERROR "error creating backup for '$_HOST/$_NAME' (see above)"; return 1; }
|| { ERROR "error creating backup for '$DB_HOST/$DB_NAME' (see above)"; return 1; }
SUCCESS "
completed backup : $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME
(compressed) : '$OUTPUT_FILE.dump'
(safe-raw) : '$OUTPUT_FILE.sql'
(raw) : '$OUTPUT_FILE.raw.sql'
"
}
#####################################################################
PG_RESTORE() {
local _HOST _NAME _PORT _USER
local _PASS _ARGS=()
local _FILE
local _ARGS=()
local FILE
POSTGRES__SET_LOGIN_ARGS $@
local INPUT_FILE=$(find "$DATA_DIR"/backup.* -type f | FZF 'select database file to restore')
@ -72,7 +81,7 @@ PG_RESTORE() {
[[ $INPUT_FILE =~ \\.dump$ ]] && RAW=0
STATUS "
loading backup for : $_USER@$_HOST:$_PORT/$_NAME
loading backup for : $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME
file : '$INPUT_FILE'
"
@ -92,7 +101,7 @@ PG_RESTORE() {
}
[[ $RAW -eq 0 ]] && {
PGPASSWORD="$_PASS" pg_restore ${_ARGS[@]} \
eval PGPASSWORD=$(printf '%q ' "$DB_PASS") pg_restore ${PSQL_ARGS[@]} \
--verbose \
--format custom \
--single-transaction \
@ -101,8 +110,8 @@ PG_RESTORE() {
}
[[ $EXIT_CODE -eq 0 ]] \
&& SUCCESS "finished restoring backup for '$_HOST/$_NAME'" \
|| ERROR "error restoring backup for '$_HOST/$_NAME' (see above)" \
&& SUCCESS "finished restoring backup for '$DB_HOST/$DB_NAME'" \
|| ERROR "error restoring backup for '$DB_HOST/$DB_NAME' (see above)" \
;
return $EXIT_CODE
@ -111,48 +120,70 @@ PG_RESTORE() {
#####################################################################
POSTGRES__LOGIN_INTERACTIVE() {
local _PASS _ARGS=()
DEPENDENCIES=(pgcli) CHECK_ENVIRONMENT --optional \
&& COMMAND=pgcli || COMMAND=psql
[[ $COMMAND =~ psql ]] && WARNING "using 'psql' instead"
POSTGRES__SET_LOGIN_ARGS $@
STATUS "performing login : $_USER@$_HOST:$_PORT/$_NAME"
STATUS "working directory : $DATA_DIR"
STATUS "
performing login : $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME
working directory : $DATA_DIR
"
eval PGPASSWORD=$_PASS pgcli ${_ARGS[@]}
eval PGPASSWORD=$(printf '%q ' "$DB_PASS") $COMMAND ${PSQL_ARGS[@]}
}
#####################################################################
POSTGRES__SET_LOGIN_ARGS() {
# allow for manual override with PSQL_ARGS
[[ ${#PSQL_ARGS[@]} -gt 0 ]] && return 0
local DATA_DIR_PREFIX
while [[ $# -gt 0 ]]
do
case $1 in
--host ) _ARGS+=(-h $2); _HOST="$2"; shift 1 ;;
--name ) _ARGS+=(-d $2); _NAME="$2"; shift 1 ;;
--port ) _ARGS+=(-p $2); _PORT="$2"; shift 1 ;;
--user ) _ARGS+=(-U $2); _USER="$2"; shift 1 ;;
-h | --host ) DB_HOST="$2"; shift 1 ;;
-p | --port ) DB_PORT="$2"; shift 1 ;;
-d | --name ) DB_NAME="$2"; shift 1 ;;
-U | --user ) DB_USER="$2"; shift 1 ;;
-P | --pass ) DB_PASS="$2"; shift 1 ;;
--pass ) _PASS="$2"; shift 1 ;;
--file ) PSQL_FILE="$2"; shift 1 ;;
--file ) _FILE="$2"; shift 1 ;;
--data-dir-prefix ) DATA_DIR_PREFIX="$2"; shift 1 ;;
* ) _ARGS+=($1) ;;
* ) PSQL_ARGS+=($1) ;;
esac
shift 1
done
[ $_FILE ] && [ ! -f "$_FILE" ] && {
ERROR "no such file '$_FILE'"
exit 1
[ $PSQL_FILE ] && [ ! -f "$PSQL_FILE" ] \
&& ERROR "no such file available:\n'$PSQL_FILE'"
CHECK_ERRORS
##########################################
[ $DATA_DIR_PREFIX ] && {
DATA_DIR="$SCWRYPTS_DATA_PATH/$DATA_DIR_PREFIX"
} || {
[ $DB_HOST ] && [ $DB_NAME ] \
&& DATA_DIR="$SCWRYPTS_DATA_PATH/db/$DB_HOST/$DB_NAME" \
|| DATA_DIR="$EXECUTION_DIR/temp-db" \
;
}
[ $_HOST ] && [ $_NAME ] \
&& DATA_DIR="$SCWRYPTS_DATA_PATH/db/$_HOST/$_NAME" \
|| DATA_DIR="$EXECUTION_DIR/temp-db" \
;
[ ! -d "$DATA_DIR" ] && mkdir -p "$DATA_DIR"
mkdir -p "$DATA_DIR"
cd "$DATA_DIR"
return 0
}
[ $DB_HOST ] || DB_HOST=127.0.0.1
[ $DB_PORT ] || DB_PORT=5432
[ $DB_NAME ] || DB_NAME=postgres
[ $DB_USER ] || DB_USER=postgres
PSQL_ARGS+=(-h $DB_HOST -p $DB_PORT -d $DB_NAME -U $DB_USER)
}

View File

@ -64,7 +64,11 @@ SCWRYPTS__GET_ENV_NAMES() {
ERROR 'environment initialization error'
return 1
}
ls "$SCWRYPTS_ENV_PATH/scwrypts" | sort -r
[ $REQUIRED_ENVIRONMENT_REGEX ] && {
ls "$SCWRYPTS_ENV_PATH/scwrypts" | grep "$REQUIRED_ENVIRONMENT_REGEX" | sort -r
} || {
ls "$SCWRYPTS_ENV_PATH/scwrypts" | sort -r
}
}
SCWRYPTS__INIT_ENVIRONMENTS() {

View File

@ -54,6 +54,7 @@ SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__scwrypts() {
| grep -v '\.git' \
| grep -v 'node_modules' \
| sed "s/^\\.\\///; s/\\.[^.]*$//; s/^/$GROUP_TYPE/" \
| grep -v '^plugins/' \
;
}

View File

@ -1,5 +1,6 @@
__CHECK_DEPENDENCIES() {
local DEP ERROR=0
[ ! $E ] && E=ERROR
DEPENDENCIES=($(echo $DEPENDENCIES | sed 's/ \+/\n/g' | sort -u))
@ -13,7 +14,7 @@ __CHECK_DEPENDENCY() {
local DEPENDENCY="$1"
[ ! $DEPENDENCY ] && return 1
command -v $DEPENDENCY >/dev/null 2>&1 || {
ERROR "'$1' required but not available on PATH $(__CREDITS $1)"
$E "application '$1' "$([[ $OPTIONAL -eq 1 ]] && echo preferred || echo required)" but not available on PATH $(__CREDITS $1)"
return 1
}
}

View File

@ -32,7 +32,7 @@ __CHECK_ENV_VAR() {
[ $DEFAULT_VALUE ] && $NAME="$DEFAULT_VALUE"
return 0
} || {
ERROR "'$NAME' required"
ERROR "variable '$NAME' required"
return 1
}
}

View File

@ -99,7 +99,7 @@ Yn() {
PROMPT "$@ [Yn]"
[ $CI ] && { echo y; return 0; }
local Yn; READ -k Yn; echo
local Yn; READ -k Yn; echo >&2
[[ $Yn =~ [nN] ]] && return 1 || return 0
}
@ -107,7 +107,7 @@ yN() {
PROMPT "$@ [yN]"
[ $CI ] && { echo y; return 0; }
local yN; READ -k yN; echo
local yN; READ -k yN; echo >&2
[[ $yN =~ [yY] ]] && return 0 || return 1
}
@ -128,7 +128,15 @@ FZF() {
exit 1
}
local SELECTION=$(fzf -i --height=30% --layout=reverse --prompt "$1 : " ${@:2})
local FZF_ARGS=()
FZF_ARGS+=(-i)
FZF_ARGS+=(--ansi)
FZF_ARGS+=(--bind=ctrl-c:cancel)
FZF_ARGS+=(--height=50%)
FZF_ARGS+=(--layout=reverse)
local SELECTION=$(fzf ${FZF_ARGS[@]} --layout=reverse --prompt "$1 : " ${@:2})
PROMPT "$1"
echo $SELECTION >&2
echo $SELECTION

View File

@ -18,6 +18,12 @@ source ${0:a:h}/environment.zsh
#####################################################################
CHECK_ENVIRONMENT() {
local OPTIONAL=0
[[ $1 =~ --optional ]] && OPTIONAL=1
[[ $OPTIONAL -eq 1 ]] \
&& E=WARNING || E=ERROR
local ENVIRONMENT_STATUS=0
__CHECK_DEPENDENCIES $DEPENDENCIES
@ -55,9 +61,9 @@ CHECK_ENVIRONMENT() {
##########################################
[[ ENVIRONMENT_STATUS -eq 0 ]] || {
[[ ENVIRONMENT_STATUS -ne 0 ]] && [[ $OPTIONAL -eq 0 ]] && {
ERROR_MESSAGE=$(echo $ERROR_MESSAGE | sed '1d; s/^/ /')
ERROR "environment errors found (see above)\n$ERROR_MESSAGE"
$E "environment errors found (see above)\n$ERROR_MESSAGE"
}
[[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && {
@ -67,10 +73,11 @@ CHECK_ENVIRONMENT() {
"
}
[[ $ENVIRONMENT_STATUS -eq 0 ]] || {
[[ $NO_EXIT -eq 1 ]] && return $ENVIRONMENT_STATUS
[[ $ENVIRONMENT_STATUS -ne 0 ]] && [[ $NO_EXIT -ne 1 ]] && [[ $OPTIONAL -eq 0 ]] && {
exit $ENVIRONMENT_STATUS
}
return $ENVIRONMENT_STATUS
}
CHECK_ENVIRONMENT