Compare commits

..

15 Commits

Author SHA1 Message Date
531aa52146 v3.6.4
=====================================================================

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

- Introduced lazy environment variable checking on ECR_LOGIN
2023-10-19 14:44:01 -06:00
f8ccce9285 v3.6.3
=====================================================================

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

- Silenced a startup error
2023-10-05 14:40:45 -06:00
6fc17bcfe5 v3.6.2
=====================================================================

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

- fixed some bugs with kubectl plugin preloading and argument processing
2023-10-05 14:36:40 -06:00
2034325ac9 v3.6.1
=====================================================================

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

- Adjusted USAGE (from zsh/lib/utils/io.zsh) to allow dynamic variable
  insertion in help dialogues by setting USAGE__<help-group> and using
  the syntax listed

- Various quality-of-life changes and and fixes to experimental kubectl
  plugin

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

- sourcing 'scwrypts.plugin.zsh' no longer sets __SCWRYPT=1 in your
  current environment
2023-08-30 17:26:13 -06:00
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
09c214f939 v3.3.1
=====================================================================

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

- fixed a bug with creating environment files for new scwrypts groups
2023-07-20 15:19:44 -06:00
e2c6007a65 v3.3.0
=====================================================================

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

- system/config/symlink )
   now copies the existing config from the current system if
   the "source" config does not exist (init from local)

- allowed implementation of group-custom scwrypt listing function
   GET_AVAILABLE_SCWRYPTS__<group-name>

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

- fixed a bug where custom runstring operators were ignored
2023-07-20 15:11:07 -06:00
620d07f1a8 v3.2.1
=====================================================================

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

 - fixed bug with initializing virtual environments
2023-06-27 18:30:29 -06:00
4baacd9c32 v3.2.0
=====================================================================

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

- split up environment files per scwrypts group

- updated i3/launch-or-show to provide some new options

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

- utils/io commands like 'STATUS' no longer throw errors '%' characters

- fixed ERROR_CHECK function calls to CHECK_ERRORS
2023-06-27 16:35:30 -06:00
6c546ebb6f v3.1.0
=====================================================================

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

- improved capability of py/discord/post-message to include username
  flag, and defaults for each value in env config
2023-06-24 07:40:31 -06:00
9783119a7d v3.0.2
=====================================================================

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

- interactive scripts work again

- color works on zx again
2023-06-22 17:58:55 -06:00
46 changed files with 1203 additions and 265 deletions

View File

@ -6,8 +6,12 @@ export AWS__EFS__LOCAL_MOUNT_POINT=
export DIRECTUS__API_TOKEN= export DIRECTUS__API_TOKEN=
export DIRECTUS__BASE_URL= export DIRECTUS__BASE_URL=
export DISCORD__BOT_TOKEN= export DISCORD__BOT_TOKEN=
export DISCORD__CONTENT_FOOTER=
export DISCORD__CONTENT_HEADER=
export DISCORD__DEFAULT_AVATAR_URL= export DISCORD__DEFAULT_AVATAR_URL=
export DISCORD__DEFAULT_CHANNEL_ID= export DISCORD__DEFAULT_CHANNEL_ID=
export DISCORD__DEFAULT_USERNAME=
export DISCORD__DEFAULT_WEBHOOK=
export I3__BORDER_PIXEL_SIZE= export I3__BORDER_PIXEL_SIZE=
export I3__DMENU_FONT_SIZE= export I3__DMENU_FONT_SIZE=
export I3__GLOBAL_FONT_SIZE= export I3__GLOBAL_FONT_SIZE=

View File

