let a stack compute its settings without make
A stack can now ship <name>.env and <name>.sh next to its compose files. The hook is sourced with the tag helpers available, which is what the computing .mk files of the catalogue were using make for: 29 of its 44 .mk files only exist to build variables like the fabio tags. Converting stack/host/fabio.mk by hand gives byte-identical output for the route tag, and drops a trailing comma the make version left in the listener list. Also: APP_HOST and APP_URI are computed (the tag helpers build on them), --color controls the escape codes rather than always emitting them, and make test-portability runs the CLI under busybox ash and dash.
This commit is contained in:
+32
-19
@@ -1,34 +1,47 @@
|
||||
#shellcheck shell=sh
|
||||
# shellcheck disable=SC3028 # HOSTNAME is a myos variable, set by bin/myos
|
||||
# myos env [VAR...] show resolved variables (replaces the make print-VAR target)
|
||||
|
||||
# myos_env_print NAME VALUE
|
||||
# Same shape as the make print-<VAR> target: the name padded to 37 columns in
|
||||
# the highlight colour, then the value in the value colour.
|
||||
myos_env_print() {
|
||||
printf '%s%-37s%s%s%s%s\n' \
|
||||
"$MYOS_C_HIGHLIGHT" "$1" "$MYOS_C_RESET" "$MYOS_C_VALUE" "$2" "$MYOS_C_RESET"
|
||||
}
|
||||
|
||||
myos_cmd_env() {
|
||||
_vars=${MYOS_VARS:-}
|
||||
[ -n "$_vars" ] || _vars=$MYOS_ARGS
|
||||
[ -n "$_vars" ] || _vars=$MYOS_REFS_RAW
|
||||
if [ -z "$_vars" ]; then
|
||||
_vars="ENV USER HOSTNAME DOMAIN WORKDIR MYOS_PATH STACK COMPOSE_PROJECT_NAME COMPOSE_FILE"
|
||||
_vars="ENV USER HOSTNAME DOMAIN WORKDIR MYOS_PATH SCOPE STACK COMPOSE_PROJECT_NAME COMPOSE_FILE"
|
||||
fi
|
||||
for _v in $_vars; do
|
||||
case $_v in
|
||||
MYOS_PATH) printf '%s %s\n' "$_v" "$(myos_path)" ;;
|
||||
COMPOSE_FILE) printf '%s %s\n' "$_v" "$(myos_all_compose_files | tr '\n' ' ' | sed 's/ $//')" ;;
|
||||
COMPOSE_PROJECT_NAME) printf '%s %s\n' "$_v" "$(myos_first_project)" ;;
|
||||
STACK) printf '%s %s\n' "$_v" "$(printf '%s' "$MYOS_STACKS" | tr '\n' ' ' | sed 's/ $//')" ;;
|
||||
DOCKER_NETWORK_DEFAULT) printf '%s %s\n' "$_v" "$(myos_network_default "$(myos_first_project)")" ;;
|
||||
DOCKER_NETWORK_PRIVATE) printf '%s %s\n' "$_v" "$(myos_network_private "$USER" "$ENV")" ;;
|
||||
DOCKER_NETWORK_PUBLIC) printf '%s %s\n' "$_v" "$(myos_network_public "${HOSTNAME:-}")" ;;
|
||||
COMPOSE_SERVICE_NAME) printf '%s %s\n' "$_v" "$(myos_service_name "$(myos_first_project)")" ;;
|
||||
COMPOSE_FILE_SUFFIX) printf '%s %s\n' "$_v" "$(myos_compose_suffixes)" ;;
|
||||
APP|APP_NAME) printf '%s %s\n' "$_v" "$(myos_first_app)" ;;
|
||||
SCOPE) printf '%s %s\n' "$_v" "$(myos_first_scope)" ;;
|
||||
# HOST_STACK/USER_STACK are the names the make engine used for the scope
|
||||
HOST_STACK) [ "$(myos_first_scope)" = host ] && printf '%s host\n' "$_v" || printf '%s\n' "$_v" ;;
|
||||
USER_STACK) [ "$(myos_first_scope)" = user ] && printf '%s User\n' "$_v" || printf '%s\n' "$_v" ;;
|
||||
DOCKER_REPOSITORY) printf '%s %s\n' "$_v" "$(printf '%s' "$(myos_first_project)" | tr '_-' '//')" ;;
|
||||
MYOS_PATH) myos_env_print "$_v" "$(myos_path)" ;;
|
||||
COMPOSE_FILE) myos_env_print "$_v" "$(myos_all_compose_files | tr '\n' ' ' | sed 's/ $//')" ;;
|
||||
COMPOSE_PROJECT_NAME) myos_env_print "$_v" "$(myos_first_project)" ;;
|
||||
COMPOSE_SERVICE_NAME) myos_env_print "$_v" "$(myos_service_name "$(myos_first_project)")" ;;
|
||||
COMPOSE_FILE_SUFFIX) myos_env_print "$_v" "$(myos_compose_suffixes)" ;;
|
||||
STACK) myos_env_print "$_v" "$(printf '%s' "$MYOS_STACKS" | tr '\n' ' ' | sed 's/ $//')" ;;
|
||||
SCOPE) myos_env_print "$_v" "$(myos_first_scope)" ;;
|
||||
APP|APP_NAME) myos_env_print "$_v" "$(myos_first_app)" ;;
|
||||
DOCKER_REPOSITORY) myos_env_print "$_v" "$(printf '%s' "$(myos_first_project)" | tr '_-' '//')" ;;
|
||||
DOCKER_NETWORK_DEFAULT) myos_env_print "$_v" "$(myos_network_default "$(myos_first_project)")" ;;
|
||||
DOCKER_NETWORK_PRIVATE) myos_env_print "$_v" "$(myos_network_private "$USER" "$ENV")" ;;
|
||||
DOCKER_NETWORK_PUBLIC) myos_env_print "$_v" "$(myos_network_public "${HOSTNAME:-}")" ;;
|
||||
DOCKER_NETWORK)
|
||||
if [ "$(myos_first_scope)" = user ]; then printf '%s %s\n' "$_v" "$USER"
|
||||
else printf '%s %s\n' "$_v" "$(myos_network_private "$USER" "$ENV")"; fi ;;
|
||||
*) printf '%s %s\n' "$_v" "$(myos_var "$_v")" ;;
|
||||
if [ "$(myos_first_scope)" = user ]; then myos_env_print "$_v" "$USER"
|
||||
else myos_env_print "$_v" "$(myos_network_private "$USER" "$ENV")"; fi ;;
|
||||
# HOST_STACK and USER_STACK are what the make engine called the scope
|
||||
HOST_STACK)
|
||||
if [ "$(myos_first_scope)" = host ]; then myos_env_print "$_v" host
|
||||
else myos_env_print "$_v" ""; fi ;;
|
||||
USER_STACK)
|
||||
if [ "$(myos_first_scope)" = user ]; then myos_env_print "$_v" User
|
||||
else myos_env_print "$_v" ""; fi ;;
|
||||
*) myos_env_print "$_v" "$(myos_var "$_v")" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
+13
-1
@@ -13,13 +13,25 @@ MYOS_E_USAGE=2 # bad invocation
|
||||
MYOS_E_NOSTACK=3 # stack not found
|
||||
MYOS_E_NOREQ=4 # missing requirement
|
||||
|
||||
# myos_colors decide whether to emit colour.
|
||||
# MYOS_COLOR=always|never|auto (default auto: only when stdout is a terminal).
|
||||
# The make engine always emitted the escape codes, even into a pipe.
|
||||
myos_colors() {
|
||||
if [ -t 2 ] && [ "${TERM:-dumb}" != dumb ] && [ -z "${NO_COLOR:-}" ]; then
|
||||
_want=${MYOS_COLOR:-auto}
|
||||
[ -n "${NO_COLOR:-}" ] && _want=never
|
||||
case $_want in
|
||||
never) _want=no ;;
|
||||
always) _want=yes ;;
|
||||
*) if [ -t 1 ] && [ "${TERM:-dumb}" != dumb ]; then _want=yes; else _want=no; fi ;;
|
||||
esac
|
||||
if [ "$_want" = yes ]; then
|
||||
MYOS_C_ERROR=$(printf '\033[31m'); MYOS_C_WARN=$(printf '\033[01;33m')
|
||||
MYOS_C_INFO=$(printf '\033[33m'); MYOS_C_DEBUG=$(printf '\033[01;34m')
|
||||
MYOS_C_VALUE=$(printf '\033[36m'); MYOS_C_RESET=$(printf '\033[0m')
|
||||
MYOS_C_HIGHLIGHT=$(printf '\033[32m')
|
||||
else
|
||||
MYOS_C_ERROR=; MYOS_C_WARN=; MYOS_C_INFO=; MYOS_C_DEBUG=; MYOS_C_VALUE=; MYOS_C_RESET=
|
||||
MYOS_C_HIGHLIGHT=
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#shellcheck shell=sh
|
||||
# hooks: the per-stack settings that used to live in a .mk file.
|
||||
#
|
||||
# A stack may ship, next to its compose files:
|
||||
# <name>.env dotenv, for plain values
|
||||
# <name>.env.<env> the same, for one environment
|
||||
# <name>.sh shell, for values that have to be computed (fabio tags, JWTs)
|
||||
# <name>.mk the legacy make snippet, still read for its groups
|
||||
#
|
||||
# A .sh hook runs with the myos helpers available (myos_tagprefix, myos_uri,
|
||||
# myos_var) and sets variables directly. This is what lets a stack of the
|
||||
# catalogue work on a machine that has no make.
|
||||
|
||||
# myos_stack_hooks DIR NAME load the hooks of one stack, most specific last
|
||||
myos_stack_hooks() {
|
||||
_hdir=$1; _hname=$2
|
||||
for _h in "$_hdir/$_hname.env" "$_hdir/$_hname.env.$ENV"; do
|
||||
[ -f "$_h" ] && myos_dotenv_load "$_h"
|
||||
done
|
||||
for _h in "$_hdir/$_hname.sh" "$_hdir/$_hname.$ENV.sh"; do
|
||||
if [ -f "$_h" ]; then
|
||||
myos_debug "hook $_h"
|
||||
# shellcheck source=/dev/null
|
||||
. "$_h"
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
@@ -79,3 +79,44 @@ myos_service_name() { printf '%s' "$1" | tr '_' '-'; }
|
||||
myos_network_default() { printf '_%s' "$1"; }
|
||||
myos_network_private() { printf '%s' "${DOCKER_NETWORK_PRIVATE:-${1}-${2}}"; }
|
||||
myos_network_public() { printf '%s' "${DOCKER_NETWORK_PUBLIC:-${1}}"; }
|
||||
|
||||
# myos_app_domain SCOPE USER DOMAIN
|
||||
# The domain a stack is served on. A host stack is never prefixed by the user:
|
||||
# it belongs to the machine.
|
||||
myos_app_domain() {
|
||||
_scope=$1; _u=$2; _dom=$3
|
||||
if [ "$_scope" != host ] && [ "${APP_HOST_MULTI_USER:-false}" = true ]; then
|
||||
printf '%s.%s' "$_u" "$_dom"
|
||||
else
|
||||
printf '%s' "$_dom"
|
||||
fi
|
||||
}
|
||||
|
||||
# myos_app_host SCOPE USER ENV APP DOMAIN HOSTNAME
|
||||
# A host stack is served on <hostname>.<domain>; anything else is prefixed by
|
||||
# the environment unless the environment is the main one.
|
||||
myos_app_host() {
|
||||
_scope=$1; _u=$2; _env=$3; _app=$4; _dom=$5; _host=$6
|
||||
_multi_env=${APP_HOST_MULTI_ENV:-}
|
||||
if [ -z "$_multi_env" ]; then
|
||||
case $_env in local|master|main) _multi_env=false ;; *) _multi_env=true ;; esac
|
||||
fi
|
||||
_prefix=
|
||||
if [ "$_scope" = host ]; then _prefix="$_host."
|
||||
elif [ "$_multi_env" = true ]; then _prefix="$_env."
|
||||
fi
|
||||
_name=
|
||||
[ "${APP_HOST_MULTI_APP:-false}" = true ] && _name="$(myos_name "$_app")."
|
||||
_out="$_prefix$_name$(myos_app_domain "$_scope" "$_u" "$_dom")"
|
||||
# a host stack behind the load balancer also answers on the bare domain
|
||||
[ "$_scope" = host ] && [ -n "${HOST_LB:-}" ] && _out="$_out $_dom"
|
||||
printf '%s' "$_out"
|
||||
}
|
||||
|
||||
# myos_app_uri HOST [PATH] the base uri the fabio tags are built on;
|
||||
# it always ends with a slash
|
||||
myos_app_uri() {
|
||||
_out=
|
||||
for _h in $1; do _out="${_out:+$_out }$_h/${2:-}"; done
|
||||
printf '%s' "$_out"
|
||||
}
|
||||
|
||||
+14
@@ -71,3 +71,17 @@ myos_tagprefix() {
|
||||
[ -n "$_uris" ] || _uris=$(myos_uri "$_stack" "$_port")
|
||||
myos_urlprefix "$_path" "$_opts" "$_uris"
|
||||
}
|
||||
|
||||
# myos_servicenvs STACK GROUP KEY
|
||||
# Collect <STACK>_SERVICE_<env>_<KEY> for every env listed in
|
||||
# <STACK>_SERVICE_<GROUP>_ENVS. Used to build a list of listeners out of one
|
||||
# variable per protocol.
|
||||
myos_servicenvs() {
|
||||
_s=$(myos_upper "$1"); _g=$(myos_upper "$2"); _k=$(myos_upper "$3")
|
||||
_out=
|
||||
for _e in $(myos_var "${_s}_SERVICE_${_g}_ENVS"); do
|
||||
_v=$(myos_var "${_s}_SERVICE_$(myos_upper "$_e")_${_k}")
|
||||
[ -n "$_v" ] && _out="${_out:+$_out }$_v"
|
||||
done
|
||||
printf '%s' "$_out"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user