client: src: lib_gen: add args and args parsing
- Allows for a dynamic `gen` experience
* All configs/accounts can now be (re)generated on-the-fly
- Individually, by section, or all at once
* Adds prompt confirmation option
* Adds developer profile option
This commit is contained in:
@@ -33,15 +33,346 @@ source "${DOCKER_FINANCE_CLIENT_REPO}/container/src/finance/lib/internal/lib_uti
|
||||
# Implementation
|
||||
#
|
||||
|
||||
function lib_gen::__parse_args()
|
||||
{
|
||||
[ -z "$global_usage" ] && lib_utils::die_fatal
|
||||
[ -z "$global_arg_delim_1" ] && lib_utils::die_fatal
|
||||
[ -z "$global_arg_delim_2" ] && lib_utils::die_fatal
|
||||
[ -z "$global_arg_delim_3" ] && lib_utils::die_fatal
|
||||
|
||||
# All available hledger-flow accounts
|
||||
local _accounts
|
||||
mapfile -t _accounts < <(find ${DOCKER_FINANCE_CLIENT_REPO}/container/src/hledger-flow/accounts -name template | sort | rev | cut -d/ -f2 | rev)
|
||||
declare -r _accounts
|
||||
|
||||
local -r _usage="
|
||||
\e[32mDescription:\e[0m
|
||||
|
||||
Generate environment and configurations
|
||||
|
||||
\e[32mUsage:\e[0m
|
||||
|
||||
$ $global_usage <<[all${global_arg_delim_2}<type1[{${global_arg_delim_2}type2${global_arg_delim_3}...}]>] [type${global_arg_delim_3}<type1[${global_arg_delim_3}type2...]>]> [<[profile${global_arg_delim_2}<profile>]> [config${global_arg_delim_2}<config1[${global_arg_delim_3}config2...]>] [account${global_arg_delim_2}<account1[${global_arg_delim_3}account2...]>]] [confirm${global_arg_delim_2}<{on|yes|true} | {off|no|false}>] [dev${global_arg_delim_2}<{on|yes|true} | {off|no|false}>]
|
||||
|
||||
\e[32mArguments:\e[0m
|
||||
|
||||
All categories and data:
|
||||
|
||||
all${global_arg_delim_2}<all | type>
|
||||
|
||||
Note: 'type' is currently the same as 'all'
|
||||
|
||||
Category type:
|
||||
|
||||
type${global_arg_delim_2}<env | build | flow | superscript>
|
||||
|
||||
Flow (only):
|
||||
|
||||
Full profile (w/ subprofile):
|
||||
|
||||
profile${global_arg_delim_2}<parent${global_arg_delim_1}child>
|
||||
|
||||
Configuration type:
|
||||
|
||||
config${global_arg_delim_2}<fetch | hledger | meta | subprofile>
|
||||
|
||||
Accounts:
|
||||
|
||||
account${global_arg_delim_2}<$(echo "${_accounts[@]}" | sed 's: : | :g')>
|
||||
|
||||
Enable developer profile w/ mockups:
|
||||
|
||||
dev${global_arg_delim_2}<{on|yes|true} | {off|no|false}> # (default disabled)
|
||||
|
||||
Enable confirmations:
|
||||
|
||||
confirm${global_arg_delim_2}<{on|yes|true} | {off|no|false}> # (default enabled)
|
||||
|
||||
|
||||
\e[32mExamples:\e[0m
|
||||
|
||||
\e[37;2m#\e[0m
|
||||
\e[37;2m# All (client, container)\e[0m
|
||||
\e[37;2m#\e[0m
|
||||
|
||||
\e[37;2m# Generate all client and container data\e[0m
|
||||
$ $global_usage all${global_arg_delim_2}all
|
||||
|
||||
\e[37;2m# Generate all client and container data, skipping confirmations (using a default profile/subprofile name)\e[0m
|
||||
$ $global_usage all${global_arg_delim_2}all confirm${global_arg_delim_2}no
|
||||
|
||||
\e[37;2m# Generate all client and container data for profile called 'parent/child', skipping confirmations\e[0m
|
||||
$ $global_usage all${global_arg_delim_2}all profile${global_arg_delim_2}parent${global_arg_delim_1}child confirm${global_arg_delim_2}off
|
||||
|
||||
\e[37;2m#\e[0m
|
||||
\e[37;2m# Client (joint container)\e[0m
|
||||
\e[37;2m#\e[0m
|
||||
|
||||
\e[37;2m# Generate only the Docker environment\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}env
|
||||
|
||||
\e[37;2m# Generate custom Dockerfile and joint client/container superscript\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}build${global_arg_delim_3}superscript
|
||||
|
||||
\e[37;2m# Generate all client related data\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}env${global_arg_delim_3}build${global_arg_delim_3}superscript
|
||||
|
||||
\e[37;2m#\e[0m
|
||||
\e[37;2m# Flow: Profile -> Configs / Accounts\e[0m
|
||||
\e[37;2m#\e[0m
|
||||
|
||||
\e[37;2m# Generate all client related and all flow related for profile/subprofile called 'parent/child'\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}env${global_arg_delim_3}build${global_arg_delim_3}superscript${global_arg_delim_3}flow profile${global_arg_delim_2}parent${global_arg_delim_1}child
|
||||
|
||||
\e[37;2m# Same command as above but without confirmations and with developer mockups\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}env${global_arg_delim_3}build${global_arg_delim_3}superscript${global_arg_delim_3}flow profile${global_arg_delim_2}parent${global_arg_delim_1}child confirm${global_arg_delim_2}false dev${global_arg_delim_2}true
|
||||
|
||||
\e[37;2m# Generate only the given configurations for 'parent/child'\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}flow profile${global_arg_delim_2}parent${global_arg_delim_1}child config${global_arg_delim_2}fetch${global_arg_delim_3}hledger${global_arg_delim_3}meta${global_arg_delim_3}subprofile
|
||||
|
||||
\e[37;2m# Generate only the given accounts for 'parent/child'\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}flow profile${global_arg_delim_2}parent${global_arg_delim_1}child account${global_arg_delim_2}capital-one${global_arg_delim_3}chase${global_arg_delim_3}coinbase
|
||||
|
||||
\e[37;2m# Generate the given configs and accounts for given 'parent/child'\e[0m
|
||||
$ $global_usage type${global_arg_delim_2}flow profile${global_arg_delim_2}parent${global_arg_delim_1}child config${global_arg_delim_2}meta${global_arg_delim_3}subprofile account${global_arg_delim_2}ethereum-based${global_arg_delim_3}metamask
|
||||
|
||||
\e[32mNotes:\e[0m
|
||||
|
||||
- The 'profile' argument is limited to 'type' flow
|
||||
- The 'config' and 'account' arguments require 'profile'
|
||||
"
|
||||
|
||||
#
|
||||
# Ensure supported arguments
|
||||
#
|
||||
|
||||
[ $# -eq 0 ] && lib_utils::die_usage "$_usage"
|
||||
|
||||
for _arg in "$@"; do
|
||||
[[ ! "$_arg" =~ ^all${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^type${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^profile${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^config[s]?${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^account[s]?${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^confirm${global_arg_delim_2} ]] \
|
||||
&& [[ ! "$_arg" =~ ^dev${global_arg_delim_2} ]] \
|
||||
&& lib_utils::die_usage "$_usage"
|
||||
done
|
||||
|
||||
#
|
||||
# Parse arguments before testing
|
||||
#
|
||||
|
||||
# Parse key for value
|
||||
for _arg in "$@"; do
|
||||
|
||||
local _key="${_arg%${global_arg_delim_2}*}"
|
||||
local _len="$((${#_key} + 1))"
|
||||
|
||||
if [[ "$_key" =~ ^all$ ]]; then
|
||||
local _arg_all="${_arg:${_len}}"
|
||||
[ -z "$_arg_all" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^type$ ]]; then
|
||||
local _arg_type="${_arg:${_len}}"
|
||||
[ -z "$_arg_type" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^profile$ ]]; then
|
||||
local _arg_profile="${_arg:${_len}}"
|
||||
[ -z "$_arg_profile" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^config[s]?$ ]]; then
|
||||
local _arg_config="${_arg:${_len}}"
|
||||
[ -z "$_arg_config" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^account[s]?$ ]]; then
|
||||
local _arg_account="${_arg:${_len}}"
|
||||
[ -z "$_arg_account" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^confirm$ ]]; then
|
||||
local _arg_confirm="${_arg:${_len}}"
|
||||
[ -z "$_arg_confirm" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
if [[ "$_key" =~ ^dev$ ]]; then
|
||||
local _arg_dev="${_arg:${_len}}"
|
||||
[ -z "$_arg_dev" ] && lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
#
|
||||
# Test for valid ordering/functionality of argument values
|
||||
#
|
||||
|
||||
[[ -z "$_arg_all" && -z "$_arg_type" ]] && lib_utils::die_usage "$_usage"
|
||||
|
||||
# Arg: all
|
||||
if [ ! -z "$_arg_all" ]; then
|
||||
# If all= then no need for type= or config= or account=
|
||||
if [[ ! -z "$_arg_type" || ! -z "$_arg_config" || ! -z "$_arg_account" ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arg: type
|
||||
# Note: check not needed
|
||||
|
||||
# Arg: profile
|
||||
if [ ! -z "$_arg_profile" ]; then
|
||||
# Requires type to be set
|
||||
if [[ ! "${_arg_all[*]}" =~ all|type && -z "$_arg_type" ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arg: config
|
||||
if [ ! -z "$_arg_config" ]; then
|
||||
# Requires profile to be set
|
||||
if [ -z "$_arg_profile" ]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arg: account
|
||||
if [ ! -z "$_arg_account" ]; then
|
||||
# Requires profile to be set
|
||||
if [ -z "$_arg_profile" ]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arg: confirm
|
||||
# Note: optional argument, check not needed
|
||||
|
||||
# Arg: dev
|
||||
# Note: optional argument, check not needed
|
||||
|
||||
#
|
||||
# Test argument values, set globals
|
||||
#
|
||||
|
||||
IFS="$global_arg_delim_3"
|
||||
|
||||
# Arg: all
|
||||
if [ ! -z "$_arg_all" ]; then
|
||||
read -ra _read <<<"$_arg_all"
|
||||
for _arg in "${_read[@]}"; do
|
||||
# Supported values
|
||||
[[ ! "$_arg" =~ ^all$|^type[s]?$ ]] \
|
||||
&& lib_utils::die_usage "$_usage"
|
||||
|
||||
# If all=all then no need for all={type}
|
||||
[[ "$_arg" == "all" && "${#_read[@]}" -gt 1 ]] \
|
||||
&& lib_utils::die_usage "$_usage"
|
||||
done
|
||||
# TODO: currently, 'all' will be equivalent 'type'
|
||||
declare -gr global_arg_all=("${_read[@]}")
|
||||
fi
|
||||
|
||||
# Arg: type
|
||||
if [ ! -z "$_arg_type" ]; then
|
||||
read -ra _read <<<"$_arg_type"
|
||||
for _arg in "${_read[@]}"; do
|
||||
if [[ ! "$_arg" =~ ^env$|^build$|^flow$|^superscript$ ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
done
|
||||
declare -gr global_arg_type=("${_read[@]}")
|
||||
fi
|
||||
|
||||
# Arg: profile
|
||||
if [ ! -z "$_arg_profile" ]; then
|
||||
# Requires flow type
|
||||
if [[ ! "${global_arg_all[*]}" =~ all|type && ! "${global_arg_type[*]}" =~ flow ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
if [[ ! "$_arg_profile" =~ $global_arg_delim_1 ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
declare -gr global_arg_profile="${_arg_profile%${global_arg_delim_1}*}"
|
||||
declare -gr global_arg_subprofile="${_arg_profile##*${global_arg_delim_1}}"
|
||||
fi
|
||||
|
||||
# Arg: config
|
||||
if [ ! -z "$_arg_config" ]; then
|
||||
# Requires profile type
|
||||
if [ -z "$global_arg_profile" ]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
read -ra _read <<<"$_arg_config"
|
||||
for _arg in "${_read[@]}"; do
|
||||
if [[ ! "$_arg" =~ ^fetch$|^hledger$|^meta$|^subprofile$ ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
done
|
||||
declare -gr global_arg_config=("${_read[@]}")
|
||||
fi
|
||||
|
||||
# Arg: account
|
||||
if [ ! -z "$_arg_account" ]; then
|
||||
# Requires profile type
|
||||
if [ -z "$global_arg_profile" ]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
read -ra _read <<<"$_arg_account"
|
||||
# Test if given account is supported
|
||||
for _arg in "${_read[@]}"; do
|
||||
_found=false
|
||||
for _account in "${_accounts[@]}"; do
|
||||
[[ "$_arg" == "$_account" ]] && _found=true
|
||||
done
|
||||
[ $_found == true ] && continue || lib_utils::die_usage "$_usage"
|
||||
done
|
||||
declare -gr global_arg_account=("${_read[@]}")
|
||||
fi
|
||||
|
||||
# Arg: confirm
|
||||
if [ ! -z "$_arg_confirm" ]; then
|
||||
if [[ ! "$_arg_confirm" =~ (^on$|^yes$|^true$)|(^off$|^no$|^false$) ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
if [[ "$_arg_confirm" =~ ^off$|^no$|^false$ ]]; then
|
||||
declare -gr global_arg_confirm=""
|
||||
else
|
||||
declare -gr global_arg_confirm="true"
|
||||
fi
|
||||
else
|
||||
declare -gr global_arg_confirm="true"
|
||||
fi
|
||||
|
||||
# Arg: dev
|
||||
if [ ! -z "$_arg_dev" ]; then
|
||||
if [[ ! "$_arg_dev" =~ (^on$|^yes$|^true$)|(^off$|^no$|^false$) ]]; then
|
||||
lib_utils::die_usage "$_usage"
|
||||
fi
|
||||
if [[ "$_arg_dev" =~ ^on$|^yes$|^true$ ]]; then
|
||||
declare -gr global_arg_dev="true"
|
||||
else
|
||||
declare -gr global_arg_dev=""
|
||||
fi
|
||||
else
|
||||
declare -gr global_arg_dev=""
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Generate new configurations or layout
|
||||
#
|
||||
|
||||
function lib_gen::gen()
|
||||
{
|
||||
lib_gen::__parse_args "$@"
|
||||
|
||||
lib_utils::print_custom "\n"
|
||||
lib_utils::print_info "Generating client/container environment"
|
||||
|
||||
# TODO: this warning is likely not needed now that lib_env is ensured
|
||||
# WARNING: client generation MUST be done before container generation
|
||||
lib_gen::__gen_client
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ function lib_docker::docker()
|
||||
|
||||
function lib_docker::gen()
|
||||
{
|
||||
lib_gen::gen
|
||||
lib_gen::gen "$@"
|
||||
lib_utils::catch $?
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user