diff --git a/.github/workflows/github-test-workflow.yml b/.github/workflows/github-test-workflow.yml old mode 100644 new mode 100755 index 17aa1e49..84c1fafc --- a/.github/workflows/github-test-workflow.yml +++ b/.github/workflows/github-test-workflow.yml @@ -21,7 +21,7 @@ jobs: - name: "shellcheck main" run: ./prj/run-shellcheck.sh - name: "shellcheck standalones" - run: shellcheck --exclude "SC2181,SC2155,SC2119,SC2031" activate && shellcheck --exclude "SC2181,SC2155,SC2119,SC2031" deactivate + run: shellcheck --exclude "SC2181,SC2155,SC2119,SC2031,SC2317" activate && shellcheck --exclude "SC2181,SC2155,SC2119,SC2031,SC2317" deactivate tests: strategy: matrix: diff --git a/.github/workflows/multi-arch.yml b/.github/workflows/multi-arch.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/Dockerfile.GitHub b/Dockerfile.GitHub old mode 100644 new mode 100755 diff --git a/Dockerfile.OCP b/Dockerfile.OCP old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/activate-auto b/activate-auto old mode 100644 new mode 100755 diff --git a/bin/ent b/bin/ent index 8ae3868c..36d6ad73 100755 --- a/bin/ent +++ b/bin/ent @@ -8,11 +8,11 @@ #H:: #H:: Built-in Scripts: +# The directory from which ent was called # shellcheck disable=SC2034 -ENT_ORIGIN_WORKDIR="$PWD" +ENT_CALLER_DIR="$PWD" +ENT_CALLER_PATH="$PATH" -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RUN() { upgrade_project_file "$C_ENT_PRJ_FILE" "$C_ENT_OLD_PRJ_FILE" @@ -27,8 +27,12 @@ RUN() { while true; do cmd="$1" export ENTANDO_CLI_COMMAND="$1" + cmd=$(_resolve_alias "$cmd") shift + + [ "$ENTANDO_ENT_TRACE" == "true" ] && set -x + case "$cmd" in "version") #H: shows the version of the current ent which_ent version @@ -61,6 +65,9 @@ RUN() { # shellcheck disable=SC1090 source "$ENTANDO_ENT_HOME/bin/mod/ent-profile" "$@" ;; + "sub-profile"|"SP"|"subpro") #H: helps creating and managing sub-profiles + _shortcut_subpro "$@" + ;; "attach-vm") #H: [vm-name] -- attach ent to a ent-managed VM managed-vm-attach "$@" ;; @@ -126,18 +133,21 @@ RUN() { "jhipster"|"bundler"|"bundle") _ent node-cmd-wrapper "$cmd" "ENT wrapper for the node command \"$cmd\"" "$@" ;; - "pkg") #H: helps dealing with the ent bin tools - _ent.pkg "$@" - ;; "crane"|"docker"|"jq"|"k9s") _ent.pkg run "$cmd" "$@" ;; "use") #H: shortcut to "ent pro use" _ent pro use "$@" ;; + "shell") #H: runs a shell that inherits the ent environment + run-sun-shell "$@" + ;; "load-module") ent-load-extension-module "$@" ;; + "trace") + ent-trace "$@" + ;; "") # shellcheck disable=SC1091 _source_ent help @@ -146,31 +156,15 @@ RUN() { cmplt ;; *) - [ "$cmd" = "k" ] && cmd="kubectl" - - local FOUND=false RV=0 - - local mod_script="${ENTANDO_ENT_HOME}/bin/mod/ent-${cmd}" - - if [ -f "$mod_script" ]; then - FOUND=true - # shellcheck disable=SC1090 - source "$mod_script" "$@" - RV="$?" + _execute_script "$cmd" "$@" + RV="$?" + if [ "$RV" = "33" ]; then + _log_e "Unrecognized ent module or command \"$cmd\"" + elif [ "$RV" = "34" ]; then + _log_e "Unrecognized ent command \"$1\" for module \"$cmd\"" else - local ext_mod_script="$ENTANDO_ENT_EXTENSIONS_MODULES_PATH/ent-${cmd}" - if _ent.extension-module.is-present "$cmd"; then - FOUND=true - _ent.extension-module.execute "${cmd}" "$@" - fi + return "${RV:-1}" fi - - ! $FOUND && { - _log_e "Unrecognized ent command \"$cmd\"" - return 33 - } - - (exit "$RV") ;; esac _SOE @@ -180,172 +174,13 @@ RUN() { done } -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -ent-load-extension-module() { - ( - local REPO NAME BRANCH - args_or_ask -h "$HH" -a -n -- REPO '1/git_repo//%sp repository of the module' "$@" - args_or_ask -h "$HH" -n -- NAME '--name/strict_file_name//%sp name of the module' "$@" - args_or_ask -h "$HH" -n -- BRANCH '--branch/dn//%sp branch to use instead of the default one' "$@" - end_help_parsing - - DIRNAME="$(basename "$REPO")" - [ -z "$NAME" ] && NAME="$DIRNAME" - - local EXT_DIR="${ENTANDO_ENT_HOME}/bin/mod/ext" - mkdir -p "$EXT_DIR" - __cd "$EXT_DIR" - if [[ "$PWD" = *".entando"* ]]; then - [ -d "$DIRNAME" ] && rm -rf "$DIRNAME" - git clone --depth=1 ${BRANCH:+-b "$BRANCH"} --single-branch "$REPO" - cp -p -- "$PWD/$DIRNAME/mod/"* . - else - _FATAL "Extension module cleanup: Refusing to delete a non entando-cli dir" - fi - ) -} - -which_ent() { +_resolve_alias() { case "$1" in - version) echo "${ENTANDO_CLI_VERSION}"; return;; - which) echo "${ENTANDO_CLI_VERSION}";; - home) echo "$ENTANDO_ENT_HOME"; return;; + k) echo "kubectl";; + *) echo "$1";; esac - - ( - echo "" - echo "---" - echo "" - - # CLI INFO - echo "## CLI:" - echo "" - cd "$ENTANDO_ENT_HOME" - echo "- DIR: $ENTANDO_ENT_HOME" - IFS='|' read -r sha time < <(git log --pretty=format:'%H|%ci' -1) - echo "- SHA: $sha" - echo "- UPD: $time" - echo "" - - # RELEASE INFO - __cd "$(_dist_directory)" - echo "## RELEASE:" - echo "" - echo "- DIR: $PWD" - IFS='|' read -r sha time < <(git log --pretty=format:'%H|%ci' -1) - echo "- SHA: $sha" - echo "- UPD: $time" - echo "" - - ) 1>&2 } -handle_config_command() { - bgn_help_parsing "${BASH_SOURCE[0]}" "$@" - - args_or_ask -h "$HH" -f -- '--default///selects the default ent configuration' "$@" && { - # shellcheck disable=SC2034 - CFG_FILE="$ENT_DEFAULT_CFG_FILE" - ENT_WORK_DIR="${ENTANDO_ENT_HOME}/w" - THIS_PROFILE="" - } - args_or_ask -h "$HH" -f -- '--global///selects the global ent configuration' "$@" && { - # shellcheck disable=SC2034 - _pp ENTANDO_GLOBAL_CFG - CFG_FILE="$ENTANDO_GLOBAL_CFG" - ENT_WORK_DIR="${ENTANDO_ENT_HOME}/w" - THIS_PROFILE="" - } - - args_or_ask -h "$HH" -F ENTANDO_NO_OBFUSCATION '--no-obfuscation///disables the obfuscation in the effective configuration' "$@" - args_or_ask -h "$HH" -f -- '--effective///prints the effective configuration' "$@" && { - print-effective-config - return 0 - } - - args_or_ask -h "$HH" -f -- '--edit///edits the configuration' "$@" && { - _edit "$CFG_FILE" - return 0 - } - - args_or_ask -h "$HH" -f -- '--set///sets a specific configuration parameter' "$@" && { - args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" - args_or_ask -a -n -h "$HH" "CFG_VALUE" "2///%sp the value to set" "$@" - save_cfg_value "$CFG_KEY" "$CFG_VALUE" "$CFG_FILE" - return 0 - } - - args_or_ask -h "$HH" -f -- '--del///deletes a specific configuration parameter' "$@" && { - args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" - save_cfg_value "$CFG_KEY" "" "$CFG_FILE" - return 0 - } - - args_or_ask -h "$HH" -f -- '--get///gets a specific configuration parameter' "$@" && { - args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" - ( - reload_cfg "$CFG_FILE" - echo "${!CFG_KEY}" - ) - return 0 - } - end_help_parsing - - if [ -n "$THIS_PROFILE" ]; then - _log_i "Configuration of the profile \"$THIS_PROFILE\" ($CFG_FILE):" 1>&2 - else - _log_i "Default configuration of the current entando distribution ($CFG_FILE):" 1>&2 - fi - [ -f "$CFG_FILE" ] || _FATAL -s "Configuration file \"$CFG_FILE\" not found" - cat "$CFG_FILE" - print-secrets-leak-warning -} - -cmplt() { - cd "$ENTANDO_ENT_HOME/bin/mod" || { - echo "Unable to enter directory $PWD/bin" - exit 99 - } - for file in ent-*; do - mod="${file//ent-/}" - echo "$mod" - done - - [ -z "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" ] && ENTANDO_ENT_EXTENSIONS_MODULES_PATH="$ENTANDO_ENT_HOME/bin/mod/ext" - if [ -d "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" ]; then - ( - cd "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" || exit 0 - for file in ent-*; do - [ -f "$file" ] && { - mod="${file//ent-/}" - echo "$mod" - } - done - ) - fi - - local topcmd+=( - "attach-vm" "detach-vm" "fix-vm-ddns" "completion" "config" "which" "version" "home" "import" "activate" - "kubectl-cmd" "reset-kubectl-mode" "status" - "attach-kubeconfig" "detach-kubeconfig" "namespace" "appname" "pkg" - "attach-kubectx" "detach-kubectx" "list-kubectx" - "bundle" "bundler" "jhipster" - ) - - for tc in "${topcmd[@]}"; do - echo "$tc" - done -} - -_ent() { - # shellcheck disable=SC1090 - "$ENTANDO_ENT_HOME/bin/ent" "$@" -} - -_source_ent() { - # shellcheck disable=SC1090 - source "$ENTANDO_ENT_HOME/bin/ent" "$@" -} # ###################################################################################################################### # ###################################################################################################################### @@ -403,43 +238,10 @@ if ( return "$ENTANDO_ENT_TMPVAR_0002bb75" else # shellcheck disable=SC2034 + ENTANDO_CALLER_PWD="$PWD" fi -upgrade_project_file() { - local N=$1 - local O=$2 - if [ -f "$O" ]; then - mkdir -p "$C_ENT_PRJ_ENT_DIR" - if [ -f "$N" ]; then - mv "$O" "$C_ENT_PRJ_ENT_DIR/$O.backup" - else - mv "$O" "$N" - fi - fi -} - -handle_status_config() { - if [ "$V" = "--del" ]; then - ent config --set "" - else - V="$2" - [ "$V" == "--" ] && V="$3" - if [ "$V" = "" ]; then - ent config --get "$1" - else - ent config --set "$1" "$V" - fi - fi -} - -handle_kubectl_cmd() { - if [ "$1" = "" ]; then - ent config --get "ENT_KUBECTL_CMD" - else - ent kubectl ent-set-cmd "$@" - fi -} DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" cd "$DIR/.." || { @@ -459,6 +261,8 @@ fi } . s/_base.sh +. s/_root-helper.sh cd - > /dev/null || _FATAL "internal error" RUN "$@" + diff --git a/bin/mod/ent-check-env b/bin/mod/ent-check-env index 71893eab..d7539d15 100755 --- a/bin/mod/ent-check-env +++ b/bin/mod/ent-check-env @@ -29,11 +29,11 @@ RUN() { $M_DEVL && check-env.develop.minimal-tools-requirements # ENT-LOCAL NODE - $M_DEVL && check-env.check-node + $M_DEVL_BASE && check-env.check-node $M_DEVL && check-env.check-jhipster $M_DEVL && check-env.check-generator-jhipster-entando $M_DEVL && check-env.check-bundler - $M_DEVL && check-env.check-bundle-cli + $M_DEVL_BASE && check-env.check-bundle-cli # RUNTIME $M_KUBE && check-env.runtime.check-k3s @@ -103,7 +103,7 @@ check-env.extention-modules() { local module; while IFS= read -r module; do _ent.extension-module.execute "$module" check-env || { - DEPENDENCY_ERROR "$FAIL_MSG" + DEPENDENCY_ERROR "$FAIL_MSG"$'\n'"for module \"$module\"" } done < <(_ent.extension-modules.list) } @@ -222,15 +222,22 @@ check-env.check-bundle-cli() { local FLAGS FORCE=false parse-version-flags FLAGS VER_ENTANDO_BUNDLE_CLI_DEF VER_ENTANDO_BUNDLE_CLI_REQ ENTANDO_BUNDLE_CLI_VERSION_OVERRIDE _str_contains "$FLAGS" ",f," && FORCE=true + + local SOURCE_BASED=false + if [[ "$VER_ENTANDO_BUNDLE_CLI_REQ" == "v1.2.0" || "$VER_ENTANDO_BUNDLE_CLI_REQ" == *"v1.0"* ]]; then + _str_contains "$FLAGS" ",g," && SOURCE_BASED=true + else + _str_contains "$FLAGS" ",r," || SOURCE_BASED=true + fi - if _str_contains "$FLAGS" ",g,"; then - check_npm_git_package --full "$REPO_ENTANDO_BUNDLE_CLI_ADDR" \ + if $SOURCE_BASED; then + check-env.npm-registry-package entando-registry "entando-bundle-cli" "@entando/entando-bundle-cli" \ "$VER_ENTANDO_BUNDLE_CLI_REQ" "$VER_ENTANDO_BUNDLE_CLI_DEF" \ - "$C_ENTANDO_BUNDLE_CLI_DIR" "$C_ENTANDO_BUNDLE_CLI_DIR" \ "$FORCE" else - check-env.npm-registry-package entando-registry "entando-bundle-cli" "@entando/entando-bundle-cli" \ + check_npm_git_package --full "$REPO_ENTANDO_BUNDLE_CLI_ADDR" \ "$VER_ENTANDO_BUNDLE_CLI_REQ" "$VER_ENTANDO_BUNDLE_CLI_DEF" \ + "$C_ENTANDO_BUNDLE_CLI_DIR" "$C_ENTANDO_BUNDLE_CLI_DIR" \ "$FORCE" fi } @@ -382,13 +389,19 @@ check_npm_git_package() { ( if $FULL; then ___npm "PHASE 1/a" install - ___npm "PHASE 1/b" run build + + if _ent-npm_direct run | grep -q -w "just-build"; then + ___npm "PHASE 1/b" run just-build + else + ___npm "PHASE 1/b" run build + fi elif $WITHINST; then ___npm "PHASE 1" install fi ) || _SOE # ACTUAL INSTALLATION + ___npm "PHASE 2" install --global date > .entando-finalized @@ -490,6 +503,7 @@ PARSE_ARGS() { fi M_DEVL=false + M_DEVL_BASE=false M_KUBE=false M_QS=false ENTANDO_CLI_CHECKENV_MODE="$ARG1" @@ -497,6 +511,10 @@ PARSE_ARGS() { case "$ARG1" in develop) #H: environment for bundle developers M_DEVL=true + M_DEVL_BASE=true + ;; + base-develop) #H: environment for bundle developers + M_DEVL_BASE=true ;; runtime) #H: kubernetes execution environment ! $OS_LINUX && FATAL "not supported on this OS" diff --git a/bin/mod/ent-help b/bin/mod/ent-help index 9b9c0d2a..7dd045fd 100755 --- a/bin/mod/ent-help +++ b/bin/mod/ent-help @@ -85,6 +85,7 @@ cd .. echo -e " --profile|-p {profile} forces the use of the given profile" echo -e " --no-profile|-P forces the use of no profile" echo -e " --debug|-d enables the debug mode for some command" + echo -e " --trace enables shell level instruction trace" echo -e " --color disables the explicit suppression of the colors for some command" echo "" diff --git a/bin/mod/ent-kubectl b/bin/mod/ent-kubectl index cb6da413..fc8d8f0e 100755 --- a/bin/mod/ent-kubectl +++ b/bin/mod/ent-kubectl @@ -109,6 +109,10 @@ print_status_info() { local mode="via user command: \"$ENT_KUBECTL_CMD\"" elif [ -n "$DESIGNATED_VM" ]; then local mode="via VM link to: \"$DESIGNATED_VM\"" + elif [ -n "$DESIGNATED_KUBECONFIG" ]; then + local mode="via config:"$'\n'"~ $DESIGNATED_KUBECONFIG" + elif [ -n "$DESIGNATED_KUBECTX" ]; then + local mode="via context: \"$DESIGNATED_KUBECTX\"" else local mode="via auto-detected kubectl" fi diff --git a/bin/mod/ent-pkg b/bin/mod/ent-pkg new file mode 100644 index 00000000..30305986 --- /dev/null +++ b/bin/mod/ent-pkg @@ -0,0 +1,30 @@ +#!/bin/bash + +#H:: +#H:: Helps managing external dependencies +#H:: +#H:: Syntax: +#H:: - ent pkkg {command} ... +#H:: +#H:: Commands: + +[[ "$1" == "--help" && "$2" == "--short" ]] && { + echo -e "Helps managing an EntandoApp" && exit 0 +} + +[ "$1" = "--cmplt" ] && { + . s/essentials.sh + print_ent_module_sub-commands "${BASH_SOURCE[0]}" + exit 0 +} + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +cd "$DIR/../.." || { + echo "Internal error: unable to find the script source dir" 1>&2 + exit +} + +. s/_base.sh + +_ent.pkg "$@" + diff --git a/bin/mod/ent-pod b/bin/mod/ent-pod index d63170f2..c35406d9 100755 --- a/bin/mod/ent-pod +++ b/bin/mod/ent-pod @@ -12,18 +12,18 @@ echo -e "Displays information related to a set of pods" && exit 0 } -[ "$1" = "--cmplt" ] && { - . s/essentials.sh - print_ent_module_sub-commands "${BASH_SOURCE[0]}" - exit 0 -} - DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)" cd "$DIR/../.." || { echo "Internal error: unable to find the script source dir" 1>&2 exit } +[ "$1" = "--cmplt" ] && { + . s/essentials.sh + print_ent_module_sub-commands "${BASH_SOURCE[0]}" + exit 0 +} + . s/_base.sh RUN() { diff --git a/bin/mod/ent-profile b/bin/mod/ent-profile index 498d1db1..5403fe6b 100755 --- a/bin/mod/ent-profile +++ b/bin/mod/ent-profile @@ -13,18 +13,18 @@ echo -e "Helps managing an EntandoApp" && exit 0 } -[ "$1" = "--cmplt" ] && { - . s/essentials.sh - print_ent_module_sub-commands "${BASH_SOURCE[0]}" - exit 0 -} - DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" cd "$DIR/../.." || { echo "Internal error: unable to find the script source dir" 1>&2 exit } +[ "$1" = "--cmplt" ] && { + . s/essentials.sh + print_ent_module_sub-commands "${BASH_SOURCE[0]}" + exit 0 +} + . s/_base.sh RUN() { @@ -34,34 +34,18 @@ RUN() { args_or_ask -h "$HH" -a -n -- "CMD" '1///%sp command' "$@" args_or_ask -h "$HH" -n -p NAMESPACE "--namespace/ext_ic_id//%sp the kubernetes namespace" "$@" - [[ -n "$HH" ]] && { + [[ "$HH" = "--help" ]] && { print_ent_module_help "${BASH_SOURCE[0]}" "$2" } + + USE_CURRENT_DIR=false show_help_option "$HH" "$CMD" case "$CMD" in "use") #H: selects the profile that ent should use - args_or_ask -h "$HH" -n -F "AUTO_YES" "--yes///Assumes yes for all yes-no questions" "$@" - args_or_ask -h "$HH" -n -F "USE_NO_PROFILE" "--none///Assumes the global profile" "$@" - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///Uses the local dir as based app dir" "$@" - [ -n "$HH" ] && exit 0 - - if [ -z "$COMMAND_FILE" ]; then - local V="ENTANDO_ENT_FORCE_PROFILE_0e7e8d89_$ENTANDO_TTY_QUALIFIER" - [ -n "${!V}" ] && { - local MSG="This SHELL SESSION is currently bound to a specific profile, " - MSG+="in order to use another profile during this session you need to source-run this command" - _log_e "$MSG" - FATAL "TTY_PRO_LOCKED" - } - fi - shift - kubectl_mode --reset-mem - THIS_PROFILE="" PROFILE_ORIGIN="" - use_profile "$@" - fix_profile + _use_or_list_profile "use" "$@" ;; "print-first-use-readme") #H: prints the first-use readme print_first_use_readme @@ -75,25 +59,27 @@ RUN() { setup_curr_profile "$@" ;; "delete") #H: deletes the given profile + shift + args_or_ask -h "$HH" -a -p -n -- PAR_USE_PROFILE '1///profile name (or "." for current profile or --none)' "$@" + args_or_ask -h "$HH" -a -p -n -- PAR_USE_PROFILE_SUB '2///optional sub-profile (or .. for a list of items)' "$@" args_or_ask -h "$HH" -n -F "AUTO_YES" "--yes///Assumes yes for all yes-no questions" "$@" args_or_ask -h "$HH" -n -F "AUTO_NO" "--no///Assumes no for all yes-no questions" "$@" - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///Uses the local dir as based app dir" "$@" + args_or_ask -h "$HH" -F USE_CURRENT_DIR "--local///Uses the local dir as based app dir" "$@" [ -n "$HH" ] && exit 0 - shift + delete_profile "$@" ;; - "list") #H: prints a list of the available profiles - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///Uses the local dir as based app dir" "$@" - [ -n "$HH" ] && exit 0 + "list") #H: lists the available profiles shift - list_profiles "$@" + _use_or_list_profile "list" "$@" ;; "link") #H: links the current profile to a kube context shift profile_link_context "$1" ;; "tmp") #H: creates and activates a tty-bound temporary profile which is the clone of the current one - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///Uses the local dir as based app dir" "$@" + shift + args_or_ask -h "$HH" -F USE_CURRENT_DIR "--local///Uses the local dir as based app dir" "$@" args_or_ask -h "$HH" -F -- PRESERVE_PROFILE "-p///Preserves the old temporary profile" "$@" [ -n "$HH" ] && exit 0 @@ -109,7 +95,7 @@ RUN() { _create_and_use_tmp_clone activate_designated_workdir --temporary - _activate_command_in_source_mode "$DESIGNATED_PROFILE" "$DESIGNATED_PROFILE_HOME" + _activate_command_in_source_mode "$DESIGNATED_PROFILE" "$DESIGNATED_PROFILE_HOME" "$DESIGNATED_PROFILE_SUB" save_cfg_value PROFILE_ORIGIN "$PROFILE_ORIGIN" @@ -117,15 +103,63 @@ RUN() { print_current_profile_info -v ;; "") - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///Uses the local dir as base for the profile dir" "$@" + args_or_ask -h "$HH" -F USE_CURRENT_DIR "--local///Uses the local dir as base for the profile dir" "$@" [ -n "$HH" ] && exit 0 print_current_profile_info _log_i "The available profiles are:" - list_profiles "$@" + list_profile_items "profile" "$1" ;; esac } +_use_or_list_profile() { + MODE="$1"; shift + args_or_ask -h "$HH" -n -F AUTO_YES "--yes///Assumes yes for all yes-no questions" "$@" + args_or_ask -h "$HH" -n -F USE_NO_PROFILE "--none///Assumes the global profile" "$@" + args_or_ask -h "$HH" -n -F AUTO_SUB "--autosub///Automatically creates the sub-profile if it doesn't exist" "$@" || + args_or_ask -h "$HH" -n -F AUTO_SUB "-a///Automatically creates the sub-profile if it doesn't exist" "$@" + args_or_ask -h "$HH" -F USE_CURRENT_DIR "--local///Uses the local dir as based app dir" "$@" + args_or_ask -h "$HH" -a -p -n -- PAR_USE_PROFILE '1///profile name (or "." for current profile or --none)' "$@" + args_or_ask -h "$HH" -a -p -n -- PAR_USE_PROFILE_SUB '2///optional sub-profile (or .. for a list of items)' "$@" + + [ "$HH" == "--cmplt" ] && { + # Additional pro use completion + if [ "$1" == "--cmplt" ]; then + echo "." + echo ".." + echo "partialname.." + else + echo ".." + echo "partialname.." + fi + } + + [ -n "$HH" ] && exit 0 + + if [ -z "$COMMAND_FILE" ]; then + local V="ENTANDO_ENT_FORCE_PROFILE_0e7e8d89_$ENTANDO_TTY_QUALIFIER" + [ -n "${!V}" ] && { + local MSG="This SHELL SESSION is currently bound to a specific profile, " + MSG+="in order to use another profile during this session you need to source-run this command" + _log_e "$MSG" + FATAL "TTY_PRO_LOCKED" + } + fi + + if [ "$MODE" == "use" ]; then + kubectl_mode --reset-mem + THIS_PROFILE="" PROFILE_ORIGIN="" + use_profile + fix_profile + else + _pp PAR_USE_PROFILE PAR_USE_PROFILE_SUB + if [[ -n "$PAR_USE_PROFILE" && "$PAR_USE_PROFILE" != *".." && -z "$PAR_USE_PROFILE_SUB" ]]; then + PAR_USE_PROFILE_SUB=".." + fi + list_profile + fi +} + setup_curr_profile() { HH="$(parse_help_option "$@")" args_or_ask -h "$HH" ENTANDO_APPNAME "--appname/ext_ic_id/$PROFILE/%sp EntandoApp name" "$@" && { @@ -137,6 +171,7 @@ setup_curr_profile() { [ -n "$HH" ] && exit 0 } +# Fix for old code fix_profile() { if [ -z "$THIS_PROFILE" ]; then THIS_PROFILE="$DESIGNATED_PROFILE" @@ -146,25 +181,13 @@ fix_profile() { use_profile() { # shellcheck disable=SC2034 - local profile - local apps_base_dir - - if $USE_CURRENT_DIR; then - apps_base_dir="$ENTANDO_CALLER_PWD/.ent/profiles" - else - apps_base_dir="$ENTANDO_PROFILES" - fi - - $USE_NO_PROFILE && profile="--none" - args_or_ask -h "$HH" -a -p -n -- "profile" '1///%sp profile (or --none)' "$@" - - DESIGNATED_PROFILE="" - # shellcheck disable=SC2034 - DESIGNATED_PROFILE_HOME="" - + local profile subprofile app_dir apps_base_dir + _setup_use_or_list profile subprofile app_dir apps_base_dir + if $USE_NO_PROFILE; then if [ -z "$COMMAND_FILE" ]; then save_cfg_value "DESIGNATED_PROFILE" "" "$ENTANDO_GLOBAL_CFG" + save_cfg_value "DESIGNATED_PROFILE_SUB" "" "$ENTANDO_GLOBAL_CFG" save_cfg_value "DESIGNATED_PROFILE_HOME" "" "$ENTANDO_GLOBAL_CFG" activate_designated_workdir return 0 @@ -172,36 +195,26 @@ use_profile() { # shellcheck disable=SC2016 { echo "export ENTANDO_ENT_FORCE_PROFILE_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"-\"" + echo "export ENTANDO_ENT_FORCE_PROFILE_SUB_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"-\"" echo "export ENTANDO_ENT_FORCE_PROFILE_HOME_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"-\"" echo 'if [ "$1" = "--full" ]; then' echo " DESIGNATED_PROFILE=\"\"" + echo " DESIGNATED_PROFILE_SUB=\"\"" echo " DESIGNATED_PROFILE_HOME=\"\"" echo 'fi' } >>"$COMMAND_FILE" fi else ( - # shellcheck disable=SC2030 - __cd "$apps_base_dir" - # shellcheck disable=SC2035 - - local tmp_profile - select_profile tmp_profile "$profile" - - local app_dir="$apps_base_dir/$tmp_profile" - - if [ ! -d "$app_dir" ]; then - _log_w "Application profile \"$tmp_profile\" not found" - $AUTO_NO && EXIT_UE "Auto Interrupted due to auto-no" - $AUTO_YES || ask "Should I create it?" || EXIT_UE "User interrupted" - new_profile "$tmp_profile" - fi + $AUTO_YES && O=--auto-accept || O=--no-auto-accept + select_profile_items $O tmp_profile tmp_subprofile "$profile" "$subprofile" "$AUTO_SUB" # shellcheck disable=SC2030 if [ -n "$COMMAND_FILE" ]; then - _activate_command_in_source_mode "${tmp_profile}" "${app_dir}" + _activate_command_in_source_mode "${tmp_profile}" "${app_dir}" "$tmp_subprofile" else save_cfg_value "DESIGNATED_PROFILE" "${tmp_profile}" "$ENTANDO_GLOBAL_CFG" + save_cfg_value "DESIGNATED_PROFILE_SUB" "${tmp_subprofile}" "$ENTANDO_GLOBAL_CFG" save_cfg_value "DESIGNATED_PROFILE_HOME" "${app_dir}" "$ENTANDO_GLOBAL_CFG" fi true @@ -209,12 +222,18 @@ use_profile() { # shellcheck disable=SC2031 disable=SC1090 { + DESIGNATED_PROFILE="" + DESIGNATED_PROFILE_SUB="" + # shellcheck disable=SC2034 + DESIGNATED_PROFILE_HOME="" + reload_cfg "$ENTANDO_GLOBAL_CFG" + if [ -n "$COMMAND_FILE" ]; then . "$COMMAND_FILE" --full activate_designated_workdir --temporary else - set_curr_profile "$DESIGNATED_PROFILE" "$DESIGNATED_PROFILE_HOME" + set_curr_profile "$DESIGNATED_PROFILE" "$DESIGNATED_PROFILE_HOME" "$DESIGNATED_PROFILE_SUB" activate_designated_workdir fi } @@ -230,25 +249,103 @@ use_profile() { fi } +list_profile() { + local profile subprofile app_dir apps_base_dir + _setup_use_or_list profile subprofile app_dir apps_base_dir + + $AUTO_YES && O=--auto-accept || O=--no-auto-accept + select_profile_items $O tmp_profile tmp_subprofile "$profile" "$subprofile" "$AUTO_SUB" +} + +_setup_use_or_list() { + # shellcheck disable=SC2034 + if [[ "$PAR_USE_PROFILE" == "." ]]; then + local _tmp_profile="$DESIGNATED_PROFILE" + else + local _tmp_profile="$PAR_USE_PROFILE" + fi + local _tmp_subprofile="$PAR_USE_PROFILE_SUB" + local _tmp_apps_base_dir + + if $USE_CURRENT_DIR; then + _tmp_apps_base_dir="$ENTANDO_CALLER_PWD/.ent/profiles" + else + _tmp_apps_base_dir="$ENTANDO_PROFILES" + fi + + local _tmp_app_dir + if $USE_CURRENT_DIR; then + _tmp_app_dir="$ENTANDO_CALLER_PWD/.ent/profiles/$DESIGNATED_PROFILE" + else + _tmp_app_dir="$ENTANDO_PROFILES/$DESIGNATED_PROFILE" + fi + + _set_var "$1" "$_tmp_profile" + _set_var "$2" "$_tmp_subprofile" + _set_var "$3" "$_tmp_app_dir" + _set_var "$4" "$_tmp_apps_base_dir" +} + +select_profile_items() { + # shellcheck disable=SC2030 + __cd "$apps_base_dir" + # shellcheck disable=SC2035 + + local O="$1" + local var1="$2" + local var2="$3" + local profile="$4" + local subprofile="$5" + local autosub="${6:-false}" + + # PROFILE + + local t_tmp_profile + select_profile_item $O t_tmp_profile "profile" "$profile" "" + [[ -z "$t_tmp_profile" && "$autosub" != "true" ]] && FATAL "The profile was not found" + + # SUBPROFILE + + local t_tmp_subprofile + if [ -n "$subprofile" ]; then + if "$autosub" && [ "$subprofile" != ".." ]; then + select_profile_item $O --exact t_tmp_subprofile "subprofile" "$subprofile" "$t_tmp_profile" + else + select_profile_item $O t_tmp_subprofile "subprofile" "$subprofile" "$t_tmp_profile" + fi + + if [ -z "$t_tmp_subprofile" ]; then + if $autosub; then + t_tmp_subprofile="$subprofile" + else + FATAL "The sub-profile was not found" + fi + fi + else + t_tmp_subprofile="" + fi + + _set_var "$var1" "$t_tmp_profile" + _set_var "$var2" "$t_tmp_subprofile" +} + _activate_command_in_source_mode() { # shellcheck disable=SC2016 { - local profile_name="$1" profile_dir="$2" + local profile_name="$1" profile_dir="$2" subprofile_name="$3" echo "export ENTANDO_ENT_FORCE_PROFILE_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"${profile_name}\"" + echo "export ENTANDO_ENT_FORCE_PROFILE_SUB_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"${subprofile_name}\"" echo "export ENTANDO_ENT_FORCE_PROFILE_HOME_0e7e8d89_$ENTANDO_TTY_QUALIFIER=\"${profile_dir}\"" echo 'if [ "$1" = "--full" ]; then' echo " DESIGNATED_PROFILE=\"${profile_name}\"" + echo " DESIGNATED_PROFILE_SUB=\"${subprofile_name}\"" echo " DESIGNATED_PROFILE_HOME=\"${profile_dir}\"" echo 'fi' } >>"$COMMAND_FILE" } _list_profiles() { - local filter - HH="$(parse_help_option "$@")" - show_help_option "$HH" - args_or_ask -h "$HH" -n -a -- filter '1///filter' "$@" - [ -n "$HH" ] && exit 0 + local filter="$1" if [ -n "$filter" ]; then # shellcheck disable=SC2010 @@ -259,27 +356,62 @@ _list_profiles() { fi } -select_profile() { +_list_sub_profiles() { + local filter="$1" + local profile="$2" + + if [ -n "$filter" ]; then + # shellcheck disable=SC2010 + ls -a -- "$profile/w/" | grep ".cfg$" | sed "s/.cfg$//" | sed "s/^.//" | grep "$filter" + else + # shellcheck disable=SC2012 + ls -a -- "$profile/w/" | grep ".cfg$" | sed "s/.cfg$//" | sed "s/^.//" + fi +} + +select_profile_item() { + local AUTOA=false; + [ "$1" = "--auto-accept" ] && { AUTOA=true; shift; } + [ "$1" = "--no-auto-accept" ] && shift; + local EXACT=false;[ "$1" = "--exact" ] && { EXACT=true; shift; } local res_var="$1" shift - local profile="$1" + local type="$1" shift + local pattern="$1" dotdot=false + [ "$pattern" = ".." ] && { pattern=""; dotdot=true; } + shift + local parent="$1" + [ -n "$1" ] && shift + local LST - stdin_to_arr $'\n\r' LST < <(list_profiles "$profile") - - if [ "${#LST[@]}" -le 0 ]; then - [ -n "$profile" ] && FATAL "No profile was found with the provided data" - FATAL "No profile was found" + + stdin_to_arr $'\n\r' LST < <(list_profile_items "$type" "$pattern" "$parent") + + if [[ "${#LST[@]}" -le 0 || -z "${LST[0]}" ]] && [[ "$dotdot" == "false" ]]; then + # No match + _tmp_result="" + return 1 fi # shellcheck disable=SC2076 disable=SC2199 - if [[ ! " ${LST[@]} " =~ " ${profile} " ]]; then - select_one "Application Profile" "${LST[@]}" + if [[ " ${LST[@]} " =~ " ${pattern} " && "$dotdot" == "false" ]]; then + # Exact match + auto-accept + _tmp_result="$pattern" + elif $EXACT; then + _tmp_result="" + else + if $AUTOA; then + select_one -s "$type" "${LST[@]}" + else + select_one "$type" "${LST[@]}" + fi + # shellcheck disable=SC2154 - profile="$select_one_res_alt" + _tmp_result="$select_one_res_alt" fi - _set_var "$res_var" "$profile" + _set_var "$res_var" "$_tmp_result" } parse_basic_profile_args() { @@ -327,7 +459,7 @@ new_profile() { args_or_ask -h "$HH" -a PROFILE "1/ext_ic_id//%sp profile name" "$@" args_or_ask -h "$HH" -n -F AUTO_USE \ "--and-use//true/%sp if true (default) automatically switches to the new profile" "$@" - args_or_ask -h "$HH" -F USE_CURRENT_DIR "-l///%sp uses the local dir as based app dir" "$@" + args_or_ask -h "$HH" -F USE_CURRENT_DIR "--local///%sp uses the local dir as based app dir" "$@" parse_basic_profile_args 2 "$@" [ -n "$HH" ] && exit 0 # ~~~~~~~~~~~~~~ @@ -393,48 +525,55 @@ print_first_use_readme() { } delete_profile() { - # shellcheck disable=SC2034 - local profile - local apps_base_dir - if $USE_CURRENT_DIR; then - apps_base_dir="$ENTANDO_CALLER_PWD/.ent/profiles" - else - apps_base_dir="$ENTANDO_PROFILES" - fi - - local PROFILE - __cd "$apps_base_dir" - # shellcheck disable=SC2035 - map-from-stdin "profile" $'\n\r' < <(ls -d * 2>/dev/null) - args_or_ask_from_list "profile" -m -a -h "$HH" PROFILE 1 "any" \ - "profile" "Select the profile" "$@" - [ ! -d "$PROFILE" ] && FATAL "Unable to select given profile: not found" - [ ! -d "$PROFILE/w" ] && FATAL "Invalid profile dir" - + local profile subprofile app_dir apps_base_dir + _setup_use_or_list profile subprofile app_dir apps_base_dir + + local PROFILE SUBPROFILE + select_profile_items --no-auto-accept PROFILE SUBPROFILE "$profile" "$subprofile" + + if [ -z "$subprofile" ]; then ( - _log_w "Application profile \"$PROFILE\" found" + _log_w "Profile \"$PROFILE\" found" $AUTO_YES || ask "Should I really delete it?" || EXIT_UE "User interrupted" rm -rf "$PROFILE" - _log_i "Application profile \"$PROFILE\" deleted" + _log_i "Profile \"$PROFILE\" deleted" save_cfg_value "DESIGNATED_PROFILE" "" "$ENTANDO_GLOBAL_CFG" + save_cfg_value "DESIGNATED_PROFILE_SUB" "" "$ENTANDO_GLOBAL_CFG" save_cfg_value "DESIGNATED_PROFILE_HOME" "" "$ENTANDO_GLOBAL_CFG" true ) && { + DESIGNATED_PROFILE="" DESIGNATED_PROFILE_SUB="" DESIGNATED_PROFILE_HOME="" reload_cfg "$ENTANDO_GLOBAL_CFG" + if [ "$PROFILE" = "$THIS_APP_PROFILE" ]; then THIS_APP_PROFILE="" save_cfg_value "DESIGNATED_APP_PROFILE" "" "$ENTANDO_GLOBAL_CFG" + save_cfg_value "DESIGNATED_APP_PROFILE_SUB" "" "$ENTANDO_GLOBAL_CFG" save_cfg_value "DESIGNATED_APP_PROFILE_HOME" "" "$ENTANDO_GLOBAL_CFG" fi print_current_profile_info } + else + ( + DESIGNATED_PROFILE="$PROFILE" + DESIGNATED_PROFILE_SUB="$SUBPROFILE" + setup_cfg_file_location --required + _log_w "Sub-Profile \"$SUBPROFILE\" found" + $AUTO_YES || ask "Should I really delete it?" || EXIT_UE "User interrupted" + rm "$CFG_FILE" && _log_i "Sub-Profile \"$SUBPROFILE\" deleted, back to the basic profile" + ) + save_cfg_value "DESIGNATED_PROFILE_SUB" "" "$ENTANDO_GLOBAL_CFG" + + DESIGNATED_PROFILE="" DESIGNATED_PROFILE_SUB="" DESIGNATED_PROFILE_HOME="" + reload_cfg "$ENTANDO_GLOBAL_CFG" + fi } -list_profiles() { +list_profile_items() { # shellcheck disable=SC2034 - local profile + if $USE_CURRENT_DIR; then apps_base_dir="$ENTANDO_CALLER_PWD/.ent/profiles" else @@ -443,7 +582,13 @@ list_profiles() { ( __cd "$apps_base_dir" - _list_profiles "$@" + if [ "$1" != "subprofile" ]; then + shift + _list_profiles "$@" + else + shift + _list_sub_profiles "$@" + fi ) } diff --git a/prj/.shpkg b/prj/.shpkg old mode 100644 new mode 100755 diff --git a/prj/run-shellcheck.sh b/prj/run-shellcheck.sh index 741c3836..c364262e 100755 --- a/prj/run-shellcheck.sh +++ b/prj/run-shellcheck.sh @@ -48,4 +48,4 @@ _xdev.ensure-project-type "sh" XDEV_SRC=$(_xdev.get-config "XDEV_SRC") XDEV_SHELLCHECK_IGNORE=$(_xdev.get-config "XDEV_SHELLCHECK_IGNORE") -RUN"$@" +RUN "$@" diff --git a/prj/xdev-lib.sh b/prj/xdev-lib.sh old mode 100644 new mode 100755 diff --git a/res/base-mfe.jdlt b/res/base-mfe.jdlt old mode 100644 new mode 100755 diff --git a/res/demo-project.jdlt b/res/demo-project.jdlt old mode 100644 new mode 100755 diff --git a/res/entando.png b/res/entando.png old mode 100644 new mode 100755 diff --git a/res/test-bundle.tar.gz b/res/test-bundle.tar.gz old mode 100644 new mode 100755 diff --git a/s/_base.sh b/s/_base.sh old mode 100644 new mode 100755 index 255f79bf..ccd23e95 --- a/s/_base.sh +++ b/s/_base.sh @@ -136,6 +136,27 @@ function print_current_function_name() { echo "${1}${FUNCNAME[1]}${2}" } +setup_cfg_file_location() { + + if [[ -z "$DESIGNATED_PROFILE" || "$DESIGNATED_PROFILE" = "-" ]]; then + CFG_FILE="" + else + local base_cfg_file="$ENT_WORK_DIR/.cfg" + if [[ -z "$DESIGNATED_PROFILE_SUB" || "$DESIGNATED_PROFILE_SUB" = "-" ]]; then + # shellcheck disable=SC2034 + CFG_FILE="$base_cfg_file" + [ ! -f "$CFG_FILE" ] && FATAL "Unable to find the given profile" + else + # shellcheck disable=SC2034 + CFG_FILE="${ENT_WORK_DIR}/.${DESIGNATED_PROFILE_SUB}.cfg" + if [ ! -f "$CFG_FILE" ]; then + [ "$1" == "--required" ] && FATAL "Unable to find the given profile or sub-profile" + cp "$base_cfg_file" "$CFG_FILE" + fi + fi + fi +} + # activates the default workdir of the current ent installation # # the default workdir is not related t any profile @@ -147,9 +168,8 @@ activate_ent_default_workdir() { PROFILE_ORIGIN="" DESIGNATED_PROFILE_HOME="" ENT_WORK_DIR="$ENTANDO_ENT_HOME/w" - # shellcheck disable=SC2034 - CFG_FILE="$ENT_WORK_DIR/.cfg" mkdir -p "$ENT_WORK_DIR" + setup_cfg_file_location fi } @@ -161,14 +181,14 @@ activate_application_workdir() { if [ -n "$DESIGNATED_PROFILE" ]; then if [ -d "$DESIGNATED_PROFILE_HOME/w" ]; then ENT_WORK_DIR="$DESIGNATED_PROFILE_HOME/w" - # shellcheck disable=SC2034 - CFG_FILE="$ENT_WORK_DIR/.cfg" + mkdir -p "$ENT_WORK_DIR" + setup_cfg_file_location return 0 else _log_e \ "Unable to load the profile \"$DESIGNATED_PROFILE\", falling back to the default profile" - DESIGNATED_PROFILE_HOME="" DESIGNATED_PROFILE="" + DESIGNATED_PROFILE_SUB="" return 1 fi fi @@ -180,11 +200,13 @@ activate_designated_workdir() { TEMPORARY=false [ "$1" = "--temporary" ] && TEMPORARY=true ! $TEMPORARY && reload_cfg "$ENTANDO_GLOBAL_CFG" + if [[ -n "$DESIGNATED_PROFILE" && "$DESIGNATED_PROFILE" != "-" ]]; then activate_application_workdir else activate_ent_default_workdir fi + ! $TEMPORARY && save_cfg_value "THIS_PROFILE" "${DESIGNATED_PROFILE}" ENT_KUBECTL_CMD="" ENABLE_AUTOLOGIN="" @@ -197,11 +219,19 @@ set_curr_profile() { [ -z "$1" ] && _FATAL "Illegal profile name detected" DESIGNATED_PROFILE="$1" DESIGNATED_PROFILE_HOME="$2" + DESIGNATED_PROFILE_SUB="$3" + [ -z "$DESIGNATED_PROFILE_HOME" ] && DESIGNATED_PROFILE_HOME="$ENTANDO_PROFILES/$DESIGNATED_PROFILE" - ! $TEMP && { + + ENT_WORK_DIR="$DESIGNATED_PROFILE_HOME/w" + + if ! $TEMP; then save_cfg_value "DESIGNATED_PROFILE" "$DESIGNATED_PROFILE" "$ENTANDO_GLOBAL_CFG" save_cfg_value "DESIGNATED_PROFILE_HOME" "$DESIGNATED_PROFILE_HOME" "$ENTANDO_GLOBAL_CFG" - } + save_cfg_value "DESIGNATED_PROFILE_SUB" "$DESIGNATED_PROFILE_SUB" "$ENTANDO_GLOBAL_CFG" + else + setup_cfg_file_location --required + fi } # ---------------------------------------------------------------------------------------------------------------------- @@ -385,19 +415,36 @@ parse_global_args() { shift;((ENTANDO_CONSUMED_ARGS++)) ENTANDO_ENT_FORCE_PROFILE="--none" ;; + "--profile="*) + ENTANDO_ENT_FORCE_PROFILE="${1:10}" + shift;((ENTANDO_CONSUMED_ARGS++)) + ;; "-p" | "--profile") shift;((ENTANDO_CONSUMED_ARGS++)) ENTANDO_ENT_FORCE_PROFILE="$1" shift;((ENTANDO_CONSUMED_ARGS++)) ;; + "--sub-profile="*) + ENTANDO_ENT_FORCE_PROFILE_SUB="${1:14}" + shift;((ENTANDO_CONSUMED_ARGS++)) + ;; + "--sub-profile") + shift;((ENTANDO_CONSUMED_ARGS++)) + ENTANDO_ENT_FORCE_PROFILE_SUB="$1" + shift;((ENTANDO_CONSUMED_ARGS++)) + ;; "--color") shift;((ENTANDO_CONSUMED_ARGS++)) ENTANDO_CLI_FORCE_COLORS=true ;; - "-d" | "--debug") + "--debug") shift;((ENTANDO_CONSUMED_ARGS++)) ENTANDO_ENT_DEBUG=true ;; + "--trace") + shift;((ENTANDO_CONSUMED_ARGS++)) + ENTANDO_ENT_TRACE=true + ;; *) break ;; @@ -405,7 +452,9 @@ parse_global_args() { done export ENTANDO_ENT_DEBUG + export ENTANDO_ENT_TRACE export ENTANDO_ENT_FORCE_PROFILE + export ENTANDO_ENT_FORCE_PROFILE_SUB } # ---------------------------------------------------------------------------------------------------------------------- @@ -430,18 +479,22 @@ parse_global_args "$@" shift "$ENTANDO_CONSUMED_ARGS" case "$ENTANDO_ENT_FORCE_PROFILE" in - "--none") DESIGNATED_PROFILE="";DESIGNATED_PROFILE_HOME="";; + "--none") DESIGNATED_PROFILE="";DESIGNATED_PROFILE_SUB="";DESIGNATED_PROFILE_HOME="";; "") ;; - *) set_curr_profile --temporary "$ENTANDO_ENT_FORCE_PROFILE";; + *) set_curr_profile --temporary "$ENTANDO_ENT_FORCE_PROFILE" "" "$ENTANDO_ENT_FORCE_PROFILE_SUB";; esac -if [ -n "$DESIGNATED_PROFILE" ]; then + if [[ -n "$DESIGNATED_PROFILE_SUB" && "$DESIGNATED_PROFILE_SUB" != "-" ]]; then + if ! assert_ext_ic_id "" "$DESIGNATED_PROFILE_SUB" "silent"; then + FATAL "Illegal value provided in environment var DESIGNATED_PROFILE_SUB, please check your gobal config: \"$ENTANDO_GLOBAL_CFG\"" + fi + fi + if assert_ext_ic_id "" "$DESIGNATED_PROFILE" "silent"; then DESIGNATED_PROFILE_HOME="$ENTANDO_PROFILES/$DESIGNATED_PROFILE" else - FATAL "Illegal value provided in environment var DESIGNATED_PROFILE" + FATAL "Illegal value provided in environment var DESIGNATED_PROFILE, please check your gobal config: \"$ENTANDO_GLOBAL_CFG\"" fi -fi if [ -n "$DESIGNATED_PROFILE" ]; then activate_application_workdir @@ -451,6 +504,7 @@ fi reload_cfg "$ENT_DEFAULT_CFG_FILE" reload_cfg + rescan-sys-env reload_cfg @@ -463,3 +517,4 @@ XU_STATUS_FILE="$ENT_WORK_DIR/.status" kubectl_update_once_options "$@" setup_kubectl + diff --git a/s/_conf.sh b/s/_conf.sh old mode 100644 new mode 100755 index ef58276c..0c99e84d --- a/s/_conf.sh +++ b/s/_conf.sh @@ -83,10 +83,11 @@ C_AUTO_VM_HOSTNAME_SUFFIX="local.entando.org" C_DEFAULT_KUBECT_VERSION="v1.23.4" -ENTANDO_CLI_DOCKER_CONFIG_PATH="$ENT_ORIGIN_WORKDIR/.entando/.docker/config.json" +ENTANDO_CLI_DOCKER_CONFIG_PATH="$ENT_CALLER_DIR/.entando/.docker/config.json" ENTANDO_OPT_OVERRIDE_HOME_VAR="true" ENTANDO_ENT_EXTENSIONS_MODULES_PATH="${ENTANDO_ENT_HOME}/bin/mod/ext" +ENTANDO_ENT_EXTENSIONS_ENABLED=true ENTANDO_CLI_FORCE_COLORS="false" ENTANDO_CLI_DEFAULT_DOCKER_REGISTRY="registry.hub.docker.com" @@ -143,6 +144,9 @@ TMP_CLI_VERSION="$( ENTANDO_MANIFEST_RELEASE="${ENTANDO_RELEASE:-"$TMP_CLI_VERSION"}" ENTANDO_RELEASE="${TMP_CLI_VERSION:-"$ENTANDO_MANIFEST_RELEASE"}" +# FLAG THAT TELLS ENTANDO_CLI TO HIDE THE PRIVATE NODEJS +ENTANDO_CLI_HIDE_PRIVATE_NODEJS="true" + # ENTANDO NPM REGISTRY DATA ENTANDO_NPM_REGISTRY_NO_SCHEMA="npm.pkg.github.com" ENTANDO_NPM_REGISTRY="https://$ENTANDO_NPM_REGISTRY_NO_SCHEMA" @@ -151,7 +155,7 @@ ENTANDO_NPM_REGISTRY="https://$ENTANDO_NPM_REGISTRY_NO_SCHEMA" # THE TOKEN HAS IN FACT NO PERMISSION BUT repository:read # it's obfuscated just to avoid false positives from security scanners ENTANDO_NPM_REGISTRY_TOKEN_FOR_ANONYMOUS_ACCESS="$( - echo -n "ZXc2Z2IwbUtWMUZ5c0g0NWxLTFBOZVBwNGJDaUk5TE9iNUw4X3BoZw==" \ + echo -n "bXl6cEw0NDFIM0NpTXJFcWs0NTlxenBUOEhRZkdiODM1SEtWX3BoZw==" \ | perl -e "use MIME::Base64; print decode_base64(<>);" \ | perl -e 'print scalar reverse(<>);' \ | tr -d '\n' | tr -d '\r' diff --git a/s/_root-helper.sh b/s/_root-helper.sh new file mode 100644 index 00000000..aa8503f0 --- /dev/null +++ b/s/_root-helper.sh @@ -0,0 +1,301 @@ +#!/bin/bash + +ent-load-extension-module() { + ( + local REPO NAME BRANCH + args_or_ask -h "$HH" -a -n -- REPO '1/git_repo//%sp repository of the module' "$@" + args_or_ask -h "$HH" -n -- NAME '--name/strict_file_name//%sp name of the module' "$@" + args_or_ask -h "$HH" -n -- BRANCH '--branch/dn//%sp branch to use instead of the default one' "$@" + end_help_parsing + + DIRNAME="$(basename "$REPO")" + [ -z "$NAME" ] && NAME="$DIRNAME" + + local EXT_DIR="${ENTANDO_ENT_HOME}/bin/mod/ext" + mkdir -p "$EXT_DIR" + __cd "$EXT_DIR" + if [[ "$PWD" = *".entando"* ]]; then + [ -d "$DIRNAME" ] && rm -rf "$DIRNAME" + git clone --depth=1 ${BRANCH:+-b "$BRANCH"} --single-branch "$REPO" + cp -p -- "$PWD/$DIRNAME/mod/"* . + else + _FATAL "Extension module cleanup: Refusing to delete a non entando-cli dir" + fi + ) +} + +which_ent() { + case "$1" in + version) echo "${ENTANDO_CLI_VERSION}"; return;; + which) echo "${ENTANDO_CLI_VERSION}";; + home) echo "$ENTANDO_ENT_HOME"; return;; + esac + + ( + echo "" + echo "---" + echo "" + + # CLI INFO + echo "## CLI:" + echo "" + __cd "$ENTANDO_ENT_HOME" + echo "- DIR: $ENTANDO_ENT_HOME" + IFS='|' read -r sha time < <(git log --pretty=format:'%H|%ci' -1) + echo "- SHA: $sha" + echo "- UPD: $time" + echo "" + + # RELEASE INFO + __cd "$(_dist_directory)" + echo "## RELEASE:" + echo "" + echo "- DIR: $PWD" + IFS='|' read -r sha time < <(git log --pretty=format:'%H|%ci' -1) + echo "- SHA: $sha" + echo "- UPD: $time" + echo "" + + ) 1>&2 +} + +handle_config_command() { + bgn_help_parsing "${BASH_SOURCE[0]}" "$@" + + args_or_ask -a -n -h "$HH" CFG_KEY "1///the config key" "$@" + args_or_ask -a -n -h "$HH" CFG_VALUE "2///the value to set" "$@" + OPT_EXPORT="" + args_or_ask -h "$HH" -f -- "--export///also export config key as variable" "$@" && { + OPT_EXPORT="-e" + } + + args_or_ask -h "$HH" -f -- '--default///selects the default ent configuration' "$@" && { + # shellcheck disable=SC2034 + CFG_FILE="$ENT_DEFAULT_CFG_FILE" + ENT_WORK_DIR="${ENTANDO_ENT_HOME}/w" + THIS_PROFILE="" + } + args_or_ask -h "$HH" -f -- '--global///selects the global ent configuration' "$@" && { + CFG_FILE="$ENTANDO_GLOBAL_CFG" + # shellcheck disable=SC2034 + ENT_WORK_DIR="${ENTANDO_ENT_HOME}/w" + THIS_PROFILE="" + } + + args_or_ask -h "$HH" -F ENTANDO_NO_OBFUSCATION '--no-obfuscation///disables the obfuscation in the effective configuration' "$@" + args_or_ask -h "$HH" -f -- '--effective///prints the effective configuration' "$@" && { + print-effective-config + return 0 + } + + args_or_ask -h "$HH" -f -- '--edit///edits the configuration' "$@" && { + _edit "$CFG_FILE" + return 0 + } + + args_or_ask -h "$HH" -f -- '--set///sets a specific configuration parameter' "$@" && { + args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" + args_or_ask -a -n -h "$HH" "CFG_VALUE" "2///%sp the value to set" "$@" + save_cfg_value $OPT_EXPORT "$CFG_KEY" "$CFG_VALUE" "$CFG_FILE" "$DO_EXPORT" + return 0 + } + + args_or_ask -h "$HH" -f -- '--del///deletes a specific configuration parameter' "$@" && { + args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" + save_cfg_value "$CFG_KEY" "" "$CFG_FILE" + return 0 + } + + args_or_ask -h "$HH" -f -- '--get///gets a specific configuration parameter' "$@" && { + args_or_ask -a -h "$HH" "CFG_KEY" "1///%sp the config key" "$@" + print_cfg_value "$CFG_KEY" "$CFG_FILE" + return 0 + } + end_help_parsing + + if [ -n "$CFG_KEY" ]; then + if [ -n "$CFG_VALUE" ]; then + save_cfg_value $OPT_EXPORT "$CFG_KEY" "$CFG_VALUE" "$CFG_FILE" + else + print_cfg_value "$CFG_KEY" "$CFG_FILE" + fi + else + print_config_file + fi +} + +print_config_file() { + if [ -n "$THIS_PROFILE" ]; then + _log_i "Configuration of the profile \"$THIS_PROFILE\" ($CFG_FILE):" 1>&2 + else + _log_i "Default configuration of the current entando distribution ($CFG_FILE):" 1>&2 + fi + + [ -f "$CFG_FILE" ] || _FATAL -s "Configuration file \"$CFG_FILE\" not found" + cat "$CFG_FILE" + print-secrets-leak-warning +} + +handle_status_config() { + if [ "$V" = "--del" ]; then + ent config --set "" + else + V="$2" + [ "$V" == "--" ] && V="$3" + if [ "$V" = "" ]; then + ent config --get "$1" + else + ent config --set "$1" "$V" + fi + fi +} + +handle_kubectl_cmd() { + if [ "$1" = "" ]; then + ent config --get "ENT_KUBECTL_CMD" + else + ent kubectl ent-set-cmd "$@" + fi +} + +upgrade_project_file() { + local N=$1 + local O=$2 + if [ -f "$O" ]; then + mkdir -p "$C_ENT_PRJ_ENT_DIR" + if [ -f "$N" ]; then + mv "$O" "$C_ENT_PRJ_ENT_DIR/$O.backup" + else + mv "$O" "$N" + fi + fi +} + +ent-trace() { + [ "$1" == "--reset" ] && { shift;CTRACE="\\"; } + KEY="$1" + if [ -z "${KEY}" ]; then + true + elif [ "${KEY:0:1}" == "-" ]; then + KEY="${KEY:1:200}" + CTRACE="${CTRACE//\\$KEY\\/\\}" + ent config --set CTRACE "${CTRACE}" + else + [ "${KEY:0:1}" == "+" ] && KEY="${KEY:1:200}" + + if [[ ! "$CTRACE" = *"\\$KEY\\"* ]]; then + CTRACE="${CTRACE}\\${KEY}\\" + fi + fi + + ent config --set CTRACE "${CTRACE}" + save_cfg_value "CTRACE" "$CTRACE" + reload_cfg + + _log_i "Current CTRACE: \"$CTRACE\"" +} + +cmplt() { + cd "$ENTANDO_ENT_HOME/bin/mod" || { + echo "Unable to enter directory $PWD/bin" + exit 99 + } + for file in ent-*; do + mod="${file//ent-/}" + echo "$mod" + done + + [ -z "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" ] && ENTANDO_ENT_EXTENSIONS_MODULES_PATH="$ENTANDO_ENT_HOME/bin/mod/ext" + if [ -d "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" ]; then + ( + cd "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" || exit 0 + for file in ent-*; do + [ -f "$file" ] && { + mod="${file//ent-/}" + echo "$mod" + } + done + ) + fi + + local topcmd+=( + "attach-vm" "detach-vm" "fix-vm-ddns" "completion" "config" "which" "version" "home" "import" "activate" + "kubectl-cmd" "reset-kubectl-mode" "status" + "attach-kubeconfig" "detach-kubeconfig" "namespace" "appname" "pkg" + "attach-kubectx" "detach-kubectx" "list-kubectx" + "bundle" "bundler" "jhipster" "shell" + ) + + for tc in "${topcmd[@]}"; do + echo "$tc" + done +} + +_ent() { + # shellcheck disable=SC1090 + "$ENTANDO_ENT_HOME/bin/ent" "$@" +} + +_source_ent() { + # shellcheck disable=SC1090 disable=SC1091 + source "$ENTANDO_ENT_HOME/bin/ent" "$@" +} + +_execute_script() { + local RV="33" + local cmd="$1";shift + local IS_HELP IS_CMPLT + args_or_ask -h "" -F IS_HELP "--help" "$@" + args_or_ask -h "" -F IS_CMPLT "--cmplt" "$@" + + if $IS_HELP || $IS_CMPLT; then + r() { cat -; }; $IS_HELP && r() { cat - 1>&2; } + { + (_execute_script_native "$@") + _execute_script_extension "$@" + RV="$?" + $IS_HELP && echo "" + } | r + RV=0 + else + _execute_script_extension "$@" + RV="$?" + [[ "$RV" != "33" && "$RV" != "34" ]] && return "$RV" + _execute_script_native "$@" + RV="$?" + fi + + return "$RV" +} + +_execute_script_extension() { + if [[ -d "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" && "$ENTANDO_ENT_EXTENSIONS_ENABLED" != "false" ]]; then + if _ent.extension-module.is-present "$cmd"; then + RV="34" + _ent.extension-module.chain-run "${cmd}" "$@" + RV="$?" # if 33 => command not found + else + RV="33" + fi + fi + + return "$RV" +} + +_execute_script_native() { + + local mod_script="${ENTANDO_ENT_HOME}/bin/mod/ent-${cmd}" + if [ -f "$mod_script" ]; then + # shellcheck disable=SC1090 + source "$mod_script" "$@" + RV="$?" + fi + + return "$RV" +} + +_shortcut_subpro() { + local pattern=${1:-..};shift + # shellcheck disable=SC1091 + source "$ENTANDO_ENT_HOME/bin/mod/ent-profile" use . "$pattern" "$@" +} diff --git a/s/attach-utils.sh b/s/attach-utils.sh old mode 100644 new mode 100755 diff --git a/s/completion.sh b/s/completion.sh old mode 100644 new mode 100755 diff --git a/s/completion.zsh b/s/completion.zsh old mode 100644 new mode 100755 diff --git a/s/currdir.cmd b/s/currdir.cmd old mode 100644 new mode 100755 diff --git a/s/ecr-utils.sh b/s/ecr-utils.sh index 0f0b0744..d7c3ae45 100644 --- a/s/ecr-utils.sh +++ b/s/ecr-utils.sh @@ -19,17 +19,16 @@ ecr-prepare-action() { app-get-main-ingresses url_scheme main_ingress ecr_ingress ignored [ -z "$main_ingress" ] && FATAL "Unable to determine the main ingress url (s1)" [ -z "$ecr_ingress" ] && FATAL "Unable to determine the ecr ingress url (s1)" - if [ -n "$url_scheme" ]; then - main_ingress="$url_scheme://$main_ingress" - else - case "$FORCE_URL_SCHEME" in + case "$FORCE_URL_SCHEME" in "http") - http-get-working-url main_ingress "http://$main_ingress" "https://$main_ingress" + url_scheme=http ;; - *) - http-get-working-url main_ingress "https://$main_ingress" "http://$main_ingress" + "https") + url_scheme="https" ;; - esac + esac + if [ -n "$url_scheme" ]; then + main_ingress="$url_scheme://$main_ingress" fi [ -z "$main_ingress" ] && FATAL "Unable to determine the main ingress url (s2)" http-get-url-scheme url_scheme "$main_ingress" @@ -72,7 +71,7 @@ ecr-bundle-action() { [ -n "$action" ] && url+="/$action" local OUT="$(mktemp /tmp/ent-auto-XXXXXXXX)" - + # shellcheck disable=SC2155 if "$DEBUG"; then local ERR="$(mktemp /tmp/ent-auto-XXXXXXXX)" @@ -217,6 +216,7 @@ ecr.generate-custom-resource() { if [[ "$REPOSITORY" = "docker://"* ]]; then ecr.docker.generate-cr "${REPOSITORY:9}" else + # shellcheck disable=2086 _ent-bundler from-git \ --dry-run \ ${NAME:+--name "$NAME"} \ @@ -231,11 +231,11 @@ ecr.docker.generate-cr() { tmp="$(mktemp)" # shellcheck disable=SC2064 trap "rm \"$tmp\"" exit - - _ent-bundle generate-cr \ + + _ent-bundle generate-cr \ -f -o "$tmp" 1>&2 \ ${REPO:+--image "$REPO"} - + cat "$tmp" ) } @@ -377,7 +377,7 @@ ecr.install-bundle() { DATA+=",\"conflictStrategy\":\"$CONFLICT_STRATEGY\"" fi DATA+="}" - + local RV ecr-bundle-action RV "POST" "install" "$INGRESS_URL" "$TOKEN" "$BUNDLE_NAME" "$DATA" &>/dev/null case "$RV" in diff --git a/s/ent-extensions.sh b/s/ent-extensions.sh new file mode 100644 index 00000000..11756d02 --- /dev/null +++ b/s/ent-extensions.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +_require 's/essentials.sh' +_require 's/var-utils.sh' +_require 's/utils.sh' + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ent-load-extension-module() { + ( + local REPO NAME BRANCH + args_or_ask -h "$HH" -a -n -- REPO '1/git_repo//%sp repository of the module' "$@" + args_or_ask -h "$HH" -n -- NAME '--name/strict_file_name//%sp name of the module' "$@" + args_or_ask -h "$HH" -n -- BRANCH '--branch/dn//%sp branch to use instead of the default one' "$@" + end_help_parsing + + DIRNAME="$(basename "$REPO")" + [ -z "$NAME" ] && NAME="$DIRNAME" + + local EXT_DIR="${ENTANDO_ENT_HOME}/bin/mod/ext" + mkdir -p "$EXT_DIR" + __cd "$EXT_DIR" + if [[ "$PWD" = *".entando"* ]]; then + [ -d "$DIRNAME" ] && rm -rf "$DIRNAME" + git clone --depth=1 ${BRANCH:+-b "$BRANCH"} --single-branch "$REPO" + cp -p -- "$PWD/$DIRNAME/mod/"* . + else + _FATAL "Extension module cleanup: Refusing to delete a non entando-cli dir" + fi + ) +} diff --git a/s/essentials.sh b/s/essentials.sh old mode 100644 new mode 100755 index a36c967d..e04c5711 --- a/s/essentials.sh +++ b/s/essentials.sh @@ -149,13 +149,16 @@ local a b c d read -r a b c d <<< "$1" (${a:+"$a"}${b:+ "$b"}${c:+ "$c"}${d:+ "$d"} version --client &> /dev/null) || { - _FATAL -s 'Unable to execute "'"$1"'", please run "ent k ent-auto-align"' 1>&2 + _FATAL 'Unable to execute "'"$1"'", please run "ent k ent-auto-align"' 1>&2 } } # KUBECTL # shellcheck disable=SC2034 setup_kubectl() { + + unset -f _kubectl + [ -n "$ENT_KUBECTL_CMD" ] && { ENTANDO_KUBECTL="$ENT_KUBECTL_CMD" } @@ -184,15 +187,17 @@ CMD="$ENTANDO_KUBECTL_BASE" fi + local MOD="$1"; shift + local a b c d read -r a b c d <<< "$CMD" - if [ -z "$DESIGNATED_KUBECONFIG" ]; then + if [ -z "$DESIGNATED_KUBECONFIG" ]; then # shellcheck disable=SC2086 - _trace "kubectl" ${a:+"$a"}${b:+ "$b"}${c:+ "$c"}${d:+ "$d"} $KUBECTL_ONCE_OPTIONS "$@" + _trace "kubectl" ${a:+"$a"}${b:+ "$b"}${c:+ "$c"}${d:+ "$d"} "$MOD" $KUBECTL_ONCE_OPTIONS "$@" else # shellcheck disable=SC2086 KUBECONFIG="$DESIGNATED_KUBECONFIG" \ - _trace "kubectl" ${a:+"$a"}${b:+ "$b"}${c:+ "$c"}${d:+ "$d"} $KUBECTL_ONCE_OPTIONS "$@" + _trace "kubectl" ${a:+"$a"}${b:+ "$b"}${c:+ "$c"}${d:+ "$d"} "$MOD" $KUBECTL_ONCE_OPTIONS "$@" fi _kubectl_handle_error "$?" } @@ -201,8 +206,9 @@ _kubectl() { kubectl_must_be_ok kubectl kubectl_update_once_options "$@" + local MOD="$1"; shift # shellcheck disable=SC2086 - KUBECONFIG="$DESIGNATED_KUBECONFIG" _trace "kubectl" kubectl $KUBECTL_ONCE_OPTIONS "$@" + KUBECONFIG="$DESIGNATED_KUBECONFIG" _trace "kubectl" kubectl "$MOD" $KUBECTL_ONCE_OPTIONS "$@" _kubectl_handle_error "$?" } _kubectl-pre-sudo() { :; } @@ -215,21 +221,24 @@ _kubectl() { kubectl_must_be_ok kubectl kubectl_update_once_options "$@" + local MOD="$1"; shift # shellcheck disable=SC2086 - _trace "kubectl" kubectl $KUBECTL_ONCE_OPTIONS "$@" + _trace "kubectl" kubectl $KUBECTL_ONCE_OPTIONS "$MOD" "$@" _kubectl_handle_error "$?" } _kubectl-pre-sudo() { :; } else ENTANDO_KUBECTL_AUTO_DETECTED="BASE-KUBECTL-PRIVILEGED" + _kubectl() { kubectl_must_be_ok kubectl kubectl_update_once_options "$@" + local MOD="$1"; shift # shellcheck disable=SC2086 if $ENT_KUBECTL_NO_AUTO_SUDO; then - _trace "kubectl" kubectl $KUBECTL_ONCE_OPTIONS "$@" + _trace "kubectl" kubectl "$MOD" $KUBECTL_ONCE_OPTIONS "$@" else - _trace "kubectl" sudo kubectl $KUBECTL_ONCE_OPTIONS "$@" + _trace "kubectl" sudo kubectl "$MOD" $KUBECTL_ONCE_OPTIONS "$@" fi _kubectl_handle_error "$?" } diff --git a/s/essentials_test.sh b/s/essentials_test.sh old mode 100644 new mode 100755 diff --git a/s/kube-utils.sh b/s/kube-utils.sh old mode 100644 new mode 100755 diff --git a/s/logger.sh b/s/logger.sh old mode 100644 new mode 100755 index 3f6783aa..8b0f105f --- a/s/logger.sh +++ b/s/logger.sh @@ -33,19 +33,19 @@ _log_e() { } _log_w() { - __log "W" "[W]" 0 "$@" + __log "W" "[W]" 0 "$@" 1>&2 } _log() { - __log "T" "[T]" 0 "$@" + __log "T" "[T]" 0 "$@" 1>&2 } _log_i() { - __log "I" "[I]" 0 "$@" + __log "I" "[I]" 0 "$@" 1>&2 } _log_d() { - __log "D" "[D]" 0 "$@" + __log "D" "[D]" 0 "$@" 1>&2 } _log_enable_types() { diff --git a/s/node-utils.sh b/s/node-utils.sh old mode 100644 new mode 100755 index a85a830e..f7d15807 --- a/s/node-utils.sh +++ b/s/node-utils.sh @@ -8,6 +8,7 @@ node.reset_environment() { ENT_NODE_MODS="" # the path of the node modules dir (for the current ent instance) ENT_NODE_BIN_NATIVE="" # the os-native path of the node binary (for the current ent instance) ENT_NPM_BIN_NATIVE="" # the os-native path of the npm binary (for the current ent instance) + # shellcheck disable=SC2034 NODE_PATH="" # the node base path standard variable } @@ -78,7 +79,7 @@ node.activate_environment() { # shellcheck disable=SC2031 ENT_NODE_DIR="$ENT_OPTS/node-$ENT_NODE_VER" # shellcheck disable=SC2154 - export PATH="$PATH:${sENT_NODE_DIR}bin" + export PATH="$PATH:${ENT_NODE_DIR}bin" _ent-npm-init-rc @@ -100,7 +101,8 @@ node.activate_environment() { ENT_NPM_BIN_NATIVE="${ENT_NODE_BINS}/npm" ;; esac - + + # shellcheck disable=SC2034 ENT_OPTS_ENTANDO="${ENT_OPTS}/entando" PATH="$ENT_NODE_BINS:$PATH" } @@ -275,7 +277,9 @@ _ent-entando-bundle-cli() { export ENTANDO_CLI_CRANE_BIN="$CRANE_PATH" export ENTANDO_CLI_DOCKER_CONFIG_PATH export ENTANDO_BUNDLE_CLI_BIN_NAME + export ENTANDO_CLI_HIDE_PRIVATE_NODEJS=${ENTANDO_CLI_HIDE_PRIVATE_NODEJS:-"true"} + # shellcheck disable=SC2153 ENTANDO_CLI_DEBUG="$ENTANDO_ENT_DEBUG" ENTANDO_OPT_OVERRIDE_HOME_VAR="false" \ _ent-run-internal-npm-tool "$C_ENTANDO_BUNDLE_CLI_BIN_NAME" "$@" } @@ -312,16 +316,26 @@ _ent-run-internal-npm-tool() { } _ent-npm.get-internal-tool-path() { - if $OS_WIN; then - _set_var "$1" "$ENT_NODE_BINS/${2}.cmd" + local NOOV=false;[ "$1" == "--no-override" ] && { NOOV=true; shift; } + local VN="OVERRIDE_PATH_OF_${2//-/_}" + local ITP="${!VN}" + + if [ -z "$ITP" ]; then + local ITP="$ENT_NODE_BINS/${2}" + else + $NOOV && _FATAL "Unable to proceed because the internal tool path was overridden" + fi + + if $OS_WIN && [[ $ITP != *".cmd" ]]; then + _set_var "$1" "$ITP.cmd" else - _set_var "$1" "$ENT_NODE_BINS/${2}" "$@" + _set_var "$1" "$ITP" fi } _ent-npm.delete-internal-tool-bin() { local BIN_PATH - _ent-npm.get-internal-tool-path BIN_PATH "$TOOL_NAME" + _ent-npm.get-internal-tool-path --no-override BIN_PATH "$TOOL_NAME" if [[ "$BIN_PATH" = *"/.entando/"* ]]; then rm "$BIN_PATH" else @@ -330,7 +344,7 @@ _ent-npm.delete-internal-tool-bin() { } - +# shellcheck disable=SC2120 node.command_wrapper() { CMD="$1" H() { echo -e "$2"; } @@ -344,6 +358,7 @@ node.command_wrapper() { echo "Internal error: unable to find the script source dir" 1>&2 exit } + # shellcheck disable=SC1094 . s/_base.sh cd "$WD" || _FATAL "Unable to access the current dir: $WD" diff --git a/s/pkg.sh b/s/pkg.sh old mode 100644 new mode 100755 index 09626422..fcd396bc --- a/s/pkg.sh +++ b/s/pkg.sh @@ -7,6 +7,7 @@ _ent.pkg() { bgn_help_parsing ":ENT-PKG" "$@" CMD="$1"; shift; + case "$CMD" in "list"|"ls") end_help_parsing @@ -184,11 +185,11 @@ _pkg_get() { "$url/jq-win64.exe" "jq-win64.exe" ""; ;; k9s) - var="K9S_PATH";ver="${ver:-v0.25.18}";url="https://github.com/derailed/k9s/releases/download/$ver/" + var="K9S_PATH";ver="${ver:-v0.32.7}";url="https://github.com/derailed/k9s/releases/download/$ver/" _pkg_download_and_install "$var" "k9s" "$ver" \ - "$url/k9s_Linux_x86_64.tar.gz" "k9s" "" \ - "$url/k9s_Darwin_x86_64.tar.gz" "k9s" "" \ - "$url/k9s_Windows_x86_64.tar.gz" "k9s.exe" ""; + "$url/k9s_Linux_amd64.tar.gz" "k9s" "" \ + "$url/k9s_Darwin_amd64.tar.gz" "k9s" "" \ + "$url/k9s_Windows_amd64.tar.gz" "k9s.exe" ""; ;; crane) var="CRANE_PATH";ver="${ver:-v0.9.0}";url="https://github.com/google/go-containerregistry/releases/download/$ver/" @@ -220,8 +221,11 @@ _pkg_get() { _pkg_jq() { + local RC SOE=false;[ "$1" == "--soe" ] && { SOE=true; shift; } local CMD; _pkg_get_path --strict CMD "jq" - "$CMD" "$@" + "$CMD" "$@"; RC="$?" + "$SOE" && _FATAL "jq error detected (RC=$RC)" + return "$RC" } _pkg_ok() { @@ -231,16 +235,24 @@ _pkg_ok() { _pkg_k9s() { local CMD; _pkg_get_path --strict CMD "k9s" - if [ -z "$1" ]; then + if [ "$1" == "--direct" ]; then + shift + SYS_CLI_PRE "$CMD" "$@" + else if _nn DESIGNATED_KUBECTX; then SYS_CLI_PRE "$CMD" "$@" --context="$DESIGNATED_KUBECTX" --namespace="$ENTANDO_NAMESPACE" elif _nn DESIGNATED_KUBECONFIG; then - SYS_CLI_PRE "$CMD" "$@" --kubeconfig="$DESIGNATED_KUBECONFIG" --namespace="$ENTANDO_NAMESPACE" + stdin_to_arr $'\n\r' ARR < <(yq '.contexts[].name' < "$DESIGNATED_KUBECONFIG") + select_one -s "CONTEXT" "${ARR[@]}" + # shellcheck disable=2154 + SELECTED_CONTEXT="$select_one_res_alt" + SYS_CLI_PRE "$CMD" "$@" \ + --kubeconfig="$DESIGNATED_KUBECONFIG" \ + --context="$SELECTED_CONTEXT" \ + --namespace="$ENTANDO_NAMESPACE" else SYS_CLI_PRE "$CMD" "$@" --namespace="$ENTANDO_NAMESPACE" fi - else - SYS_CLI_PRE "$CMD" "$@" fi } diff --git a/s/pkg_test.sh b/s/pkg_test.sh old mode 100644 new mode 100755 diff --git a/s/quickstart-helper.sh b/s/quickstart-helper.sh index 2552a8d8..331d0eda 100755 --- a/s/quickstart-helper.sh +++ b/s/quickstart-helper.sh @@ -62,7 +62,7 @@ debug_trace_vars() { if [[ "$ENTANDO_DEBUG" -gt 0 || "$1" == "-f" ]]; then _pp \ ENTANDO_RELEASE ENTANDO_RELEASES_FILES_STRUCTURE ENTANDO_CLI_VERSION \ - DESIGNATED_PROFILE DESIGNATED_KUBECONFIG DESIGNATED_DESIGNATED_KUBECTX \ + DESIGNATED_PROFILE DESIGNATED_PROFILE_SUB DESIGNATED_KUBECONFIG DESIGNATED_DESIGNATED_KUBECTX \ ENTANDO_NAMESPACE ENTANDO_APPNAME \ ENTANDO_STANDARD_QUICKSTART ENTANDO_PRE_EXISTING K8S_TEMPLATE \ ADDR VM_OPT WITH_HOSTNAME WITH_SINGLE_HOSTNAME \ diff --git a/s/quickstart-mocks.sh b/s/quickstart-mocks.sh old mode 100644 new mode 100755 diff --git a/s/quickstart-mocks_test.sh b/s/quickstart-mocks_test.sh old mode 100644 new mode 100755 diff --git a/s/sys-utils.sh b/s/sys-utils.sh old mode 100644 new mode 100755 index c0af9009..1e18eabf --- a/s/sys-utils.sh +++ b/s/sys-utils.sh @@ -276,6 +276,7 @@ win_convert_existing_posix_path_to_win_path() { RES="$("$ENTANDO_ENT_HOME/s/currdir.cmd" | sed 's/\\/\\\\/g')" [[ -z "$RES" ]] && _FATAL "Error converting \"$1\" to windows path" if [[ "$1" =~ ^.*/$ ]]; then + # shellcheck disable=SC2028 echo "$RES\\\\" else echo "$RES" @@ -456,10 +457,31 @@ _strip_colors() { _trace() { local trace_id="$1"; shift # shellcheck disable=SC2076 - [[ " $CTRACE " =~ " $trace_id " ]] && debug-print "$*" + if [[ " $CTRACE " =~ ":$trace_id:" ]]; then + debug-print "$*" 2>&1 | _trace_obfuscate 1>&2 + _trace_obfuscate --reset + fi "$@" } +_trace_obfuscate() { + if [ "$1" = "--reset" ]; then + ENTANDO_TRACE_OBFUSCATE="" + elif [ -z "$1" ]; then + if [ -n "$ENTANDO_TRACE_OBFUSCATE" ]; then + cat - | sed -E $'s\005'"${ENTANDO_TRACE_OBFUSCATE}"$'\005XXXXXXXX\005g' - + else + cat - + fi + else + if [ -z "$ENTANDO_TRACE_OBFUSCATE" ]; then + ENTANDO_TRACE_OBFUSCATE="$1" + else + ENTANDO_TRACE_OBFUSCATE+="|$1" + fi + fi +} + print_hr() { if "$SYS_IS_STDIN_A_TTY"; then printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | _perl_sed "s/ /${1:-~}/g" @@ -552,25 +574,55 @@ _ent.extension-modules.list() { ( cd "$ENTANDO_ENT_EXTENSIONS_MODULES_PATH" || exit 0 # shellcheck disable=SC2010 - ls ent-* -p 2>/dev/null | grep -v / | sed 's/^ent-//' + find . -type f | grep "^./[^/]*/mod/ent-[^.]*" | sed 's/^\.\///' ) fi } _ent.extension-module.is-present() { local module="$1";shift; - local mod_script="${ENTANDO_ENT_EXTENSIONS_MODULES_PATH}/ent-${module}" - [ -f "$mod_script" ] + found="$(_ent.extension-modules.list 2>/dev/null | grep "/ent-${module}$")" + [ -n "$found" ] } +_ent.extension-module.chain-run() { + local module_to_run="$1";shift; + local IS_HELP=false IS_CMPLT=false + local FINAL_RES=34 + local MODULES + + args_or_ask -h "" -F IS_HELP "--help" "$@" + args_or_ask -h "" -F IS_CMPLT "--cmplt" "$@" + + stdin_to_arr $'\n\r' MODULES < <(_ent.extension-modules.list) + for module in "${MODULES[@]}"; do + if [[ "$module" = *"/ent-$module_to_run" ]]; then + $IS_HELP && { + echo "" + print_fullsize_hbar + echo -e "> Additional commands from extension [${module/\/mod\///}]\n" + } 1>&2 + _ent.extension-module.execute "$module" "$@" + RV="$?" + [[ "$RV" != "33" && "$RV" != "34" ]] && FINAL_RES="$RV" && ! $IS_HELP && ! $IS_CMPLT && break + fi + done + + return "$FINAL_RES" +} + + _ent.extension-module.execute() { ( - local module="$1";shift; - local mod_script="${ENTANDO_ENT_EXTENSIONS_MODULES_PATH}/ent-${module}" - [ ! -f "$mod_script" ] && _FATAL "unable to find script \"$mod_script\" of extension module \"$module\"" + local module_rel_path="$1";shift; + local mod_script="${ENTANDO_ENT_EXTENSIONS_MODULES_PATH}/${module_rel_path}" + [ ! -f "$mod_script" ] && _FATAL "unable to access script \"$mod_script\"" # shellcheck disable=SC2034 - ENTANDO_CLI_MODULE_NAME="$module" - RUN() { _FATAL "unable to load extension module \"$module\" from script \"$mod_script\""; } + ENTANDO_CLI_MODULE_BASE_PATH="$(dirname "$mod_script")" + ENTANDO_CLI_MODULE_NAME="${module/\/mod\///}" + RUN() { _FATAL "unable to load extension module \"$ENTANDO_CLI_MODULE_NAME\" from script \"$mod_script\""; } + # shellcheck disable=SC2164 + cd "$ENTANDO_CLI_MODULE_BASE_PATH/.." # shellcheck disable=SC1090 source "$mod_script" RUN "$@" diff --git a/s/sys-utils_tests.sh b/s/sys-utils_tests.sh old mode 100644 new mode 100755 diff --git a/s/utils.sh b/s/utils.sh old mode 100644 new mode 100755 index 3b98755f..482ee547 --- a/s/utils.sh +++ b/s/utils.sh @@ -36,29 +36,33 @@ _sed_in_place() { # Maps: # save_cfg_value -m {MAP_NAME} {KEY} {VALUE} # +# Also export the value: +# save_cfg_value -e {KEY} {VALUE} +# save_cfg_value() { - IS_MAP=false - [ "$1" = "-m" ] && IS_MAP=true && shift + IS_EXP=false;[ "$1" = "-e" ] && IS_EXP=true && shift + IS_MAP=false;[ "$1" = "-m" ] && IS_MAP=true && shift local name="${1}" shift local value="${1}" shift - local config_file="$CFG_FILE" - [ -n "$1" ] && { - config_file="$1" - shift - } + local config_file="$CFG_FILE"; [ -n "$1" ] && { config_file="$1"; shift; } + + if [ "$(echo "$value" | wc -l)" -gt 1 ]; then + _FATAL "save_cfg_value: multiline values are not supported (variable: \"$name\")" + fi if [[ -f "$config_file" ]]; then + _sed_in_place "/^#:EXPORT:${name}/d" "$config_file" if $IS_MAP; then _sed_in_place "/^${name}__/d" "$config_file" else _sed_in_place "/^${name}=/d" "$config_file" fi fi - if [ "$(echo "$value" | wc -l)" -gt 1 ]; then - FATAL "save_cfg_value: Unsupported multiline value \"$value\" for var: \"$name\"" - fi + + # shellcheck disable=2059 + $IS_EXP && printf "#:EXPORT:${name}\n" >> "$config_file" if $IS_MAP; then local key local val @@ -69,13 +73,33 @@ save_cfg_value() { done else if [ -n "$value" ]; then - printf "$name=%s\n" "$value" >> "$config_file" + (printf "$name=%s\n" "$value" >> "$config_file") || _FATAL "save_cfg_value failed" fi fi return 0 } +# Prints a configuration value +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# $1: key strict identifier +# $2: [cfg-file] optional cfg file name; defaults to the project config file +# +print_cfg_value() { + ( + local name="${1}" + shift + local config_file="$CFG_FILE" + [ -n "$1" ] && { + config_file="$1" + shift + } + reload_cfg "$config_file" + echo "${!name}" + ) +} + + # Reloads the CFG file in a safe mode # # prevents injections and quoting escape tricks @@ -90,6 +114,7 @@ reload_cfg() { local sanitized="" # shellcheck disable=SC1097 while IFS== read -r var value; do + [[ "${var:0:9}" = "#:EXPORT:" ]] && { OPT_EXPORT="export "; continue; } [[ "$var" =~ ^# ]] && continue [[ -z "${var// }" ]] && continue if assert_ext_ic_id_with_arr "CFGVAR" "$var" "silent"; then @@ -97,13 +122,14 @@ reload_cfg() { sanitized="${sanitized/\\r/}" sanitized="${sanitized/\\n/}" if "$PRINT"; then - echo "${PRE}${var}=${sanitized}" + echo "${PRE}${OPT_EXPORT}${var}=${sanitized}" else - eval "${PRE}${var}=${sanitized}" + eval "${PRE}${OPT_EXPORT}${var}=${sanitized}" fi else _log_e "Skipped illegal var name $var" fi + OPT_EXPORT="" done <<<"$(cat "$config_file")" return 0 } @@ -208,6 +234,7 @@ ask() { [Nn]*) return 1 ;; [Qq]*) EXIT_UE "User stopped the execution" + # shellcheck disable=2317 exit 99 ;; *) @@ -226,6 +253,7 @@ NONNULL() { local O="-S 1"; [ "$1" = "-s" ] && { O="-s"; shift; } for var_name in "$@"; do local var_value="${!var_name}" + # shellcheck disable=2086 [ -z "$var_value" ] && _FATAL $O "${FUNCNAME[1]}> Variable \"$var_name\" should not be null" done } @@ -323,7 +351,9 @@ index_of_arg() { # shellcheck disable=SC2059 print_entando_banner() { { + # shellcheck disable=2028 B() { echo '\033[0;34m'; } + # shellcheck disable=2028 W() { echo '\033[0;39m'; } N='' printf "\n" @@ -414,7 +444,7 @@ select_one() { while true; do printf "%s" "$P" - set_or_ask "SELECTED" "" "" + set_or_ask SELECTED "" "" [[ "$SELECTED" == "q" ]] && EXIT_UE "User interrupted" [[ ! "$SELECTED" =~ ^[0-9]+$ ]] && continue [[ "$SELECTED" -gt 0 && "$SELECTED" -lt "$i" ]] && break @@ -854,16 +884,23 @@ stdin_to_arr() { done } +print_current_profile_indicator() { + if [ -n "$THIS_PROFILE" ]; then + echo "${THIS_PROFILE}${DESIGNATED_PROFILE_SUB:+/$DESIGNATED_PROFILE_SUB}" + else + echo "" + fi +} # shellcheck disable=SC2120 print_current_profile_info() { VERBOSE=false; [ "$1" = "-v" ] && VERBOSE=true if $VERBOSE; then - echo " - PROFILE: ${THIS_PROFILE:-}" + echo " - PROFILE: $(print_current_profile_indicator)" echo " - PROFILE HOME: ${DESIGNATED_PROFILE_HOME}" _nn PROFILE_ORIGIN && echo " - PROFILE ORIGIN: ${PROFILE_ORIGIN}" else if [ -n "$THIS_PROFILE" ]; then - _log_i "Currently using profile \"$THIS_PROFILE\"" 1>&2 + _log_i "Currently using profile \"$(print_current_profile_indicator)\"" 1>&2 else _log_i "Currently not using any profile" 1>&2 fi @@ -1108,25 +1145,32 @@ keycloak-get-token() { # shellcheck disable=SC2296 handle_forced_profile() { local pv="ENTANDO_ENT_FORCE_PROFILE_0e7e8d89_$ENTANDO_TTY_QUALIFIER"; + local pvs="ENTANDO_ENT_FORCE_PROFILE_SUB_0e7e8d89_$ENTANDO_TTY_QUALIFIER"; local phv="ENTANDO_ENT_FORCE_PROFILE_HOME_0e7e8d89_$ENTANDO_TTY_QUALIFIER"; if [[ "$1" =~ --profile=.* ]]; then args_or_ask -n -h "$HH" "ENTANDO_USE_PROFILE" "--profile/ext_ic_id//" "$@" + args_or_ask -n -h "$HH" "ENTANDO_USE_PROFILE_SUB" "--sub-profile/ext_ic_id//" "$@" _set_var "$pv" "$ENTANDO_USE_PROFILE" + _set_var "$pvs" "$ENTANDO_USE_PROFILE_SUB" _set_var "$phv" "$ENTANDO_PROFILES/$ENTANDO_USE_PROFILE" fi local pvv phvv if [ -n "$ZSH_VERSION" ]; then pvv=${(P)pv} + pvs=${(P)pvs} phvv=${(P)phv} else pvv=${!pv} + pvs=${!pvs} phvv=${!phv} fi - - if [[ -n "$pvv" && "$DESIGNATED_PROFILE" != "$pvv" ]]; then - kubectl_mode --reset-mem + + if [[ -n "$pvv" && "$DESIGNATED_PROFILE/$DESIGNATED_PROFILE_SUB" != "$pvv/$pvs" ]]; then + kubectl_mode --reset-mem DESIGNATED_PROFILE="$pvv" + DESIGNATED_PROFILE_SUB="$pvs" + THIS_PROFILE="$DESIGNATED_PROFILE" # shellcheck disable=SC2034 DESIGNATED_PROFILE_HOME="$phvv" activate_designated_workdir --temporary @@ -1441,44 +1485,109 @@ print-effective-config() { for var in ${ENTANDO_VARS_DEFAULTS[*]}; do echo "AUTO:$var=${!var}"; done } )" + + _log_i "Effective configuration for profile \"$(print_current_profile_indicator)\"" + echo "" 1>&2 - _log_i "Profile config location: \"$CFG_FILE\"" 1>&2 - _log_i "Default config location: \"$ENT_DEFAULT_CFG_FILE\"" 1>&2 - _log_i "Global config location: \"$ENTANDO_GLOBAL_CFG\"" 1>&2 + _log_i "List of configuration files in lookup order:" \ + $'\n '"1) Profile specific: \"$CFG_FILE\"" \ + $'\n '"2) Installation defaults: \"$ENT_DEFAULT_CFG_FILE\"" \ + $'\n '"3) Global settings: \"$ENTANDO_GLOBAL_CFG\"" echo "" 1>&2 + + _log_i "Variables:" + # shellcheck disable=SC2001 KEYS="$(sed 's/=.*//' <<< "$ALL" | sort -t':' -u -k2,2)" + ( reload_cfg "$ENT_DEFAULT_CFG_FILE" reload_cfg "$CFG_FILE" - for var in $KEYS; do - IFS=':' read -r tag var <<<"$var" + while IFS= read -r line; do + tag="${line%:*}" + var="${line#*:*}" + + if [[ $var = *[[:space:]]* ]]; then + opt="${var% *}" + var="${line#* *}" + if [[ "$opt" = "export" ]]; then + opt="E" + else + _log_e "Invalid variable option \"$opt\" will be ignored" + opt="-" + fi + else + opt="-" + fi + + (val="${!var}") || _FATAL "error assigning variable" + val="${!var}" if [[ "$var" != *"TOKEN"* || "$ENTANDO_NO_OBFUSCATION" = "true" ]]; then - echo "$tag> $var=$val" + echo "$tag/$opt> $var=$val" else - echo -e "$tag> $var=\033[101m**OBFUSCATED**\033[0m" + echo -e "$tag/$opt> $var=\033[101m**OBFUSCATED**\033[0m" fi - done + done <<< "$KEYS" ) - sleep 0.1 + sync_tty_streams print-secrets-leak-warning - _log_i "Hint: Use --no-obfuscation to show obfuscated values" 1>&2 - echo "" 1>&2 } print-secrets-leak-warning() { { - echo "" - echo -e "\033[101m▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\033[0;37m" - echo -e "\033[101m▒▒ /!\ W A R N I N G /!\ ▒▒\033[0;37m" - echo -e "\033[101m▒▒ This output may contain secrets, think twice before sharing it ▒▒\033[0;37m" - echo -e "\033[101m▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\033[0;37m" - echo "" + echo -e "\033[0;37m" + echo -e "\033[101m▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\033[0;37m" + echo -e '\033[101m▒▒ /!\ W A R N I N G /!\ ▒▒\033[0;37m' + echo -e "\033[101m▒▒ This output may contain secrets, think twice before sharing it ▒▒\033[0;37m" + echo -e "\033[101m▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\033[0;37m" + echo "" } 1>&2 + + ! $ENTANDO_NO_OBFUSCATION && _log_i "Hint: Use --no-obfuscation to show obfuscated values" 1>&2 + echo "" 1>&2 +} + +# simple trick to resync of the output streams, necessary in particular +# when output is capured, but not very well (e.g. some pipeline) +sync_tty_streams() { + sleep 0.1 +} + + +# runs a subshell that inherits the ent environment +run-sun-shell() { + export KUBECONFIG="$DESIGNATED_KUBECONFIG" + export NAMESPACE="$DESIGNATED_NAMESPACE" + export NS="$ENTANDO_NAMESPACE" + + k() { ent k "$@"; } + export -f k + + [ ! -d "$DESIGNATED_PROFILE_HOME/w" ] && FATAL "This command is only available when using a profile" + + mkdir -p "$DESIGNATED_PROFILE_HOME/w/shell" + if [ -n "$ENT_KUBECTL_CMD" ]; then + ENT_EFFECTIVE_KUBECTL_CMD="$ENT_KUBECTL_CMD" + cp "$ENT_KUBECTL_CMD" "$DESIGNATED_PROFILE_HOME/w/shell" + cp "$ENT_KUBECTL_CMD" "$DESIGNATED_PROFILE_HOME/w/shell/kubectl" + else + # shellcheck disable=SC2034 + ENT_EFFECTIVE_KUBECTL_CMD="kubectl" + fi + + # shellcheck disable=SC2016 disable=SC2028 + "bash" \ + --rcfile <( + echo 'source "$HOME/.bashrc"' + echo 'NORMAL="\[\e[0m\]" LIGHTGRAY="\033[0;37m" RED="\[\e[1;31m\]" GREEN="\[\e[1;32m\]"' + echo "export PATH=\"$DESIGNATED_PROFILE_HOME/w/shell:\$PATH\"" + echo 'export PS1="${RED}ENT-SHELL>${NORMAL} "' + ) \ + "$@" } diff --git a/s/utils_test.sh b/s/utils_test.sh old mode 100644 new mode 100755 index a0c7fb6c..903e1039 --- a/s/utils_test.sh +++ b/s/utils_test.sh @@ -37,24 +37,42 @@ test_index_of_arg() { #TEST:unit,lib,config test_cfg_helper() { - ( _IT "should find arguments in args list" - + ( _IT "should save single line variables" CFG_FILE="/tmp/ent-test" - save_cfg_value "XX1" "hey" "$CFG_FILE" - save_cfg_value "XX2" "hey hey" "$CFG_FILE" - save_cfg_value "XX3" "hey hey// \"/'" "$CFG_FILE" - save_cfg_value "XX4" "\" && echo \"**INJECTION ATTEMPT**\"\\ / && \"" "$CFG_FILE" - save_cfg_value "XX5" "\\\" && echo \"**INJECTION ATTEMPT2**\"\\ / && \\\"" "$CFG_FILE" + save_cfg_value "XX1" "hey" "$CFG_FILE"; _ASSERT_RC 0 + save_cfg_value "XX2" "hey hey" "$CFG_FILE"; _ASSERT_RC 0 + save_cfg_value "XX3" "hey hey// \"/'" "$CFG_FILE"; _ASSERT_RC 0 + save_cfg_value "XX4" "\" && echo \"**INJECTION ATTEMPT**\"\\ / && \"" "$CFG_FILE"; _ASSERT_RC 0 + save_cfg_value "XX5" "\\\" && echo \"**INJECTION ATTEMPT2**\"\\ / && \\\"" "$CFG_FILE"; _ASSERT_RC 0 reload_cfg "$CFG_FILE" - [ "$XX1" = "hey" ] || _FAIL - [ "$XX2" = "hey hey" ] || _FAIL - [ "$XX3" = "hey hey// \"/'" ] || _FAIL - [ "$XX3" = "hey hey// \"/'" ] || _FAIL - [ "$XX4" = "\" && echo \"**INJECTION ATTEMPT**\"\\ / && \"" ] || _FAIL - [ "$XX5" = "\\\" && echo \"**INJECTION ATTEMPT2**\"\\ / && \\\"" ] || _FAIL + _ASSERT XX1 = "hey" + _ASSERT XX2 = "hey hey" + _ASSERT XX3 = "hey hey// \"/'" + _ASSERT XX4 = "\" && echo \"**INJECTION ATTEMPT**\"\\ / && \"" + _ASSERT XX5 = "\\\" && echo \"**INJECTION ATTEMPT2**\"\\ / && \\\"" ) + + ( _IT "should support the export of specific variables" + CFG_FILE="/tmp/ent-test" + + save_cfg_value -e "XX6" "exported hey" "$CFG_FILE"; _ASSERT_RC 0 + reload_cfg "$CFG_FILE" + _ASSERT XX6 = "exported hey" + + # shellcheck disable=SC2034 + XX_FROM_SUB_SHELL="$(bash -c 'echo "$XX1$XX2$XX3$XX4$XX5$XX6"')" + _ASSERT XX_FROM_SUB_SHELL = "exported hey" + ) + + ( _IT "should reject multiline strings" + CFG_FILE="/tmp/ent-test" + + (save_cfg_value "XXML" $'HEY\nTHERE' "$CFG_FILE") 2>/dev/null + _ASSERT_RC 77 + ) + } #TEST:unit,lib,ui,mock diff --git a/s/var-utils.sh b/s/var-utils.sh old mode 100644 new mode 100755 diff --git a/s/var-utils_tests.sh b/s/var-utils_tests.sh old mode 100644 new mode 100755 diff --git a/s/verify.sh b/s/verify.sh old mode 100644 new mode 100755 index 75e94d06..3d9f6241 --- a/s/verify.sh +++ b/s/verify.sh @@ -40,18 +40,18 @@ _verify.verify-expression() { fi case "$O" in - eq) O="==";OD="TO: "; [[ "$E" -eq "$V" ]];; - ne) O="!=";OD="TO: "; [[ "$E" -ne "$V" ]];; - gt) O=">";OD="THAN:"; [[ "$E" -gt "$V" ]];; - ge) O=">=";OD="THAN:"; [[ "$E" -ge "$V" ]];; - lt) O="<";OD="THAN:"; [[ "$E" -lt "$V" ]];; - le) O="<=";OD="THAN:"; [[ "$E" -le "$V" ]];; - =|==) O="=";OD="TO: "; [[ "$E" = "$V" ]];; - !=) O="!=";OD="TO: "; [[ "$E" != "$V" ]];; - =~) O="=~";OD="TO: "; [[ "$E" =~ $V ]];; - !=~) O="=~";OD="TO: "; [[ ! "$E" =~ $V ]];; - starts-with) O="starting";OD="WITH:"; [[ "$E" = "$V"* ]];; - ends-with) O="ending";OD="WITH:"; [[ "$E" = *"$V" ]];; + eq) O="==";OD="TO: "; [[ "$E" -eq "$V" ]];; + ne) O="!=";OD="TO: "; [[ "$E" -ne "$V" ]];; + gt) O=">";OD="THAN: "; [[ "$E" -gt "$V" ]];; + ge) O=">=";OD="THAN: "; [[ "$E" -ge "$V" ]];; + lt) O="<";OD="THAN: "; [[ "$E" -lt "$V" ]];; + le) O="<=";OD="THAN: "; [[ "$E" -le "$V" ]];; + =|==) O="=";OD="TO: "; [[ "$E" = "$V" ]];; + !=) O="!=";OD="TO: "; [[ "$E" != "$V" ]];; + =~) O="=~";OD="TO: "; [[ "$E" =~ $V ]];; + !=~) O="=~";OD="TO: "; [[ ! "$E" =~ $V ]];; + starts-with) O="starting";OD="WITH: "; [[ "$E" = "$V"* ]];; + ends-with) O="ending";OD="WITH: "; [[ "$E" = *"$V" ]];; contains) O="containing";OD="THE VALUE:"; [[ "$E" = *"$V"* ]];; *) _sys.fatal -S "${SKIP}" "Unknown operator \"$O\"";; esac @@ -68,8 +68,8 @@ _verify.verify-expression() { if [ "${#E}" -gt 30 ] || [ "${#V}" -gt 30 ]; then MSG="Validation Failed" - MSG2="\n${PREFIX}Validation Failed in:\n> EXPECTED: $_tmp_ver_N" - MSG2+="\n> TO BE: $O\n> $OD $V\n\n> BUT WAS FOUND: $E" + MSG2="\n${PREFIX}Validation Failed:\n> EXPECTED: $_tmp_ver_N" + MSG2+="\n> TO BE: $O\n> $OD $V\n\n> BUT WAS FOUND: $E" else MSG="Validation Failed" MSG2="\n${PREFIX}Expected $_tmp_ver_N $O \"$V\" but instead I've found \"$E\"" diff --git a/s/verify_test.sh b/s/verify_test.sh old mode 100644 new mode 100755 diff --git a/test/init.sh b/test/init.sh old mode 100644 new mode 100755 index ad018968..e2a8b1d9 --- a/test/init.sh +++ b/test/init.sh @@ -24,7 +24,7 @@ _IT() { local ignored # shellcheck disable=SC2034 read -r ignored fn ignored <<<"$_ESS_TEST_CALLER" - _xdev.log "It $_ESS_TEST_IT" + echo "";_xdev.log "It $_ESS_TEST_IT" _ESS_SILENCE_ERRORS=false _ESS_IGNORE_EXITCODE=true diff --git a/test/integration/test-int-bundle.sh b/test/integration/test-int-bundle.sh old mode 100644 new mode 100755 diff --git a/test/integration/test-int-profiles.sh b/test/integration/test-int-profiles.sh new file mode 100644 index 00000000..3021c749 --- /dev/null +++ b/test/integration/test-int-profiles.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +XDEV_TEST.BEFORE_FILE() { + export TEST_PROFILE="ent-integration-tests" +} + +#TEST:integration,profile +test_profile_use() { + + _test_profile.cleanup + + ( _IT "should create and use the valid profile" + + ent profile new "$TEST_PROFILE" "$TEST_PROFILE" "$TEST_PROFILE" + + _ASSERT -v current-profile "|$(_test_profile.get_current_profile)|" = "|$TEST_PROFILE|" + + ent config TEST_VAR "" + _ASSERT -v TEST_VAR "$(ent config TEST_VAR)" = "" + ) || _SOE + + ( _IT "should graciously fail when trying to use an unexisting subprofile" + + _ASSERT -v use-sub-profile-result "$( + ent profile use "$TEST_PROFILE" "x" 2>&1 + )" contains "The sub-profile was not found" + + _ASSERT -v current-profile "$(_test_profile.get_current_profile)" = "$TEST_PROFILE" + _ASSERT -v TEST_VAR "$(ent config TEST_VAR)" = "" + ) || _SOE + + ( _IT "should support autocreation" + + ent profile use "$TEST_PROFILE" "x" -a + ent config TEST_VAR "" + + _ASSERT -v current-profile "$(_test_profile.get_current_profile)" = "$TEST_PROFILE/x" + _ASSERT -v TEST_VAR "$(ent config TEST_VAR)" = "" + + ) || _SOE + + ( _IT "should be able to properly restore the base profile" + + ent profile use "$TEST_PROFILE" + _ASSERT -v current-profile "$(_test_profile.get_current_profile)" = "$TEST_PROFILE" + _ASSERT -v TEST_VAR "$(ent config TEST_VAR)" = "" + + ) || _SOE + + _test_profile.cleanup +} + +_test_profile.get_current_profile() { + ent status | grep "PROFILE:" | sed 's/.*PROFILE:[[:space:]]*//' +} + +_test_profile.cleanup() { + ent profile delete "$TEST_PROFILE" --yes #&>/dev/null +} diff --git a/utils/activate-ent.sh b/utils/activate-ent.sh old mode 100644 new mode 100755 diff --git a/utils/docker b/utils/docker old mode 100644 new mode 100755 diff --git a/xdev b/xdev index b56e56ca..27b08eb4 100755 --- a/xdev +++ b/xdev @@ -1,4 +1,4 @@ XDEV_LANG="sh" XDEV_SRC="bin:*.sh;s:*.sh;test:*.sh;hr:*.sh" XDEV_TEST_FOLDER="test" -XDEV_SHELLCHECK_IGNORE="SC2181,SC2155,SC2119,SC2030,SC2031" +XDEV_SHELLCHECK_IGNORE="SC2181,SC2155,SC2119,SC2030,SC2031,SC2317"