@ -8,8 +8,12 @@ DIRECTUS__API_TOKEN | details for a directus instance
DIRECTUS__BASE_URL | DIRECTUS__BASE_URL |
DISCORD__BOT_TOKEN | details for discord bot DISCORD__BOT_TOKEN | details for discord bot
DISCORD__CONTENT_HEADER |
DISCORD__CONTENT_FOOTER |
DISCORD__DEFAULT_AVATAR_URL | DISCORD__DEFAULT_AVATAR_URL |
DISCORD__DEFAULT_CHANNEL_ID | DISCORD__DEFAULT_CHANNEL_ID |
DISCORD__DEFAULT_USERNAME |
DISCORD__DEFAULT_WEBHOOK |
I3__BORDER_PIXEL_SIZE | custom i3 configuration settings I3__BORDER_PIXEL_SIZE | custom i3 configuration settings
I3__DMENU_FONT_SIZE | I3__DMENU_FONT_SIZE |

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`.

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,195 @@
[[ $SCWRYPTS_KUBECTL_DRIVER_READY -eq 1 ]] && return 0
unalias k h >/dev/null 2>&1
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="
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 "\\033[0;32m[0-9]\\033[0m^if the first argument is a number 0-9, uses or creates a subsession (default 0)"
echo " ^ "
for C in ${CUSTOM_COMMANDS[@]}
do
echo "\\033[0;32m$C\\033[0m^$(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) 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.
All actions are scoped to the current SCWRYPTS_ENV
currently : \\033[0;33m$SCWRYPTS_ENV\\033[0m
"
##########################################
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 )
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
;;
-- ) 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
CHECK_ERRORS --no-fail || return 1
[[ $HELP -eq 1 ]] && { 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)
[[ $STRICT -eq 1 ]] && {
[ $CONTEXT ] || ERROR "missing kubectl 'context'"
[ $NAMESPACE ] || ERROR "missing kubectl 'namespace'"
CHECK_ERRORS --no-fail --no-usage || {
ERROR "with 'strict' settings enabled, context and namespace must be set!"
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 ]] && {
INFO "
context '$CONTEXT'
namespace '$NAMESPACE'
environment '$SCWRYPTS_ENV'
subsession '$SUBSESSION'
"
STATUS "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}"
} || {
[[ $(_SCWRYPTS_KUBECTL_SETTINGS get context) =~ ^show$ ]] && {
INFO "$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)
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,140 @@
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) ;;
-h | --help ) HELP=1 ;;
* ) 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 ;;
* ) 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 ;;
* ) ERROR "target session must be a number [0-9]" ;;
esac
shift 1
;;
clear | show | hide | strict | loose ) USER_ARGS+=($1) ;;
* ) ERROR "no meta command '$1'"
esac
shift 1
done
}
SCWRYPTS_KUBECTL_CUSTOM_COMMAND__meta() {
case $1 in
get )
[[ $2 =~ ^all$ ]] && {
local CONTEXT=$(REDIS get --prefix current:context | grep . || echo "\\033[1;31mnone set\\033[0m")
local NAMESPACE=$(REDIS get --prefix current:namespace | grep . || echo "\\033[1;31mnone set\\033[0m")
echo "
environment : $SCWRYPTS_ENV
context : $CONTEXT
namespace : $NAMESPACE
CLI settings
command context : $(_SCWRYPTS_KUBECTL_SETTINGS get context)
strict mode : $([[ $STRICT -eq 1 ]] && echo "on" || echo "\\033[1;31moff\\033[0m")
" | sed 's/^ \+//' >&2
return 0
}
REDIS get --prefix current:$2
;;
set )
scwrypts -n --name set-$2 --type zsh --group kubectl -- --subsession $SUBSESSION >/dev/null \
&& SUCCESS "$2 set"
;;
copy )
: \
&& STATUS "copying $1 to $2" \
&& scwrypts -n --name set-context --type zsh --group kubectl -- --subsession $2 $(k meta get context | grep . || echo 'reset') \
&& scwrypts -n --name set-namespace --type zsh --group kubectl -- --subsession $2 $(k meta get namespace | grep . || echo 'reset') \
&& SUCCESS "subsession $1 copied to $2" \
;
;;
clear )
scwrypts -n --name set-context --type zsh --group kubectl -- --subsession $SUBSESSION reset >/dev/null \
&& SUCCESS "subsession $SUBSESSION reset to default"
;;
show )
_SCWRYPTS_KUBECTL_SETTINGS set context show >/dev/null \
&& SUCCESS "now showing full command context"
;;
hide )
_SCWRYPTS_KUBECTL_SETTINGS set context hide >/dev/null \
&& SUCCESS "now hiding command context"
;;
loose )
_SCWRYPTS_KUBECTL_SETTINGS set strict 0 >/dev/null \
&& WARNING "now running in 'loose' mode"
;;
strict )
_SCWRYPTS_KUBECTL_SETTINGS set strict 1 >/dev/null \
&& 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"
}

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,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/driver/kubectl.driver.zsh"

View File

@ -0,0 +1,89 @@
#####################################################################
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 =~ reset ]] && {
: \
&& REDIS del --prefix "current:context" \
&& KUBECTL__SET_NAMESPACE reset \
;
return $?
}
: \
&& REDIS set --prefix "current:context" "$CONTEXT" \
&& KUBECTL__SET_NAMESPACE reset \
;
}
KUBECTL__SELECT_CONTEXT() {
KUBECTL__LIST_CONTEXTS | FZF 'select a context'
}
KUBECTL__LIST_CONTEXTS() {
echo reset
local ALL_CONTEXTS=$(KUBECTL config get-contexts -o name | sort)
echo $ALL_CONTEXTS | grep -v '^arn:aws:eks'
[[ $AWS_ACCOUNT ]] && {
echo $ALL_CONTEXTS | grep "^arn:aws:eks:.*:$AWS_ACCOUNT"
true
} || {
echo $ALL_CONTEXTS | grep '^arn:aws:eks'
}
}
#####################################################################
KUBECTL__GET_NAMESPACE() { REDIS get --prefix "current:namespace"; }
KUBECTL__SET_NAMESPACE() {
local NAMESPACE=$1
[ ! $NAMESPACE ] && return 1
[[ $NAMESPACE =~ reset ]] && {
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 reset
echo default
KUBECTL get namespaces -o name | sed 's/^namespace\///' | sort
}

View File

@ -0,0 +1,97 @@
#####################################################################
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:
--subsession [0-9] use a particular subsession
-p, --prefix apply dynamic prefix to the next command line argument
--get-prefix output key prefix for current session+subsession
--get-static-definition output the static ZSH function definition for REDIS
additional arguments and options are passed through to 'redis-cli'
"
local REDIS_ARGS=() USER_ARGS=()
[ $SUBSESSION ] || local SUBSESSION=0
local REDIS_PREFIX=$(eval echo '$SCWRYPTS_KUBECTL_REDIS_KEY_PREFIX__'$SCWRYPTS_KUBECTL_REDIS)
[ $REDIS_PREFIX ] && REDIS_PREFIX+=':'
while [[ $# -gt 0 ]]
do
case $1 in
-p | --prefix ) USER_ARGS+=("${REDIS_PREFIX}${SCWRYPTS_ENV}:${SUBSESSION}:$2"); shift 1 ;;
--subsession ) SUBSESSION=$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=(); \
[ ! \$SUBSESSION ] && local SUBSESSION=0 ;\
while [[ \$# -gt 0 ]]; \
do \
case \$1 in
-p | --prefix ) USER_ARGS+=(\"${REDIS_PREFIX}\${SCWRYPTS_ENV}:\${SUBSESSION}:\$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)

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

@ -0,0 +1,46 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
local USAGE="
usage: [context] [...options...]
args:
context (optional) the full name of the kubeconfig context to set
options:
--subsession REDIS subsession (default 0)
"
local CONTEXT
local SUBSESSION=0
while [[ $# -gt 0 ]]
do
case $1 in
--subsession ) SUBSESSION=$2; shift 1 ;;
* )
[ $CONTEXT ] && ERROR "unexpected argument '$2'"
CONTEXT=$1
;;
esac
shift 1
done
[ $CONTEXT ] || CONTEXT=$(KUBECTL__SELECT_CONTEXT)
[ $CONTEXT ] || ERROR 'must provide or select a valid kube context'
CHECK_ERRORS
KUBECTL__SET_CONTEXT $CONTEXT
}
#####################################################################
MAIN $@

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

@ -0,0 +1,46 @@
#!/bin/zsh
#####################################################################
DEPENDENCIES+=()
REQUIRED_ENV+=()
use kubectl --group kubectl
CHECK_ENVIRONMENT
#####################################################################
MAIN() {
local USAGE="
usage: [namespace] [...options...]
args:
namespace (optional) the full name of the namespace context to set
options:
--subsession REDIS subsession (default 0)
"
local NAMESPACE
local SUBSESSION=0
while [[ $# -gt 0 ]]
do
case $1 in
--subsession ) SUBSESSION=$2; shift 1 ;;
* )
[ $NAMESPACE ] && ERROR "unexpected argument '$2'"
NAMESPACE=$1
;;
esac
shift 1
done
[ $NAMESPACE ] || NAMESPACE=$(KUBECTL__SELECT_NAMESPACE)
[ $NAMESPACE ] || ERROR 'must provide or select a valid namespace'
CHECK_ERRORS
KUBECTL__SET_NAMESPACE $NAMESPACE
}
#####################################################################
MAIN $@

View File

@ -13,19 +13,14 @@ if __name__ != '__main__':
##################################################################### #####################################################################
def main(args, stream): def main(args, stream):
if args.body is None: if args.content is None:
print(f'reading input from {stream.input.name}', file=stderr) print(f'reading input from {stream.input.name}', file=stderr)
args.body = ''.join(stream.readlines()).strip() args.content = ''.join(stream.readlines()).strip()
if len(args.body) == 0: if len(args.content) == 0:
args.body = 'PING' args.content = 'PING'
response = discord.send_message( response = discord.send_message(**vars(args))
content = args.body,
channel_id = args.channel_id,
webhook = args.webhook,
avatar_url = args.avatar_url,
)
stream.writeline(dumps({ stream.writeline(dumps({
**(response.json() if response.text != '' else {'message': 'OK'}), **(response.json() if response.text != '' else {'message': 'OK'}),
@ -38,23 +33,28 @@ execute(main,
description = 'post a message to the indicated discord channel', description = 'post a message to the indicated discord channel',
parse_args = [ parse_args = [
( ['-b', '--body'], { ( ['-b', '--body'], {
'dest' : 'body', 'dest' : 'content',
'help' : 'message body', 'help' : 'message body',
'required' : False, 'required' : False,
}), }),
( ['-c', '--channel-id'], { ( ['-c', '--channel-id'], {
'dest' : 'channel_id', 'dest' : 'channel_id',
'help' : 'target channel id', 'help' : 'override default target channel id',
'required' : False, 'required' : False,
}), }),
( ['-w', '--webhook'], { ( ['-w', '--webhook'], {
'dest' : 'webhook', 'dest' : 'webhook',
'help' : 'target webhook (takes precedence over -c)', 'help' : 'override default target webhook (takes precedence over -c)',
'required' : False, 'required' : False,
}), }),
( ['--avatar-url'], { ( ['--avatar-url'], {
'dest' : 'avatar_url', 'dest' : 'avatar_url',
'help' : 'replace default avatar_url', 'help' : 'override default avatar_url',
'required' : False,
}),
( ['--username'], {
'dest' : 'username',
'help' : 'override default username',
'required' : False, 'required' : False,
}), }),
] ]

View File

@ -1,9 +1,9 @@
from py.lib.scwrypts import getenv from py.lib.scwrypts import getenv
from py.lib.http.discord import request from py.lib.http.discord import request
def send_message(content, channel_id=None, webhook=None, avatar_url=None, **kwargs): def send_message(content, channel_id=None, webhook=None, username=None, avatar_url=None, **kwargs):
if channel_id is None: if username is None:
channel_id = getenv('DISCORD__DEFAULT_CHANNEL_ID', required=False) username = getenv('DISCORD__DEFAULT_USERNAME', required=False)
if avatar_url is None: if avatar_url is None:
avatar_url = getenv('DISCORD__DEFAULT_AVATAR_URL', required=False) avatar_url = getenv('DISCORD__DEFAULT_AVATAR_URL', required=False)
@ -12,11 +12,25 @@ def send_message(content, channel_id=None, webhook=None, avatar_url=None, **kwar
if webhook is not None: if webhook is not None:
endpoint = f'webhooks/{webhook}' endpoint = f'webhooks/{webhook}'
elif channel_id is not None: elif channel_id is not None:
endpoint = f'channels/{channel_id}/messages' endpoint = f'channels/{channel_id}/messages'
elif (webhook := getenv('DISCORD__DEFAULT_WEBHOOK', required=False)) is not None:
endpoint = f'webhooks/{webhook}'
elif (channel_id := getenv('DISCORD__DEFAULT_CHANNEL_ID', required=False)) is not None:
endpoint = f'channels/{channel_id}/messages'
else: else:
raise ValueError('must provide target channel_id or webhook') raise ValueError('must provide target channel_id or webhook')
if (header := getenv('DISCORD__CONTENT_HEADER', required=False)) is not None:
content = f'{header}{content}'
if (footer := getenv('DISCORD__CONTENT_FOOTER', required=False)) is not None:
content = f'{content}{footer}'
return request( return request(
method = 'POST', method = 'POST',
@ -25,7 +39,7 @@ def send_message(content, channel_id=None, webhook=None, avatar_url=None, **kwar
key: value key: value
for key, value in { for key, value in {
'content': content, 'content': content,
'username': 'wrobot', 'username': username,
'avatar_url': avatar_url, 'avatar_url': avatar_url,
**kwargs, **kwargs,
}.items() }.items()

35
run
View File

@ -85,6 +85,7 @@ __RUN() {
--update ) --update )
cd "$SCWRYPTS__ROOT__scwrypts" cd "$SCWRYPTS__ROOT__scwrypts"
git fetch --quiet origin main git fetch --quiet origin main
git fetch --quiet origin main --tags
local SYNC_STATUS=$? local SYNC_STATUS=$?
git diff --exit-code origin/main -- . >&2 git diff --exit-code origin/main -- . >&2
@ -208,19 +209,33 @@ __RUN() {
########################################## ##########################################
local ENV_REQUIRED=$(__CHECK_ENV_REQUIRED && echo 1 || echo 0) 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_REQUIRED -eq 1 ]] && {
[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV) [ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV)
local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME") for GROUP in ${SCWRYPTS_GROUPS[@]}
source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$ENV_NAME'" 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 export ENV_NAME
} }
for f in $(eval 'echo $SCWRYPTS_STATIC_CONFIG__'$SCWRYPT_GROUP) [ $REQUIRED_ENVIRONMENT_REGEX ] && {
do [[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \
source "$f" || FAIL 5 "invalid static config '$f'" || FAIL 5 "group '$SCWRYPT_GROUP' requires current environment to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)"
done }
########################################## ##########################################
@ -235,7 +250,7 @@ __RUN() {
########################################## ##########################################
local LOGFILE=$(__GET_LOGFILE $SCRIPT) local LOGFILE=$(__GET_LOGFILE)
local HEADER=$( local HEADER=$(
[ $SUBSCWRYPT ] && return 0 [ $SUBSCWRYPT ] && return 0
@ -308,11 +323,9 @@ __VALIDATE_UPSTREAM_TIMELINE() {
} }
__GET_LOGFILE() { __GET_LOGFILE() {
local SCRIPT="$1"
[ $SUBSCWRYPT ] \ [ $SUBSCWRYPT ] \
|| [[ $SCRIPT =~ scwrypts/logs ]] \ || [[ $SCWRYPT_NAME =~ scwrypts/logs ]] \
|| [[ $SCRIPT =~ interactive ]] \ || [[ $SCWRYPT_NAME =~ interactive ]] \
&& return 0 && return 0
echo "$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log" echo "$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log"

View File

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

View File

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

View File

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

View File

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

View File

@ -4,16 +4,15 @@ DEPENDENCIES+=(
docker docker
) )
REQUIRED_ENV+=( REQUIRED_ENV+=()
AWS_ACCOUNT
AWS_REGION
)
use cloud/aws/cli use cloud/aws/cli
##################################################################### #####################################################################
ECR_LOGIN() { ECR_LOGIN() {
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT) CHECK_ENVIRONMENT || return 1
STATUS "performing AWS ECR docker login" STATUS "performing AWS ECR docker login"
AWS ecr get-login-password \ AWS ecr get-login-password \
| docker login \ | docker login \

View File

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

View File

@ -2,11 +2,6 @@ export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT"
export SCWRYPTS_LIBRARY_ROOT__scwrypts="$SCWRYPTS_ROOT/zsh/lib" export SCWRYPTS_LIBRARY_ROOT__scwrypts="$SCWRYPTS_ROOT/zsh/lib"
export SCWRYPTS_COLOR__scwrypts='\033[0;32m' export SCWRYPTS_COLOR__scwrypts='\033[0;32m'
export SCWRYPTS_ENV_PATH__scwrypts="$SCWRYPTS_CONFIG_PATH/scwrypts/env"
[ ! -d "$SCWRYPTS_ENV_PATH__scwrypts" ] && mkdir -p "$SCWRYPTS_ENV_PATH__scwrypts"
export SCWRYPTS_ENV_TEMPLATE__scwrypts="$SCWRYPTS_ROOT__scwrypts/.env.template"
export SCWRYPTS_ENV_TEMPLATE_DESCRIPTIONS__scwrypts="$SCWRYPTS_ROOT__scwrypts/.env.template.descriptions"
export SCWRYPTS_VIRTUALENV_PATH__scwrypts="$SCWRYPTS_DATA_PATH/virtualenv" export SCWRYPTS_VIRTUALENV_PATH__scwrypts="$SCWRYPTS_DATA_PATH/virtualenv"
[ ! -d "$SCWRYPTS_VIRTUALENV_PATH__scwrypts" ] && mkdir -p "$SCWRYPTS_VIRTUALENV_PATH__scwrypts" [ ! -d "$SCWRYPTS_VIRTUALENV_PATH__scwrypts" ] && mkdir -p "$SCWRYPTS_VIRTUALENV_PATH__scwrypts"

Binary file not shown.

View File

@ -39,4 +39,11 @@ source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \
|| FAIL 69 'failed to set up scwrypts group; aborting' || FAIL 69 'failed to set up scwrypts group; aborting'
##################################################################### #####################################################################
__SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt
[[ $SCWRYPTS_PLUGIN_ENABLED__kubectl -eq 1 ]] && {
source "$SCWRYPTS_ROOT/plugins/kubectl/kubectl.scwrypts.zsh"
}
#####################################################################
[ $NO_EXPORT_CONFIG ] || __SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt
true

View File

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

@ -118,7 +118,16 @@ use() {
} }
GET_SCWRYPTS_LIBRARY_ROOT() { GET_SCWRYPTS_LIBRARY_ROOT() {
eval echo '$SCWRYPTS_LIBRARY_ROOT__'$SCWRYPTS_LIBRARY_GROUP local ROOT
ROOT=$(eval echo '$SCWRYPTS_LIBRARY_ROOT__'$SCWRYPTS_LIBRARY_GROUP)
[ $ROOT ] && echo $ROOT && return 0
[[ $(eval echo '$SCWRYPTS_TYPE__'$SCWRYPTS_LIBRARY_GROUP) =~ zsh ]] \
&& ROOT=$(eval echo '$SCWRYPTS_ROOT__'$SCWRYPTS_LIBRARY_GROUP/lib) \
|| ROOT=$(eval echo '$SCWRYPTS_ROOT__'$SCWRYPTS_LIBRARY_GROUP/zsh/lib) \
;
[ $ROOT ] && echo $ROOT && return 0
} }
IS_LOADED() { IS_LOADED() {

View File

@ -15,20 +15,47 @@ SCWRYPTS__SELECT_OR_CREATE_ENV() {
SCWRYPTS__GET_ENV_NAMES | FZF_TAIL 'select / create an environment' SCWRYPTS__GET_ENV_NAMES | FZF_TAIL 'select / create an environment'
} }
SCWRYPTS__GET_ENV_FILE() { SCWRYPTS__GET_ENV_FILES() {
local NAME="$1" local NAME="$1"
echo "$SCWRYPTS_ENV_PATH/$NAME" local FILENAMES=$(
for GROUP in ${SCWRYPTS_GROUPS[@]}
do
echo "$SCWRYPTS_ENV_PATH/$GROUP/$NAME"
done
)
echo $FILENAMES | grep 'environments/scwrypts/'
echo $FILENAMES | grep -v 'environments/scwrypts/' | sort
SCWRYPTS__GET_ENV_NAMES | grep -q $NAME \ SCWRYPTS__GET_ENV_NAMES | grep -q $NAME \
|| { ERROR "no environment '$NAME' exists"; return 1; } || { ERROR "no environment '$NAME' exists"; return 1; }
} }
SCWRYPTS__GET_ENV_FILE() {
local NAME="$1"
local GROUP="$2"
[ ! $GROUP ] && { ERROR 'must provide group'; return 1; }
echo "$SCWRYPTS_ENV_PATH/$GROUP/$NAME"
SCWRYPTS__GET_ENV_NAMES | grep -q $NAME \
|| { ERROR "no environment '$NAME' exists"; return 1; }
[ -f "$SCWRYPTS_ENV_PATH/$GROUP/$NAME" ] || {
mkdir -p "$SCWRYPTS_ENV_PATH/$GROUP"
touch "$SCWRYPTS_ENV_PATH/$GROUP/$NAME"
}
[ -f "$SCWRYPTS_ENV_PATH/$GROUP/$NAME" ] \
|| { ERROR "missing environment file for '$GROUP/$NAME'"; return 2; }
}
SCWRYPTS__GET_ENV_TEMPLATE_FILES() { SCWRYPTS__GET_ENV_TEMPLATE_FILES() {
local GROUP local GROUP
for GROUP in ${SCWRYPTS_GROUPS[@]} for GROUP in ${SCWRYPTS_GROUPS[@]}
do do
eval echo '$SCWRYPTS_ENV_TEMPLATE__'$GROUP eval echo '$SCWRYPTS_ROOT__'$GROUP/.config/env.template
done done
} }
@ -37,7 +64,11 @@ SCWRYPTS__GET_ENV_NAMES() {
ERROR 'environment initialization error' ERROR 'environment initialization error'
return 1 return 1
} }
ls "$SCWRYPTS_ENV_PATH" | 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() { SCWRYPTS__INIT_ENVIRONMENTS() {
@ -49,7 +80,11 @@ SCWRYPTS__INIT_ENVIRONMENTS() {
local BASIC_ENV local BASIC_ENV
for BASIC_ENV in local dev prod for BASIC_ENV in local dev prod
do do
GENERATE_TEMPLATE > "$SCWRYPTS_ENV_PATH/$BASIC_ENV" for GROUP in ${SCWRYPTS_GROUPS[@]}
do
mkdir -p "$SCWRYPTS_ENV_PATH/$GROUP"
GENERATE_TEMPLATE > "$SCWRYPTS_ENV_PATH/$GROUP/$BASIC_ENV"
done
done done
} }
@ -58,30 +93,28 @@ SCWRYPTS__INIT_ENVIRONMENTS() {
_SED() { sed --follow-symlinks $@; } _SED() { sed --follow-symlinks $@; }
GENERATE_TEMPLATE() { GENERATE_TEMPLATE() {
echo "#!/bin/zsh" [ ! $GROUP ] && { ERROR 'must provide GROUP'; return 1; }
echo '#####################################################################' DIVIDER='#####################################################################'
echo "### scwrypts runtime configuration ##################################" HEADER='### scwrypts runtime configuration '
echo '#####################################################################' [[ GROUP =~ ^scwrypts$ ]] || HEADER="${HEADER}(group '$GROUP') "
local FILE GROUP CONTENT printf "#!/bin/zsh\n$DIVIDER\n$HEADER%s\n$DIVIDER\n" "${DIVIDER:${#$(echo "$HEADER")}}"
local VARIABLE DESCRIPTION
for GROUP in ${SCWRYPTS_GROUPS[@]}
do
FILE=$(eval echo '$SCWRYPTS_ENV_TEMPLATE__'$GROUP)
CONTENT=$(GET_VARIABLE_NAMES "$FILE" | sed 's/^/export /; s/$/=/') local FILE CONTENT
local VARIABLE DESCRIPTION
FILE=$(eval echo '$SCWRYPTS_ROOT__'$GROUP/.config/env.template)
while read DESCRIPTION_LINE CONTENT=$(GET_VARIABLE_NAMES "$FILE" | sed 's/^/export /; s/$/=/')
do
VARIABLE=$(echo $DESCRIPTION_LINE | sed 's/ \+| .*$//')
DESCRIPTION=$(echo $DESCRIPTION_LINE | sed 's/^.* | //')
[ ! $DESCRIPTION ] && continue
CONTENT=$(echo "$CONTENT" | sed "/^export $VARIABLE=/i #" | sed "/^export $VARIABLE=/i # $DESCRIPTION") while read DESCRIPTION_LINE
done < <(_SED -n '/^[^ ]\+ \+| /p' "$FILE.descriptions") do
VARIABLE=$(echo $DESCRIPTION_LINE | sed 's/ \+| .*$//')
DESCRIPTION=$(echo $DESCRIPTION_LINE | sed 's/^.* | //')
[ ! $DESCRIPTION ] && continue
echo "$CONTENT" | sed 's/^#$//' CONTENT=$(echo "$CONTENT" | sed "/^export $VARIABLE=/i #" | sed "/^export $VARIABLE=/i # $DESCRIPTION")
echo '\n#####################################################################' done < <(_SED -n '/^[^ ]\+ \+| /p' "$FILE.descriptions")
done
echo "$CONTENT" | sed 's/^#$//'
} }
GET_VARIABLE_NAMES() { GET_VARIABLE_NAMES() {
@ -91,4 +124,3 @@ GET_VARIABLE_NAMES() {
| grep -v '__[a-z]\+$' \ | grep -v '__[a-z]\+$' \
; ;
} }

View File

@ -16,14 +16,18 @@ SCWRYPTS__GET_AVAILABLE_SCWRYPTS() {
do do
GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP) GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP)
GROUP_COLOR=$(eval echo '$SCWRYPTS_COLOR__'$GROUP) GROUP_COLOR=$(eval echo '$SCWRYPTS_COLOR__'$GROUP)
{
cd "$GROUP_PATH" GROUP_TYPE=$(eval echo '$SCWRYPTS_TYPE__'$GROUP)
find . -mindepth 2 -type f -executable \ [ $GROUP_TYPE ] && MINDEPTH=1 && GROUP_TYPE="$GROUP_TYPE\\/" || MINDEPTH=2
| grep -v '\.git' \
| grep -v 'node_modules' \ command -v SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__$GROUP >/dev/null 2>&1 \
| sed "s/^\\.\\///; s/\\.[^.]*$//" \ && LOOKUP=SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__$GROUP \
| sed "s|\\([^/]*\\)/\(.*\)$|$(printf $__COLOR_RESET)\\2^$(printf $TYPE_COLOR)\\1^$(printf $GROUP_COLOR)$GROUP$(printf $__COLOR_RESET)|" \ || LOOKUP=SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__scwrypts \
; ;
{
$LOOKUP \
| sed "s|\\([^/]*\\)/\(.*\)$|$(printf $__COLOR_RESET)\\2^$(printf $TYPE_COLOR)\\1^$(printf $GROUP_COLOR)$GROUP$(printf $__COLOR_RESET)|" \
} & } &
LOOKUP_PIDS+=($!) LOOKUP_PIDS+=($!)
done done
@ -42,54 +46,63 @@ SCWRYPTS__SEPARATE_SCWRYPT_SELECTION() {
done done
} }
SCWRYPTS__LIST_AVAILABLE_SCWRYPTS__scwrypts() {
# implementation should output lines of the following format:
# "${SCWRYPT_TYPE}/${SCWRYPT_NAME}"
cd "$GROUP_PATH"
find . -mindepth $MINDEPTH -type f -executable \
| grep -v '\.git' \
| grep -v 'node_modules' \
| sed "s/^\\.\\///; s/\\.[^.]*$//; s/^/$GROUP_TYPE/" \
| grep -v '^plugins/' \
;
}
SCWRYPTS__GET_RUNSTRING() { SCWRYPTS__GET_RUNSTRING() {
# accepts a selected line from SCWRYPTS__GET_AVAILABLE_SCWRYPTS local GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$SCWRYPT_GROUP)
local NAME="$1"
local TYPE="$2"
local GROUP="$3"
local GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP)
local RUNSTRING local RUNSTRING
[ $NAME ] && [ $TYPE ] && [ $GROUP ] || { [ $SCWRYPT_NAME ] && [ $SCWRYPT_TYPE ] && [ $SCWRYPT_GROUP ] || {
ERROR 'missing required information to get runstring' ERROR 'missing required information to get runstring'
return 1 return 1
} }
[ $ENV_REQUIRED ] && [[ $ENV_REQUIRED -eq 1 ]] && [ ! $ENV_NAME ] && { [ $ENV_REQUIRED ] && [[ $ENV_REQUIRED -eq 1 ]] && [ ! $ENV_NAME ] && {
ERROR 'missing required information to get runstring' ERROR 'missing required information to get runstring'
return 1 return 1
} }
typeset -f SCWRYPTS__GET_RUNSTRING__${GROUP}__${TYPE} >/dev/null 2>&1 && { [ ! $RUNSTRING ] && typeset -f SCWRYPTS__GET_RUNSTRING__${SCWRYPT_GROUP}__${SCWRYPT_TYPE} >/dev/null 2>&1 && {
RUNSTRING=$(SCWRYPTS__GET_RUNSTRING__${GROUP}__${TYPE}) RUNSTRING=$(SCWRYPTS__GET_RUNSTRING__${SCWRYPT_GROUP}__${SCWRYPT_TYPE})
[ ! $RUNSTRING ] && { [ ! $RUNSTRING ] && {
ERROR "SCWRYPTS__GET_RUNSTRING__${GROUP}__${TYPE} error" ERROR "SCWRYPTS__GET_RUNSTRING__${SCWRYPT_GROUP}__${SCWRYPT_TYPE} error"
return 2 return 2
} }
} }
typeset -f SCWRYPTS__GET_RUNSTRING__${TYPE} >/dev/null 2>&1 && { [ ! $RUNSTRING ] && typeset -f SCWRYPTS__GET_RUNSTRING__${SCWRYPT_TYPE} >/dev/null 2>&1 && {
RUNSTRING=$(SCWRYPTS__GET_RUNSTRING__${TYPE}) RUNSTRING=$(SCWRYPTS__GET_RUNSTRING__${SCWRYPT_TYPE})
[ ! $RUNSTRING ] && { [ ! $RUNSTRING ] && {
ERROR "SCWRYPTS__GET_RUNSTRING__${TYPE} error" ERROR "SCWRYPTS__GET_RUNSTRING__${SCWRYPT_TYPE} error"
return 3 return 3
} }
} }
[ ! $RUNSTRING ] && { [ ! $RUNSTRING ] && {
ERROR "type ${TYPE} (group ${GROUP}) has no supported runstring generator" ERROR "type ${SCWRYPT_TYPE} (group ${SCWRYPT_GROUP}) has no supported runstring generator"
return 4 return 4
} }
RUNSTRING="SCWRYPTS_ENV=$ENV_NAME; $RUNSTRING" RUNSTRING="SCWRYPTS_ENV=$ENV_NAME; $RUNSTRING"
RUNSTRING="source $SCWRYPTS_ROOT/zsh/lib/import.driver.zsh; $RUNSTRING" RUNSTRING="source $SCWRYPTS_ROOT/zsh/lib/import.driver.zsh; $RUNSTRING"
local _VIRTUALENV=$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP'/$TYPE/bin/activate') local _VIRTUALENV=$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$SCWRYPT_GROUP'/$SCWRYPT_TYPE/bin/activate')
[ -f $_VIRTUALENV ] && RUNSTRING="source $_VIRTUALENV; $RUNSTRING" [ -f $_VIRTUALENV ] && RUNSTRING="source $_VIRTUALENV; $RUNSTRING"
local G SCWRYPTSENV local G SCWRYPTSENV
for G in ${SCWRYPTS__GROUPS[@]} for G in ${SCWRYPTS__GROUPS[@]}
do do
SCWRYPTSENV=$(eval echo '$SCWRYPTS_ENV_PATH__'$GROUP'/$ENV_NAME') SCWRYPTSENV="$SCWRYPTS_ENV_PATH/$G/$ENV_NAME"
[ -f $SCWRYPTSENV ] && RUNSTRING="source $SCWRYPTSENV; $RUNSTRING" [ -f $SCWRYPTSENV ] && RUNSTRING="source $SCWRYPTSENV; $RUNSTRING"
done done
@ -99,7 +112,12 @@ SCWRYPTS__GET_RUNSTRING() {
SCWRYPTS__GET_RUNSTRING__zsh() { SCWRYPTS__GET_RUNSTRING__zsh() {
__CHECK_DEPENDENCY zsh || return 1 __CHECK_DEPENDENCY zsh || return 1
echo "source $GROUP_PATH/$TYPE/$NAME" [ $(eval echo '$SCWRYPTS_TYPE__'$SCWRYPT_GROUP) ] \
&& echo "source $GROUP_PATH/$SCWRYPT_NAME" \
|| echo "source $GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \
;
return 0
} }
SCWRYPTS__GET_RUNSTRING__py() { SCWRYPTS__GET_RUNSTRING__py() {
@ -110,11 +128,11 @@ SCWRYPTS__GET_RUNSTRING__py() {
WARNING 'compatibility may vary' WARNING 'compatibility may vary'
} }
echo "cd $GROUP_PATH; python -m $(echo $TYPE/$NAME | sed 's/\//./g; s/\.py$//; s/\.\.//')" echo "cd $GROUP_PATH; python -m $(echo $SCWRYPT_TYPE/$SCWRYPT_NAME | sed 's/\//./g; s/\.py$//; s/\.\.//')"
} }
SCWRYPTS__GET_RUNSTRING__zx() { SCWRYPTS__GET_RUNSTRING__zx() {
__CHECK_DEPENDENCY zx || return 1 __CHECK_DEPENDENCY zx || return 1
echo "FORCE_COLOR=3; cd $GROUP_PATH; ./$TYPE/$NAME.js" echo "export FORCE_COLOR=3; cd $GROUP_PATH; ./$SCWRYPT_TYPE/$SCWRYPT_NAME.js"
} }

View File

@ -37,7 +37,11 @@ UPDATE_VIRTUALENV() {
local VIRTUALENV_PATH=$(GET_VIRTUALENV_PATH $GROUP $TYPE) local VIRTUALENV_PATH=$(GET_VIRTUALENV_PATH $GROUP $TYPE)
[ ! -d $VIRTUALENV_PATH ] && CREATE_VIRTUALENV__${GROUP}__${TYPE} $VIRTUALENV_PATH [ ! -d $VIRTUALENV_PATH ] && {
which CREATE_VIRTUALENV__${GROUP}__${TYPE} >/dev/null 2>&1 \
&& CREATE_VIRTUALENV__${GROUP}__${TYPE} $VIRTUALENV_PATH \
|| return 0
}
STATUS "updating $TYPE virtual environment" STATUS "updating $TYPE virtual environment"
@ -49,7 +53,7 @@ UPDATE_VIRTUALENV() {
cd $SCWRYPTS_ROOT cd $SCWRYPTS_ROOT
local UPDATE_CODE=0 local UPDATE_CODE=0
case $TYPE in case $TYPE in
py ) cd py; pip install -r requirements.txt; UPDATE_CODE=$? ;; py ) cd py; pip install --no-cache-dir -r requirements.txt; UPDATE_CODE=$? ;;
zx ) cd zx; npm install ;; zx ) cd zx; npm install ;;
esac esac
UPDATE_CODE=$? UPDATE_CODE=$?
@ -83,7 +87,11 @@ DELETE_VIRTUALENV() {
GET_VIRTUALENV_PATH() { GET_VIRTUALENV_PATH() {
local GROUP="$1" local GROUP="$1"
local TYPE="$2" local TYPE="$2"
eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP/$TYPE
local ENV_PATH="$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP 2>/dev/null)"
[ ! $ENV_PATH ] && ENV_PATH="$SCWRYPTS_VIRTUALENV_PATH__scwrypts"
echo $ENV_PATH/$TYPE
} }
##################################################################### #####################################################################
@ -121,7 +129,7 @@ CREATE_VIRTUALENV__scwrypts__zx() {
nodeenv $VIRTUALENV_PATH --node=$SCWRYPTS_NODE_VERSION__scwrypts \ nodeenv $VIRTUALENV_PATH --node=$SCWRYPTS_NODE_VERSION__scwrypts \
&& SUCCESS 'node virtualenv created' \ && SUCCESS 'node virtualenv created' \
|| { || {
ERROR "unable to create '$VIRTUALENV_PATH' with '$SCWRYPTS__NODE_VERSION'" ERROR "unable to create '$VIRTUALENV_PATH' with '$SCWRYPTS_NODE_VERSION__scwrypts'"
return 2 return 2
} }
} }

View File

@ -1,5 +1,6 @@
__CHECK_DEPENDENCIES() { __CHECK_DEPENDENCIES() {
local DEP ERROR=0 local DEP ERROR=0
[ ! $E ] && E=ERROR
DEPENDENCIES=($(echo $DEPENDENCIES | sed 's/ \+/\n/g' | sort -u)) DEPENDENCIES=($(echo $DEPENDENCIES | sed 's/ \+/\n/g' | sort -u))
@ -13,7 +14,7 @@ __CHECK_DEPENDENCY() {
local DEPENDENCY="$1" local DEPENDENCY="$1"
[ ! $DEPENDENCY ] && return 1 [ ! $DEPENDENCY ] && return 1
command -v $DEPENDENCY >/dev/null 2>&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 return 1
} }
} }

View File

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

View File

@ -16,7 +16,9 @@ PRINT() {
shift 1 shift 1
done done
local STYLED_MESSAGE="${COLOR}$({ MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')"
local STYLED_MESSAGE="$({
printf "${COLOR}" printf "${COLOR}"
while IFS='' read line while IFS='' read line
do do
@ -26,7 +28,9 @@ PRINT() {
PREFIX=$(echo $PREFIX | sed 's/./ /g') PREFIX=$(echo $PREFIX | sed 's/./ /g')
done <<< $MESSAGE done <<< $MESSAGE
})${__COLOR_RESET}${LAST_LINE_END}" })"
STYLED_MESSAGE="${COLOR}$(echo "$STYLED_MESSAGE" | sed 's/%/%%/g')${__COLOR_RESET}${LAST_LINE_END}"
[[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2 [[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2
[[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE [[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE
@ -51,37 +55,81 @@ ABORT() { FAIL 69 'user abort'; }
CHECK_ERRORS() { CHECK_ERRORS() {
local FAIL_OUT=1 local FAIL_OUT=1
local DISPLAY_USAGE=1
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
case $1 in case $1 in
-n | --no-fail ) FAIL_OUT=0 ;; --no-fail ) FAIL_OUT=0 ;;
--no-usage ) DISPLAY_USAGE=0 ;;
esac esac
shift 1 shift 1
done done
[ ! $ERRORS ] && ERRORS=0 [ ! $ERRORS ] && ERRORS=0
[[ $ERRORS -ne 0 ]] && USAGE [[ $ERRORS -eq 0 ]] && return 0
[[ $ERRORS -eq 0 ]] || {
[[ $FAIL_OUT -eq 1 ]] \ [[ $DISPLAY_USAGE -eq 1 ]] && USAGE
&& exit $ERRORS \
|| return $ERRORS [[ $FAIL_OUT -eq 1 ]] && exit $ERRORS
}
return $ERRORS
} }
USAGE() { USAGE() { # formatter for USAGE variable
[ ! $USAGE ] && return 0 [ ! $USAGE ] && return 0
USAGE=$(echo $USAGE | sed "s/^\t\+//; s/\s\+$//") local USAGE_LINE=$(echo $USAGE | grep -i '^[ ]*usage *:' | sed 's/^[ ]*//')
local USAGE_LINE=$(\ [ $USAGE__usage ] && echo $USAGE_LINE | grep -q 'usage: -' \
echo $USAGE \ && USAGE_LINE=$(echo $USAGE_LINE | sed "s/usage: -/usage: $USAGE__usage/")
| grep -i '^ *usage *:' \
| sed "s;^[^:]*:;& scwrypts $SCWRYPT_NAME --;" \
| sed 's/ \{2,\}/ /g; s/scwrypts -- scwrypts/scwrypts/' \
)
local THE_REST=$(echo $USAGE | grep -vi '^ *usage *:' | sed 'N;/^\n$/D;P;D;')
{ echo; printf "$__DARK_BLUE $USAGE_LINE$__COLOR_RESET\n"; echo $THE_REST; echo } >&2 [ $__SCWRYPT ] \
&& USAGE_LINE=$(
echo $USAGE_LINE \
| sed "s;^[^:]*:;& scwrypts $SCWRYPT_NAME --;" \
| sed 's/ \{2,\}/ /g; s/scwrypts -- scwrypts/scwrypts/' \
)
local THE_REST=$(echo $USAGE | grep -vi '^[ ]*usage *:' )
local DYNAMIC_USAGE_ELEMENT
#
# create dynamic usage elements (like 'args') by defining USAGE__<element>
# then using the syntax "<element>: -" in your USAGE variable
#
# e.g.
#
# USAGE__args="
# subcommand arg 1 arg 1 description
# subcommand arg 2 some other description
# "
#
# USAGE="
# usage: some-command [...args...]
#
# args: -
# -h, --help some arguments are applicable everywhere
# "
#
for DYNAMIC_USAGE_ELEMENT in $(echo $THE_REST | sed -n 's/^\([^:]*\): -$/\1/p')
do
DYNAMIC_USAGE_ELEMENT_TEXT=$(eval echo '$USAGE__'$DYNAMIC_USAGE_ELEMENT)
[[ ! $DYNAMIC_USAGE_ELEMENT =~ ^description$ ]] \
&& DYNAMIC_USAGE_ELEMENT_TEXT=$(echo $DYNAMIC_USAGE_ELEMENT_TEXT | sed 's/[^ ]/ &/')
THE_REST=$(echo $THE_REST | perl -pe "s/$DYNAMIC_USAGE_ELEMENT: -/$DYNAMIC_USAGE_ELEMENT:\n$DYNAMIC_USAGE_ELEMENT_TEXT\n\n/")
done
# allow for dynamic 'description: -' but delete the 'description:' header line
THE_REST=$(echo $THE_REST | sed '/^[ ]*description:$/d')
echo "$__DARK_BLUE$USAGE_LINE$__COLOR_RESET\n\n$THE_REST" \
| sed "s/^\t\+//; s/\s\+$//; s/^\\s*$//;" \
| sed '/./,$!d; :a; /^\n*$/{$d;N;ba;};' \
| perl -p0e 's/\n{2,}/\n\n/g' \
| perl -p0e 's/:\n{2,}/:\n/g' \
>&2
} }
INPUT() { INPUT() {
@ -95,7 +143,7 @@ Yn() {
PROMPT "$@ [Yn]" PROMPT "$@ [Yn]"
[ $CI ] && { echo y; return 0; } [ $CI ] && { echo y; return 0; }
local Yn; READ -k Yn; echo local Yn; READ -k Yn; echo >&2
[[ $Yn =~ [nN] ]] && return 1 || return 0 [[ $Yn =~ [nN] ]] && return 1 || return 0
} }
@ -103,7 +151,7 @@ yN() {
PROMPT "$@ [yN]" PROMPT "$@ [yN]"
[ $CI ] && { echo y; return 0; } [ $CI ] && { echo y; return 0; }
local yN; READ -k yN; echo local yN; READ -k yN; echo >&2
[[ $yN =~ [yY] ]] && return 0 || return 1 [[ $yN =~ [yY] ]] && return 0 || return 1
} }
@ -124,7 +172,15 @@ FZF() {
exit 1 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" PROMPT "$1"
echo $SELECTION >&2 echo $SELECTION >&2
echo $SELECTION echo $SELECTION

View File

@ -18,6 +18,12 @@ source ${0:a:h}/environment.zsh
##################################################################### #####################################################################
CHECK_ENVIRONMENT() { CHECK_ENVIRONMENT() {
local OPTIONAL=0
[[ $1 =~ --optional ]] && OPTIONAL=1
[[ $OPTIONAL -eq 1 ]] \
&& E=WARNING || E=ERROR
local ENVIRONMENT_STATUS=0 local ENVIRONMENT_STATUS=0
__CHECK_DEPENDENCIES $DEPENDENCIES __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_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 ]] && { [[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && {
@ -67,10 +73,11 @@ CHECK_ENVIRONMENT() {
" "
} }
[[ $ENVIRONMENT_STATUS -eq 0 ]] || { [[ $ENVIRONMENT_STATUS -ne 0 ]] && [[ $NO_EXIT -ne 1 ]] && [[ $OPTIONAL -eq 0 ]] && {
[[ $NO_EXIT -eq 1 ]] && return $ENVIRONMENT_STATUS
exit $ENVIRONMENT_STATUS exit $ENVIRONMENT_STATUS
} }
return $ENVIRONMENT_STATUS
} }
CHECK_ENVIRONMENT CHECK_ENVIRONMENT

View File

@ -1,4 +1,4 @@
#!/bin/zsh #!/bin/zsh
DEPENDENCIES+=() DEPENDENCIES+=()
REQUIRED_ENV+=() REQUIRED_ENV+=()
@ -16,18 +16,23 @@ STATUS "selected '$TEMPLATE_ENV_NAME'"
PROMPT 'enter new environment name' PROMPT 'enter new environment name'
ENV_NAME=$(echo '' | FZF_HEAD 'new environment') ENV_NAME=$(echo '' | FZF_HEAD 'new environment')
[ ! $ENV_NAME ] && ABORT [ ! $ENV_NAME ] && ABORT
SCWRYPTS__GET_ENV_NAMES | grep -q $ENV_NAME && FAIL 1 "'$ENV_NAME' already exists"
TEMPLATE_ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $TEMPLATE_ENV_NAME 2>/dev/null) for GROUP in ${SCWRYPTS_GROUPS[@]}
ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $ENV_NAME) do
TEMPLATE_ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $TEMPLATE_ENV_NAME $GROUP 2>/dev/null)
ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $ENV_NAME $GROUP 2>/dev/null)
[ -f "$ENV_FILE" ] && FAIL 2 "'$ENV_NAME' already exists" STATUS "creating environment '$ENV_NAME'"
cat "$TEMPLATE_ENV_FILE" \
| sed 's/ # from.*//' \
> "$ENV_FILE" \
&& SUCCESS "created '$ENV_FILE'" \
|| FAIL 2 "something went wrong creating '$ENV_FILE'"
done
STATUS "creating environment '$ENV_NAME'" STATUS "synchronizing environments"
cat "$TEMPLATE_ENV_FILE" \ SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \
| sed 's/ from.*//' \ && SUCCESS "finished copy environment '$TEMPLATE_ENV_NAME > $ENV_NAME'" \
> "$ENV_FILE" \ || FAIL 3 'error during synchronization of new environment (see above)' \
&& SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \ ;
&& SUCCESS "created '$ENV_NAME'" \
|| FAIL 3 "something went wrong creating '$ENV_NAME'"
SUCCESS "finished copy environment '$TEMPLATE_ENV_NAME > $ENV_NAME'"

View File

@ -11,18 +11,26 @@ PROMPT 'choose an environment to delete'
ENV_NAME=$(SCWRYPTS__SELECT_ENV) ENV_NAME=$(SCWRYPTS__SELECT_ENV)
[ ! $ENV_NAME ] && ABORT [ ! $ENV_NAME ] && ABORT
ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $ENV_NAME) ENV_FILES=($(SCWRYPTS__GET_ENV_FILES $ENV_NAME))
STATUS "preparing to remove '$ENV_NAME'" STATUS "preparing to remove '$ENV_NAME'"
WARNING " WARNING "
the '$ENV_NAME' environment will be removed the '$ENV_NAME' environment will be removed configured options
configured options and stored credentials will be lost forever and stored credentials will be lost forever:
$(echo $ENV_FILES | sed 's| /|\n - /|g; s/^/ - /')
" "
yN 'continue?' || ABORT yN 'continue?' || ABORT
STATUS "removing environment" STATUS "removing environment"
rm "$ENV_FILE" \ for ENV_FILE in ${ENV_FILES[@]}
&& SUCCESS "removed '$ENV_NAME'" \ do
|| FAIL 3 "unable to remove '$ENV_FILE'; is it protected?" rm "$ENV_FILE" \
&& SUCCESS "removed '$ENV_FILE'" \
|| ERROR "unable to remove '$ENV_FILE'; is it protected?" \
;
done
CHECK_ERRORS -n || FAIL 2 "some errors ocurred when cleaning up $ENV_NAME"

View File

@ -16,16 +16,27 @@ CHECK_ENVIRONMENT
} }
[ ! $ENV_NAME ] && ABORT [ ! $ENV_NAME ] && ABORT
ENV_FILE=$(SCWRYPTS__GET_ENV_FILE $ENV_NAME 2>/dev/null) ENV_FILES=($(SCWRYPTS__GET_ENV_FILES $ENV_NAME 2>/dev/null))
[ ! -f "$ENV_FILE" ] && { for ENV_FILE in ${ENV_FILES[@]}
STATUS "Creating '$ENV_NAME'..." \ do
&& touch "$ENV_FILE" \ [ ! -f "$ENV_FILE" ] && {
&& SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \ STATUS "Creating '$ENV_FILE'..." \
&& SUCCESS "created '$ENV_NAME'" \ && mkdir -p "$(dirname "$ENV_FILE")" \
|| { ERROR "failed to create '$ENV_FILE'"; exit 1; } && touch "$ENV_FILE" \
} && ((CREATED+=1)) \
&& SUCCESS "created '$ENV_NAME'" \
|| { ERROR "failed to create '$ENV_FILE'"; exit 1; }
}
EDIT $ENV_FILE [ $CREATED ] && [[ $CREATED -gt 0 ]] && {
STATUS "detected new environment files; performing sync" \
&& SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \
|| FAIL 1 "failure during sync for '$ENV_NAME'" \
}
;
done
EDIT $ENV_FILES
SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \ SCWRYPTS__RUN --name scwrypts/environment/synchronize --group scwrypts --type zsh -- --no-prompt \
|| FAIL 4 'failed to run environment sync' \ || FAIL 4 'failed to run environment sync' \

View File

@ -1,8 +0,0 @@
#!/bin/zsh
DEPENDENCIES+=()
REQUIRED_ENV+=()
CHECK_ENVIRONMENT
#####################################################################
__CHECK_REQUIRED_ENV $@

View File

@ -49,39 +49,47 @@ SYNCHRONIZE() {
local ENVIRONMENTS ENVIRONMENT_FILES local ENVIRONMENTS ENVIRONMENT_FILES
local FILE NAME ENVIRONMENT_FILE local FILE NAME ENVIRONMENT_FILE
ENVIRONMENTS=($(SCWRYPTS__GET_ENV_NAMES | sort -r)) GROUP_PIDS=()
ENVIRONMENT_FILES=($( for GROUP in ${SCWRYPTS_GROUPS}
do
{
ENVIRONMENTS=($(SCWRYPTS__GET_ENV_NAMES | sort -r))
ENVIRONMENT_FILES=($(
for NAME in ${ENVIRONMENTS[@]}
do
SCWRYPTS__GET_ENV_FILE $NAME $GROUP
done
))
STATUS 'generating working environment files...'
for FILE in ${ENVIRONMENT_FILES[@]}
do
GENERATE_TEMP_ENVIRONMENT_FILE "$FILE"
done
STATUS 'cascading environment values to children...'
for NAME in ${ENVIRONMENTS[@]} for NAME in ${ENVIRONMENTS[@]}
do do
SCWRYPTS__GET_ENV_FILE $NAME CASCADE_ENVIRONMENT $NAME
done done
))
STATUS 'generating working environment files...' STATUS 'cleaning up working space...'
for FILE in ${ENVIRONMENT_FILES[@]} for FILE in ${ENVIRONMENT_FILES[@]}
do do
GENERATE_TEMP_ENVIRONMENT_FILE "$FILE" CLEANUP_ENVIRONMENT_FILE "$FILE"
done
SUCCESS 'finished sync!'
} &
GROUP_PIDS+=$!
done done
for P in ${GROUP_PIDS[@]}; do wait $P; done
STATUS 'cascading environment values to children...'
for NAME in ${ENVIRONMENTS[@]}
do
CASCADE_ENVIRONMENT $NAME
done
STATUS 'cleaning up working space...'
for FILE in ${ENVIRONMENT_FILES[@]}
do
CLEANUP_ENVIRONMENT_FILE "$FILE"
done
SUCCESS 'finished sync!'
} }
##################################################################### #####################################################################
CASCADE_ENVIRONMENT() { CASCADE_ENVIRONMENT() {
local PARENT_NAME="$1" local PARENT_NAME="$1"
local PARENT_FILE="$(SCWRYPTS__GET_ENV_FILE $PARENT_NAME).temp" local PARENT_FILE="$(SCWRYPTS__GET_ENV_FILE $PARENT_NAME $GROUP).temp"
local CHILD_NAMES=($(echo $ENVIRONMENTS | sed 's/ \+/\n/g' |grep "^$PARENT_NAME\\.")) local CHILD_NAMES=($(echo $ENVIRONMENTS | sed 's/ \+/\n/g' |grep "^$PARENT_NAME\\."))
[[ ${#CHILD_NAMES[@]} -eq 0 ]] && return 0 [[ ${#CHILD_NAMES[@]} -eq 0 ]] && return 0
@ -93,7 +101,7 @@ CASCADE_ENVIRONMENT() {
for CHILD_NAME in ${CHILD_NAMES[@]} for CHILD_NAME in ${CHILD_NAMES[@]}
do do
STATUS "propagating environment '$PARENT_NAME' to child '$CHILD_NAME'" STATUS "propagating environment '$PARENT_NAME' to child '$CHILD_NAME'"
CHILD_FILE="$(SCWRYPTS__GET_ENV_FILE $CHILD_NAME).temp" CHILD_FILE="$(SCWRYPTS__GET_ENV_FILE $CHILD_NAME $GROUP).temp"
CONTENT=$(cat "$CHILD_FILE") CONTENT=$(cat "$CHILD_FILE")
echo "$PARENT_VARIABLES" | ADD_LINES echo "$PARENT_VARIABLES" | ADD_LINES
echo "$CONTENT" > "$CHILD_FILE" echo "$CONTENT" > "$CHILD_FILE"

View File

@ -18,10 +18,18 @@ SETUP_SYMLINK() {
[ ! $2 ] && FAIL 1 'must provide SOURCE_CONFIG and TARGET_CONFIG' [ ! $2 ] && FAIL 1 'must provide SOURCE_CONFIG and TARGET_CONFIG'
local SOURCE_CONFIG="$1" local SOURCE_CONFIG="$1"
[ ! -f "$SOURCE_CONFIG" ] && [ ! -d "$SOURCE_CONFIG" ] && FAIL 2 "no such file or directory '$SOURCE_CONFIG'"
local TARGET_CONFIG="$HOME/.config/$2" local TARGET_CONFIG="$HOME/.config/$2"
[ ! -f "$SOURCE_CONFIG" ] && [ ! -d "$SOURCE_CONFIG" ] && [ -f "$TARGET_CONFIG" ] && {
INFO 'SOURCE_CONFIG is not tracked; copying from TARGET_CONFIG'
mkdir -p "$(dirname "$SOURCE_CONFIG")"
cp "$TARGET_CONFIG" "$SOURCE_CONFIG"
}
[ ! -f "$SOURCE_CONFIG" ] && [ ! -d "$SOURCE_CONFIG" ] && {
WARNING "no such file or directory '$SOURCE_CONFIG'"
return 0
}
[ ! -d $(dirname "$TARGET_CONFIG") ] && mkdir -p $(dirname "$TARGET_CONFIG") [ ! -d $(dirname "$TARGET_CONFIG") ] && mkdir -p $(dirname "$TARGET_CONFIG")
[[ $SAFE_SYMLINKS -eq 1 ]] \ [[ $SAFE_SYMLINKS -eq 1 ]] \

View File

@ -25,6 +25,9 @@ LAUNCH_OR_SHOW() {
-a, --always-launch invoke executable even if client-class exists -a, --always-launch invoke executable even if client-class exists
-n, --no-resize don't resize the window (ignores -sxy flags) -n, --no-resize don't resize the window (ignores -sxy flags)
-l, --no-center leave the window wherever it was last positioned
--has-statusbar-icon (default: false) use if program has a statusbar icon
-h, --help print this message and exit -h, --help print this message and exit
@ -47,6 +50,8 @@ LAUNCH_OR_SHOW() {
local ALWAYS_LAUNCH=0 local ALWAYS_LAUNCH=0
local RESIZE=1 local RESIZE=1
local MOVE=1
local MIN_ACTIVE=1
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
@ -58,6 +63,9 @@ LAUNCH_OR_SHOW() {
-a | --always-launch ) ALWAYS_LAUNCH=1 ;; -a | --always-launch ) ALWAYS_LAUNCH=1 ;;
-n | --no-resize ) RESIZE=0 ;; -n | --no-resize ) RESIZE=0 ;;
-l | --no-center ) MOVE=0 ;;
--has-statusbar-icon ) MIN_ACTIVE=2 ;;
-h | --help ) USAGE; exit 0 ;; -h | --help ) USAGE; exit 0 ;;
@ -78,7 +86,13 @@ LAUNCH_OR_SHOW() {
} }
} }
ERROR_CHECK CHECK_ERRORS
xrandr | grep primary | awk '{print $4;}' | grep -q '^[0-9]\+$' || {
xrandr --output $(xrandr | grep ' connected' | awk '{print $1;}' | head -n1) --primary
}
local CURRENTLY_ACTIVE=$(xdotool search --onlyvisible --classname $CLIENT_CLASS 2>/dev/null | wc -l)
local LAUNCH_APP=$ALWAYS_LAUNCH local LAUNCH_APP=$ALWAYS_LAUNCH
STATUS "looking for window process ids" STATUS "looking for window process ids"
@ -107,11 +121,15 @@ LAUNCH_OR_SHOW() {
&& STATUS 'resizing window' \ && STATUS 'resizing window' \
&& i3-msg "[class=$CLIENT_CLASS] resize set $WINDOW_SIZE" && i3-msg "[class=$CLIENT_CLASS] resize set $WINDOW_SIZE"
STATUS 'pulling window from scratchpad to foreground' [[ $CURRENTLY_ACTIVE -lt $MIN_ACTIVE ]] && {
i3-msg "[class=$CLIENT_CLASS] scratchpad show" STATUS 'pulling window from scratchpad to foreground'
i3-msg "[class=$CLIENT_CLASS] scratchpad show"
}
STATUS 'moving window to center of current screen' STATUS 'moving window to center of current screen'
i3-msg "[class=$CLIENT_CLASS] move position center" [[ $MOVE -eq 1 ]] && i3-msg "[class=$CLIENT_CLASS] move position center"
return 0
} }
##################################################################### #####################################################################

View File

@ -65,7 +65,7 @@ INSTALL() {
} }
} }
ERROR_CHECK CHECK_ERRORS
#################################################### ####################################################