"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/salt/cloud/deploy/bootstrap-salt.sh" (18 Nov 2020, 300739 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "bootstrap-salt.sh": 3002.1_vs_3002.2.

    1 #!/bin/sh -
    2 
    3 # WARNING: Changes to this file in the salt repo will be overwritten!
    4 # Please submit pull requests against the salt-bootstrap repo:
    5 # https://github.com/saltstack/salt-bootstrap
    6 
    7 #======================================================================================================================
    8 # vim: softtabstop=4 shiftwidth=4 expandtab fenc=utf-8 spell spelllang=en cc=120
    9 #======================================================================================================================
   10 #
   11 #          FILE: bootstrap-salt.sh
   12 #
   13 #   DESCRIPTION: Bootstrap Salt installation for various systems/distributions
   14 #
   15 #          BUGS: https://github.com/saltstack/salt-bootstrap/issues
   16 #
   17 #     COPYRIGHT: (c) 2012-2018 by the SaltStack Team, see AUTHORS.rst for more
   18 #                details.
   19 #
   20 #       LICENSE: Apache 2.0
   21 #  ORGANIZATION: SaltStack (saltstack.com)
   22 #       CREATED: 10/15/2012 09:49:37 PM WEST
   23 #======================================================================================================================
   24 set -o nounset                              # Treat unset variables as an error
   25 
   26 __ScriptVersion="2020.10.20"
   27 __ScriptName="bootstrap-salt.sh"
   28 
   29 __ScriptFullName="$0"
   30 __ScriptArgs="$*"
   31 
   32 #======================================================================================================================
   33 #  Environment variables taken into account.
   34 #----------------------------------------------------------------------------------------------------------------------
   35 #   * BS_COLORS:                If 0 disables colour support
   36 #   * BS_PIP_ALLOWED:           If 1 enable pip based installations(if needed)
   37 #   * BS_PIP_ALL:               If 1 enable all python packages to be installed via pip instead of apt, requires setting virtualenv
   38 #   * BS_VIRTUALENV_DIR:        The virtualenv to install salt into (shouldn't exist yet)
   39 #   * BS_ECHO_DEBUG:            If 1 enable debug echo which can also be set by -D
   40 #   * BS_SALT_ETC_DIR:          Defaults to /etc/salt (Only tweak'able on git based installations)
   41 #   * BS_SALT_CACHE_DIR:        Defaults to /var/cache/salt (Only tweak'able on git based installations)
   42 #   * BS_KEEP_TEMP_FILES:       If 1, don't move temporary files, instead copy them
   43 #   * BS_FORCE_OVERWRITE:       Force overriding copied files(config, init.d, etc)
   44 #   * BS_UPGRADE_SYS:           If 1 and an option, upgrade system. Default 0.
   45 #   * BS_GENTOO_USE_BINHOST:    If 1 add `--getbinpkg` to gentoo's emerge
   46 #   * BS_SALT_MASTER_ADDRESS:   The IP or DNS name of the salt-master the minion should connect to
   47 #   * BS_SALT_GIT_CHECKOUT_DIR: The directory where to clone Salt on git installations
   48 #======================================================================================================================
   49 
   50 
   51 # Bootstrap script truth values
   52 BS_TRUE=1
   53 BS_FALSE=0
   54 
   55 # Default sleep time used when waiting for daemons to start, restart and checking for these running
   56 __DEFAULT_SLEEP=3
   57 
   58 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
   59 #          NAME:  __detect_color_support
   60 #   DESCRIPTION:  Try to detect color support.
   61 #----------------------------------------------------------------------------------------------------------------------
   62 _COLORS=${BS_COLORS:-$(tput colors 2>/dev/null || echo 0)}
   63 __detect_color_support() {
   64     # shellcheck disable=SC2181
   65     if [ $? -eq 0 ] && [ "$_COLORS" -gt 2 ]; then
   66         RC='\033[1;31m'
   67         GC='\033[1;32m'
   68         BC='\033[1;34m'
   69         YC='\033[1;33m'
   70         EC='\033[0m'
   71     else
   72         RC=""
   73         GC=""
   74         BC=""
   75         YC=""
   76         EC=""
   77     fi
   78 }
   79 __detect_color_support
   80 
   81 
   82 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
   83 #          NAME:  echoerr
   84 #   DESCRIPTION:  Echo errors to stderr.
   85 #----------------------------------------------------------------------------------------------------------------------
   86 echoerror() {
   87     printf "${RC} * ERROR${EC}: %s\\n" "$@" 1>&2;
   88 }
   89 
   90 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
   91 #          NAME:  echoinfo
   92 #   DESCRIPTION:  Echo information to stdout.
   93 #----------------------------------------------------------------------------------------------------------------------
   94 echoinfo() {
   95     printf "${GC} *  INFO${EC}: %s\\n" "$@";
   96 }
   97 
   98 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
   99 #          NAME:  echowarn
  100 #   DESCRIPTION:  Echo warning information to stdout.
  101 #----------------------------------------------------------------------------------------------------------------------
  102 echowarn() {
  103     printf "${YC} *  WARN${EC}: %s\\n" "$@";
  104 }
  105 
  106 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  107 #          NAME:  echodebug
  108 #   DESCRIPTION:  Echo debug information to stdout.
  109 #----------------------------------------------------------------------------------------------------------------------
  110 echodebug() {
  111     if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
  112         printf "${BC} * DEBUG${EC}: %s\\n" "$@";
  113     fi
  114 }
  115 
  116 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  117 #          NAME:  __check_command_exists
  118 #   DESCRIPTION:  Check if a command exists.
  119 #----------------------------------------------------------------------------------------------------------------------
  120 __check_command_exists() {
  121     command -v "$1" > /dev/null 2>&1
  122 }
  123 
  124 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  125 #          NAME:  __check_pip_allowed
  126 #   DESCRIPTION:  Simple function to let the users know that -P needs to be used.
  127 #----------------------------------------------------------------------------------------------------------------------
  128 __check_pip_allowed() {
  129     if [ $# -eq 1 ]; then
  130         _PIP_ALLOWED_ERROR_MSG=$1
  131     else
  132         _PIP_ALLOWED_ERROR_MSG="pip based installations were not allowed. Retry using '-P'"
  133     fi
  134 
  135     if [ "$_PIP_ALLOWED" -eq $BS_FALSE ]; then
  136         echoerror "$_PIP_ALLOWED_ERROR_MSG"
  137         __usage
  138         exit 1
  139     fi
  140 }
  141 
  142 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  143 #         NAME:  __check_config_dir
  144 #  DESCRIPTION:  Checks the config directory, retrieves URLs if provided.
  145 #----------------------------------------------------------------------------------------------------------------------
  146 __check_config_dir() {
  147     CC_DIR_NAME="$1"
  148     CC_DIR_BASE=$(basename "${CC_DIR_NAME}")
  149 
  150     case "$CC_DIR_NAME" in
  151         http://*|https://*)
  152             __fetch_url "/tmp/${CC_DIR_BASE}" "${CC_DIR_NAME}"
  153             CC_DIR_NAME="/tmp/${CC_DIR_BASE}"
  154             ;;
  155         ftp://*)
  156             __fetch_url "/tmp/${CC_DIR_BASE}" "${CC_DIR_NAME}"
  157             CC_DIR_NAME="/tmp/${CC_DIR_BASE}"
  158             ;;
  159         *://*)
  160             echoerror "Unsupported URI scheme for $CC_DIR_NAME"
  161             echo "null"
  162             return
  163             ;;
  164         *)
  165             if [ ! -e "${CC_DIR_NAME}" ]; then
  166                 echoerror "The configuration directory or archive $CC_DIR_NAME does not exist."
  167                 echo "null"
  168                 return
  169             fi
  170             ;;
  171     esac
  172 
  173     case "$CC_DIR_NAME" in
  174         *.tgz|*.tar.gz)
  175             tar -zxf "${CC_DIR_NAME}" -C /tmp
  176             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".tgz")
  177             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".tar.gz")
  178             CC_DIR_NAME="/tmp/${CC_DIR_BASE}"
  179             ;;
  180         *.tbz|*.tar.bz2)
  181             tar -xjf "${CC_DIR_NAME}" -C /tmp
  182             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".tbz")
  183             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".tar.bz2")
  184             CC_DIR_NAME="/tmp/${CC_DIR_BASE}"
  185             ;;
  186         *.txz|*.tar.xz)
  187             tar -xJf "${CC_DIR_NAME}" -C /tmp
  188             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".txz")
  189             CC_DIR_BASE=$(basename "${CC_DIR_BASE}" ".tar.xz")
  190             CC_DIR_NAME="/tmp/${CC_DIR_BASE}"
  191             ;;
  192     esac
  193 
  194     echo "${CC_DIR_NAME}"
  195 }
  196 
  197 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  198 #         NAME:  __check_unparsed_options
  199 #  DESCRIPTION:  Checks the placed after the install arguments
  200 #----------------------------------------------------------------------------------------------------------------------
  201 __check_unparsed_options() {
  202     shellopts="$1"
  203     # grep alternative for SunOS
  204     if [ -f /usr/xpg4/bin/grep ]; then
  205         grep='/usr/xpg4/bin/grep'
  206     else
  207         grep='grep'
  208     fi
  209     unparsed_options=$( echo "$shellopts" | ${grep} -E '(^|[[:space:]])[-]+[[:alnum:]]' )
  210     if [ "$unparsed_options" != "" ]; then
  211         __usage
  212         echo
  213         echoerror "options are only allowed before install arguments"
  214         echo
  215         exit 1
  216     fi
  217 }
  218 
  219 
  220 #----------------------------------------------------------------------------------------------------------------------
  221 #  Handle command line arguments
  222 #----------------------------------------------------------------------------------------------------------------------
  223 _KEEP_TEMP_FILES=${BS_KEEP_TEMP_FILES:-$BS_FALSE}
  224 _TEMP_CONFIG_DIR="null"
  225 _SALTSTACK_REPO_URL="https://github.com/saltstack/salt.git"
  226 _SALT_REPO_URL=${_SALTSTACK_REPO_URL}
  227 _DOWNSTREAM_PKG_REPO=$BS_FALSE
  228 _TEMP_KEYS_DIR="null"
  229 _SLEEP="${__DEFAULT_SLEEP}"
  230 _INSTALL_MASTER=$BS_FALSE
  231 _INSTALL_SYNDIC=$BS_FALSE
  232 _INSTALL_MINION=$BS_TRUE
  233 _INSTALL_CLOUD=$BS_FALSE
  234 _VIRTUALENV_DIR=${BS_VIRTUALENV_DIR:-"null"}
  235 _START_DAEMONS=$BS_TRUE
  236 _DISABLE_SALT_CHECKS=$BS_FALSE
  237 _ECHO_DEBUG=${BS_ECHO_DEBUG:-$BS_FALSE}
  238 _CONFIG_ONLY=$BS_FALSE
  239 _PIP_ALLOWED=${BS_PIP_ALLOWED:-$BS_FALSE}
  240 _PIP_ALL=${BS_PIP_ALL:-$BS_FALSE}
  241 _SALT_ETC_DIR=${BS_SALT_ETC_DIR:-/etc/salt}
  242 _SALT_CACHE_DIR=${BS_SALT_CACHE_DIR:-/var/cache/salt}
  243 _PKI_DIR=${_SALT_ETC_DIR}/pki
  244 _FORCE_OVERWRITE=${BS_FORCE_OVERWRITE:-$BS_FALSE}
  245 _GENTOO_USE_BINHOST=${BS_GENTOO_USE_BINHOST:-$BS_FALSE}
  246 _EPEL_REPO=${BS_EPEL_REPO:-epel}
  247 _EPEL_REPOS_INSTALLED=$BS_FALSE
  248 _UPGRADE_SYS=${BS_UPGRADE_SYS:-$BS_FALSE}
  249 _INSECURE_DL=${BS_INSECURE_DL:-$BS_FALSE}
  250 _CURL_ARGS=${BS_CURL_ARGS:-}
  251 _FETCH_ARGS=${BS_FETCH_ARGS:-}
  252 _GPG_ARGS=${BS_GPG_ARGS:-}
  253 _WGET_ARGS=${BS_WGET_ARGS:-}
  254 _SALT_MASTER_ADDRESS=${BS_SALT_MASTER_ADDRESS:-null}
  255 _SALT_MINION_ID="null"
  256 # _SIMPLIFY_VERSION is mostly used in Solaris based distributions
  257 _SIMPLIFY_VERSION=$BS_TRUE
  258 _LIBCLOUD_MIN_VERSION="0.14.0"
  259 _EXTRA_PACKAGES=""
  260 _HTTP_PROXY=""
  261 _SALT_GIT_CHECKOUT_DIR=${BS_SALT_GIT_CHECKOUT_DIR:-/tmp/git/salt}
  262 _NO_DEPS=$BS_FALSE
  263 _FORCE_SHALLOW_CLONE=$BS_FALSE
  264 _DISABLE_SSL=$BS_FALSE
  265 _DISABLE_REPOS=$BS_FALSE
  266 _CUSTOM_REPO_URL="null"
  267 _CUSTOM_MASTER_CONFIG="null"
  268 _CUSTOM_MINION_CONFIG="null"
  269 _QUIET_GIT_INSTALLATION=$BS_FALSE
  270 _REPO_URL="repo.saltstack.com"
  271 _PY_EXE=""
  272 _INSTALL_PY="$BS_FALSE"
  273 _TORNADO_MAX_PY3_VERSION="5.0"
  274 _POST_NEON_INSTALL=$BS_FALSE
  275 _MINIMUM_PIP_VERSION="8.0.0"
  276 _MINIMUM_SETUPTOOLS_VERSION="9.1"
  277 _POST_NEON_PIP_INSTALL_ARGS="--prefix=/usr"
  278 
  279 # Defaults for install arguments
  280 ITYPE="stable"
  281 
  282 
  283 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  284 #         NAME:  __usage
  285 #  DESCRIPTION:  Display usage information.
  286 #----------------------------------------------------------------------------------------------------------------------
  287 __usage() {
  288     cat << EOT
  289 
  290   Usage :  ${__ScriptName} [options] <install-type> [install-type-args]
  291 
  292   Installation types:
  293     - stable              Install latest stable release. This is the default
  294                           install type
  295     - stable [branch]     Install latest version on a branch. Only supported
  296                           for packages available at repo.saltstack.com
  297     - stable [version]    Install a specific version. Only supported for
  298                           packages available at repo.saltstack.com
  299                           To pin a 3xxx minor version, specify it as 3xxx.0
  300     - testing             RHEL-family specific: configure EPEL testing repo
  301     - git                 Install from the head of the master branch
  302     - git [ref]           Install from any git ref (such as a branch, tag, or
  303                           commit)
  304 
  305   Examples:
  306     - ${__ScriptName}
  307     - ${__ScriptName} stable
  308     - ${__ScriptName} stable 2017.7
  309     - ${__ScriptName} stable 2017.7.2
  310     - ${__ScriptName} testing
  311     - ${__ScriptName} git
  312     - ${__ScriptName} git 2017.7
  313     - ${__ScriptName} git v2017.7.2
  314     - ${__ScriptName} git 06f249901a2e2f1ed310d58ea3921a129f214358
  315 
  316   Options:
  317     -h  Display this message
  318     -v  Display script version
  319     -n  No colours
  320     -D  Show debug output
  321     -c  Temporary configuration directory
  322     -g  Salt Git repository URL. Default: ${_SALTSTACK_REPO_URL}
  323     -w  Install packages from downstream package repository rather than
  324         upstream, saltstack package repository. This is currently only
  325         implemented for SUSE.
  326     -k  Temporary directory holding the minion keys which will pre-seed
  327         the master.
  328     -s  Sleep time used when waiting for daemons to start, restart and when
  329         checking for the services running. Default: ${__DEFAULT_SLEEP}
  330     -L  Also install salt-cloud and required python-libcloud package
  331     -M  Also install salt-master
  332     -S  Also install salt-syndic
  333     -N  Do not install salt-minion
  334     -X  Do not start daemons after installation
  335     -d  Disables checking if Salt services are enabled to start on system boot.
  336         You can also do this by touching /tmp/disable_salt_checks on the target
  337         host. Default: \${BS_FALSE}
  338     -P  Allow pip based installations. On some distributions the required salt
  339         packages or its dependencies are not available as a package for that
  340         distribution. Using this flag allows the script to use pip as a last
  341         resort method. NOTE: This only works for functions which actually
  342         implement pip based installations.
  343     -U  If set, fully upgrade the system prior to bootstrapping Salt
  344     -I  If set, allow insecure connections while downloading any files. For
  345         example, pass '--no-check-certificate' to 'wget' or '--insecure' to
  346         'curl'. On Debian and Ubuntu, using this option with -U allows obtaining
  347         GnuPG archive keys insecurely if distro has changed release signatures.
  348     -F  Allow copied files to overwrite existing (config, init.d, etc)
  349     -K  If set, keep the temporary files in the temporary directories specified
  350         with -c and -k
  351     -C  Only run the configuration function. Implies -F (forced overwrite).
  352         To overwrite Master or Syndic configs, -M or -S, respectively, must
  353         also be specified. Salt installation will be ommitted, but some of the
  354         dependencies could be installed to write configuration with -j or -J.
  355     -A  Pass the salt-master DNS name or IP. This will be stored under
  356         \${BS_SALT_ETC_DIR}/minion.d/99-master-address.conf
  357     -i  Pass the salt-minion id. This will be stored under
  358         \${BS_SALT_ETC_DIR}/minion_id
  359     -p  Extra-package to install while installing Salt dependencies. One package
  360         per -p flag. You are responsible for providing the proper package name.
  361     -H  Use the specified HTTP proxy for all download URLs (including https://).
  362         For example: http://myproxy.example.com:3128
  363     -b  Assume that dependencies are already installed and software sources are
  364         set up. If git is selected, git tree is still checked out as dependency
  365         step.
  366     -f  Force shallow cloning for git installations.
  367         This may result in an "n/a" in the version number.
  368     -l  Disable ssl checks. When passed, switches "https" calls to "http" where
  369         possible.
  370     -V  Install Salt into virtualenv
  371         (only available for Ubuntu based distributions)
  372     -a  Pip install all Python pkg dependencies for Salt. Requires -V to install
  373         all pip pkgs into the virtualenv.
  374         (Only available for Ubuntu based distributions)
  375     -r  Disable all repository configuration performed by this script. This
  376         option assumes all necessary repository configuration is already present
  377         on the system.
  378     -R  Specify a custom repository URL. Assumes the custom repository URL
  379         points to a repository that mirrors Salt packages located at
  380         repo.saltstack.com. The option passed with -R replaces the
  381         "repo.saltstack.com". If -R is passed, -r is also set. Currently only
  382         works on CentOS/RHEL and Debian based distributions.
  383     -J  Replace the Master config file with data passed in as a JSON string. If
  384         a Master config file is found, a reasonable effort will be made to save
  385         the file with a ".bak" extension. If used in conjunction with -C or -F,
  386         no ".bak" file will be created as either of those options will force
  387         a complete overwrite of the file.
  388     -j  Replace the Minion config file with data passed in as a JSON string. If
  389         a Minion config file is found, a reasonable effort will be made to save
  390         the file with a ".bak" extension. If used in conjunction with -C or -F,
  391         no ".bak" file will be created as either of those options will force
  392         a complete overwrite of the file.
  393     -q  Quiet salt installation from git (setup.py install -q)
  394     -x  Changes the Python version used to install Salt.
  395         For CentOS 6 git installations python2.7 is supported.
  396         Fedora git installation, CentOS 7, Debian 9, Ubuntu 16.04 and 18.04 support python3.
  397     -y  Installs a different python version on host. Currently this has only been
  398         tested with CentOS 6 and is considered experimental. This will install the
  399         ius repo on the box if disable repo is false. This must be used in conjunction
  400         with -x <pythonversion>.  For example:
  401             sh bootstrap.sh -P -y -x python2.7 git v2017.7.2
  402         The above will install python27 and install the git version of salt using the
  403         python2.7 executable. This only works for git and pip installations.
  404 
  405 EOT
  406 }   # ----------  end of function __usage  ----------
  407 
  408 
  409 while getopts ':hvnDc:g:Gyx:wk:s:MSNXCPFUKIA:i:Lp:dH:bflV:J:j:rR:aq' opt
  410 do
  411   case "${opt}" in
  412 
  413     h )  __usage; exit 0                                ;;
  414     v )  echo "$0 -- Version $__ScriptVersion"; exit 0  ;;
  415     n )  _COLORS=0; __detect_color_support              ;;
  416     D )  _ECHO_DEBUG=$BS_TRUE                           ;;
  417     c )  _TEMP_CONFIG_DIR="$OPTARG"                     ;;
  418     g )  _SALT_REPO_URL=$OPTARG                         ;;
  419 
  420     G )  echowarn "The '-G' option is DEPRECATED and will be removed in the future stable release!"
  421          echowarn "Bootstrap will always use 'https' protocol to clone from SaltStack GitHub repo."
  422          echowarn "No need to provide this option anymore, now it is a default behavior."
  423          ;;
  424 
  425     w )  _DOWNSTREAM_PKG_REPO=$BS_TRUE                  ;;
  426     k )  _TEMP_KEYS_DIR="$OPTARG"                       ;;
  427     s )  _SLEEP=$OPTARG                                 ;;
  428     M )  _INSTALL_MASTER=$BS_TRUE                       ;;
  429     S )  _INSTALL_SYNDIC=$BS_TRUE                       ;;
  430     N )  _INSTALL_MINION=$BS_FALSE                      ;;
  431     X )  _START_DAEMONS=$BS_FALSE                       ;;
  432     C )  _CONFIG_ONLY=$BS_TRUE                          ;;
  433     P )  _PIP_ALLOWED=$BS_TRUE                          ;;
  434     F )  _FORCE_OVERWRITE=$BS_TRUE                      ;;
  435     U )  _UPGRADE_SYS=$BS_TRUE                          ;;
  436     K )  _KEEP_TEMP_FILES=$BS_TRUE                      ;;
  437     I )  _INSECURE_DL=$BS_TRUE                          ;;
  438     A )  _SALT_MASTER_ADDRESS=$OPTARG                   ;;
  439     i )  _SALT_MINION_ID=$OPTARG                        ;;
  440     L )  _INSTALL_CLOUD=$BS_TRUE                        ;;
  441     p )  _EXTRA_PACKAGES="$_EXTRA_PACKAGES $OPTARG"     ;;
  442     d )  _DISABLE_SALT_CHECKS=$BS_TRUE                  ;;
  443     H )  _HTTP_PROXY="$OPTARG"                          ;;
  444     b )  _NO_DEPS=$BS_TRUE                              ;;
  445     f )  _FORCE_SHALLOW_CLONE=$BS_TRUE                  ;;
  446     l )  _DISABLE_SSL=$BS_TRUE                          ;;
  447     V )  _VIRTUALENV_DIR="$OPTARG"                      ;;
  448     a )  _PIP_ALL=$BS_TRUE                              ;;
  449     r )  _DISABLE_REPOS=$BS_TRUE                        ;;
  450     R )  _CUSTOM_REPO_URL=$OPTARG                       ;;
  451     J )  _CUSTOM_MASTER_CONFIG=$OPTARG                  ;;
  452     j )  _CUSTOM_MINION_CONFIG=$OPTARG                  ;;
  453     q )  _QUIET_GIT_INSTALLATION=$BS_TRUE               ;;
  454     x )  _PY_EXE="$OPTARG"                              ;;
  455     y )  _INSTALL_PY="$BS_TRUE"                         ;;
  456 
  457     \?)  echo
  458          echoerror "Option does not exist : $OPTARG"
  459          __usage
  460          exit 1
  461          ;;
  462 
  463   esac    # --- end of case ---
  464 done
  465 shift $((OPTIND-1))
  466 
  467 
  468 # Define our logging file and pipe paths
  469 LOGFILE="/tmp/$( echo "$__ScriptName" | sed s/.sh/.log/g )"
  470 LOGPIPE="/tmp/$( echo "$__ScriptName" | sed s/.sh/.logpipe/g )"
  471 # Ensure no residual pipe exists
  472 rm "$LOGPIPE" 2>/dev/null
  473 
  474 # Create our logging pipe
  475 # On FreeBSD we have to use mkfifo instead of mknod
  476 if ! (mknod "$LOGPIPE" p >/dev/null 2>&1 || mkfifo "$LOGPIPE" >/dev/null 2>&1); then
  477     echoerror "Failed to create the named pipe required to log"
  478     exit 1
  479 fi
  480 
  481 # What ever is written to the logpipe gets written to the logfile
  482 tee < "$LOGPIPE" "$LOGFILE" &
  483 
  484 # Close STDOUT, reopen it directing it to the logpipe
  485 exec 1>&-
  486 exec 1>"$LOGPIPE"
  487 # Close STDERR, reopen it directing it to the logpipe
  488 exec 2>&-
  489 exec 2>"$LOGPIPE"
  490 
  491 
  492 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  493 #          NAME:  __exit_cleanup
  494 #   DESCRIPTION:  Cleanup any leftovers after script has ended
  495 #
  496 #
  497 #   http://www.unix.com/man-page/POSIX/1posix/trap/
  498 #
  499 #               Signal Number   Signal Name
  500 #               1               SIGHUP
  501 #               2               SIGINT
  502 #               3               SIGQUIT
  503 #               6               SIGABRT
  504 #               9               SIGKILL
  505 #              14               SIGALRM
  506 #              15               SIGTERM
  507 #----------------------------------------------------------------------------------------------------------------------
  508 APT_ERR=$(mktemp /tmp/apt_error.XXXXXX)
  509 __exit_cleanup() {
  510     EXIT_CODE=$?
  511 
  512     if [ "$ITYPE" = "git" ] && [ -d "${_SALT_GIT_CHECKOUT_DIR}" ]; then
  513         if [ $_KEEP_TEMP_FILES -eq $BS_FALSE ]; then
  514             # Clean up the checked out repository
  515             echodebug "Cleaning up the Salt Temporary Git Repository"
  516             # shellcheck disable=SC2164
  517             cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
  518             rm -rf "${_SALT_GIT_CHECKOUT_DIR}"
  519             #rm -rf "${_SALT_GIT_CHECKOUT_DIR}/deps"
  520         else
  521             echowarn "Not cleaning up the Salt Temporary git repository on request"
  522             echowarn "Note that if you intend to re-run this script using the git approach, you might encounter some issues"
  523         fi
  524     fi
  525 
  526     # Remove the logging pipe when the script exits
  527     if [ -p "$LOGPIPE" ]; then
  528         echodebug "Removing the logging pipe $LOGPIPE"
  529         rm -f "$LOGPIPE"
  530     fi
  531 
  532     # Remove the temporary apt error file when the script exits
  533     if [ -f "$APT_ERR" ]; then
  534         echodebug "Removing the temporary apt error file $APT_ERR"
  535         rm -f "$APT_ERR"
  536     fi
  537 
  538     # Kill tee when exiting, CentOS, at least requires this
  539     # shellcheck disable=SC2009
  540     TEE_PID=$(ps ax | grep tee | grep "$LOGFILE" | awk '{print $1}')
  541 
  542     [ "$TEE_PID" = "" ] && exit $EXIT_CODE
  543 
  544     echodebug "Killing logging pipe tee's with pid(s): $TEE_PID"
  545 
  546     # We need to trap errors since killing tee will cause a 127 errno
  547     # We also do this as late as possible so we don't "mis-catch" other errors
  548     __trap_errors() {
  549         echoinfo "Errors Trapped: $EXIT_CODE"
  550         # Exit with the "original" exit code, not the trapped code
  551         exit $EXIT_CODE
  552     }
  553     trap "__trap_errors" INT ABRT QUIT TERM
  554 
  555     # Now we're "good" to kill tee
  556     kill -s TERM "$TEE_PID"
  557 
  558     # In case the 127 errno is not triggered, exit with the "original" exit code
  559     exit $EXIT_CODE
  560 }
  561 trap "__exit_cleanup" EXIT INT
  562 
  563 
  564 # Let's discover how we're being called
  565 # shellcheck disable=SC2009
  566 CALLER=$(ps -a -o pid,args | grep $$ | grep -v grep | tr -s ' ' | cut -d ' ' -f 3)
  567 
  568 if [ "${CALLER}x" = "${0}x" ]; then
  569     CALLER="shell pipe"
  570 fi
  571 
  572 echoinfo "Running version: ${__ScriptVersion}"
  573 echoinfo "Executed by: ${CALLER}"
  574 echoinfo "Command line: '${__ScriptFullName} ${__ScriptArgs}'"
  575 #echowarn "Running the unstable version of ${__ScriptName}"
  576 
  577 # Define installation type
  578 if [ "$#" -gt 0 ];then
  579     __check_unparsed_options "$*"
  580     ITYPE=$1
  581     shift
  582 fi
  583 
  584 # Check installation type
  585 if [ "$(echo "$ITYPE" | grep -E '(stable|testing|git)')" = "" ]; then
  586     echoerror "Installation type \"$ITYPE\" is not known..."
  587     exit 1
  588 fi
  589 
  590 # If doing a git install, check what branch/tag/sha will be checked out
  591 if [ "$ITYPE" = "git" ]; then
  592     if [ "$#" -eq 0 ];then
  593         GIT_REV="master"
  594     else
  595         GIT_REV="$1"
  596         shift
  597     fi
  598 
  599     # Disable shell warning about unbound variable during git install
  600     STABLE_REV="latest"
  601 
  602 # If doing stable install, check if version specified
  603 elif [ "$ITYPE" = "stable" ]; then
  604     if [ "$#" -eq 0 ];then
  605         STABLE_REV="latest"
  606     else
  607         if [ "$(echo "$1" | grep -E '^(latest|1\.6|1\.7|2014\.1|2014\.7|2015\.5|2015\.8|2016\.3|2016\.11|2017\.7|2018\.3|2019\.2|3000|3001|3002)$')" != "" ]; then
  608             STABLE_REV="$1"
  609             shift
  610         elif [ "$(echo "$1" | grep -E '^(2[0-9]*\.[0-9]*\.[0-9]*|[3-9][0-9]{3}(\.[0-9]*)?)$')" != "" ]; then
  611             # Handle the 3xxx.0 version as 3xxx archive (pin to minor) and strip the fake ".0" suffix
  612             STABLE_REV=$(echo "$1" | sed -E 's/^([3-9][0-9]{3})\.0$/\1/')
  613             if [ "$(uname)" != "Darwin" ]; then
  614                 STABLE_REV="archive/$STABLE_REV"
  615             fi
  616             shift
  617         else
  618             echo "Unknown stable version: $1 (valid: 1.6, 1.7, 2014.1, 2014.7, 2015.5, 2015.8, 2016.3, 2016.11, 2017.7, 2018.3, 2019.2, 3000, 3001 3002, latest, \$MAJOR.\$MINOR.\$PATCH until 2019.2, \$MAJOR or \$MAJOR.\$PATCH starting from 3000)"
  619             exit 1
  620         fi
  621     fi
  622 fi
  623 
  624 # Check for any unparsed arguments. Should be an error.
  625 if [ "$#" -gt 0 ]; then
  626     __usage
  627     echo
  628     echoerror "Too many arguments."
  629     exit 1
  630 fi
  631 
  632 # whoami alternative for SunOS
  633 if [ -f /usr/xpg4/bin/id ]; then
  634     whoami='/usr/xpg4/bin/id -un'
  635 else
  636     whoami='whoami'
  637 fi
  638 
  639 # Root permissions are required to run this script
  640 if [ "$($whoami)" != "root" ]; then
  641     echoerror "Salt requires root privileges to install. Please re-run this script as root."
  642     exit 1
  643 fi
  644 
  645 # Check that we're actually installing one of minion/master/syndic
  646 if [ "$_INSTALL_MINION" -eq $BS_FALSE ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
  647     echowarn "Nothing to install or configure"
  648     exit 1
  649 fi
  650 
  651 # Check that we're installing a minion if we're being passed a master address
  652 if [ "$_INSTALL_MINION" -eq $BS_FALSE ] && [ "$_SALT_MASTER_ADDRESS" != "null" ]; then
  653     echoerror "Don't pass a master address (-A) if no minion is going to be bootstrapped."
  654     exit 1
  655 fi
  656 
  657 # Check that we're installing a minion if we're being passed a minion id
  658 if [ "$_INSTALL_MINION" -eq $BS_FALSE ] && [ "$_SALT_MINION_ID" != "null" ]; then
  659     echoerror "Don't pass a minion id (-i) if no minion is going to be bootstrapped."
  660     exit 1
  661 fi
  662 
  663 # Check that we're installing or configuring a master if we're being passed a master config json dict
  664 if [ "$_CUSTOM_MASTER_CONFIG" != "null" ]; then
  665     if [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
  666         echoerror "Don't pass a master config JSON dict (-J) if no master is going to be bootstrapped or configured."
  667         exit 1
  668     fi
  669 fi
  670 
  671 # Check that we're installing or configuring a minion if we're being passed a minion config json dict
  672 if [ "$_CUSTOM_MINION_CONFIG" != "null" ]; then
  673     if [ "$_INSTALL_MINION" -eq $BS_FALSE ] && [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
  674         echoerror "Don't pass a minion config JSON dict (-j) if no minion is going to be bootstrapped or configured."
  675         exit 1
  676     fi
  677 fi
  678 
  679 # Check if we're installing via a different Python executable and set major version variables
  680 if [ -n "$_PY_EXE" ]; then
  681     if [ "$(uname)" = "Darwin" ]; then
  682       _PY_PKG_VER=$(echo "$_PY_EXE" | sed "s/\\.//g")
  683     else
  684       _PY_PKG_VER=$(echo "$_PY_EXE" | sed -E "s/\\.//g")
  685     fi
  686 
  687     _PY_MAJOR_VERSION=$(echo "$_PY_PKG_VER" | cut -c 7)
  688     if [ "$_PY_MAJOR_VERSION" != 3 ] && [ "$_PY_MAJOR_VERSION" != 2 ]; then
  689         echoerror "Detected -x option, but Python major version is not 2 or 3."
  690         echoerror "The -x option must be passed as python2, python27, or python2.7 (or use the Python '3' versions of examples)."
  691         exit 1
  692     fi
  693 
  694     echoinfo "Detected -x option. Using $_PY_EXE to install Salt."
  695 else
  696     _PY_PKG_VER=""
  697     _PY_MAJOR_VERSION=""
  698 fi
  699 
  700 # If the configuration directory or archive does not exist, error out
  701 if [ "$_TEMP_CONFIG_DIR" != "null" ]; then
  702     _TEMP_CONFIG_DIR="$(__check_config_dir "$_TEMP_CONFIG_DIR")"
  703     [ "$_TEMP_CONFIG_DIR" = "null" ] && exit 1
  704 fi
  705 
  706 # If the pre-seed keys directory does not exist, error out
  707 if [ "$_TEMP_KEYS_DIR" != "null" ] && [ ! -d "$_TEMP_KEYS_DIR" ]; then
  708     echoerror "The pre-seed keys directory ${_TEMP_KEYS_DIR} does not exist."
  709     exit 1
  710 fi
  711 
  712 # -a and -V only work from git
  713 if [ "$ITYPE" != "git" ]; then
  714     if [ $_PIP_ALL -eq $BS_TRUE ]; then
  715         echoerror "Pip installing all python packages with -a is only possible when installing Salt via git"
  716         exit 1
  717     fi
  718     if [ "$_VIRTUALENV_DIR" != "null" ]; then
  719         echoerror "Virtualenv installs via -V is only possible when installing Salt via git"
  720         exit 1
  721     fi
  722 fi
  723 
  724 # Set the _REPO_URL value based on if -R was passed or not. Defaults to repo.saltstack.com.
  725 if [ "$_CUSTOM_REPO_URL" != "null" ]; then
  726     _REPO_URL="$_CUSTOM_REPO_URL"
  727 
  728     # Check for -r since -R is being passed. Set -r with a warning.
  729     if [ "$_DISABLE_REPOS" -eq $BS_FALSE ]; then
  730         echowarn "Detected -R option. No other repositories will be configured when -R is used. Setting -r option to True."
  731         _DISABLE_REPOS=$BS_TRUE
  732     fi
  733 fi
  734 
  735 # Check the _DISABLE_SSL value and set HTTP or HTTPS.
  736 if [ "$_DISABLE_SSL" -eq $BS_TRUE ]; then
  737     HTTP_VAL="http"
  738 else
  739     HTTP_VAL="https"
  740 fi
  741 
  742 # Check the _QUIET_GIT_INSTALLATION value and set SETUP_PY_INSTALL_ARGS.
  743 if [ "$_QUIET_GIT_INSTALLATION" -eq $BS_TRUE ]; then
  744     SETUP_PY_INSTALL_ARGS="-q"
  745 else
  746     SETUP_PY_INSTALL_ARGS=""
  747 fi
  748 
  749 # Handle the insecure flags
  750 if [ "$_INSECURE_DL" -eq $BS_TRUE ]; then
  751     _CURL_ARGS="${_CURL_ARGS} --insecure"
  752     _FETCH_ARGS="${_FETCH_ARGS} --no-verify-peer"
  753     _GPG_ARGS="${_GPG_ARGS} --keyserver-options no-check-cert"
  754     _WGET_ARGS="${_WGET_ARGS} --no-check-certificate"
  755 else
  756     _GPG_ARGS="${_GPG_ARGS} --keyserver-options ca-cert-file=/etc/ssl/certs/ca-certificates.crt"
  757 fi
  758 
  759 # Export the http_proxy configuration to our current environment
  760 if [ "${_HTTP_PROXY}" != "" ]; then
  761     export http_proxy="${_HTTP_PROXY}"
  762     export https_proxy="${_HTTP_PROXY}"
  763     # Using "deprecated" option here, but that appears the only way to make it work.
  764     # See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818802
  765     # and https://bugs.launchpad.net/ubuntu/+source/gnupg2/+bug/1625848
  766     _GPG_ARGS="${_GPG_ARGS},http-proxy=${_HTTP_PROXY}"
  767 fi
  768 
  769 # Work around for 'Docker + salt-bootstrap failure' https://github.com/saltstack/salt-bootstrap/issues/394
  770 if [ "${_DISABLE_SALT_CHECKS}" -eq $BS_FALSE ] && [ -f /tmp/disable_salt_checks ]; then
  771     # shellcheck disable=SC2016
  772     echowarn 'Found file: /tmp/disable_salt_checks, setting _DISABLE_SALT_CHECKS=$BS_TRUE'
  773     _DISABLE_SALT_CHECKS=$BS_TRUE
  774 fi
  775 
  776 # Because -a can only be installed into virtualenv
  777 if [ "${_PIP_ALL}" -eq $BS_TRUE ] && [ "${_VIRTUALENV_DIR}" = "null" ]; then
  778     usage
  779     # Could possibly set up a default virtualenv location when -a flag is passed
  780     echoerror "Using -a requires -V because pip pkgs should be siloed from python system pkgs"
  781     exit 1
  782 fi
  783 
  784 # Make sure virtualenv directory does not already exist
  785 if [ -d "${_VIRTUALENV_DIR}" ]; then
  786     echoerror "The directory ${_VIRTUALENV_DIR} for virtualenv already exists"
  787     exit 1
  788 fi
  789 
  790 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  791 #         NAME:  __fetch_url
  792 #  DESCRIPTION:  Retrieves a URL and writes it to a given path
  793 #----------------------------------------------------------------------------------------------------------------------
  794 __fetch_url() {
  795     # shellcheck disable=SC2086
  796     curl $_CURL_ARGS -L -s -f -o "$1" "$2" >/dev/null 2>&1     ||
  797         wget $_WGET_ARGS -q -O "$1" "$2" >/dev/null 2>&1       ||
  798             fetch $_FETCH_ARGS -q -o "$1" "$2" >/dev/null 2>&1 ||  # FreeBSD
  799                 fetch -q -o "$1" "$2" >/dev/null 2>&1          ||  # Pre FreeBSD 10
  800                     ftp -o "$1" "$2" >/dev/null 2>&1           ||  # OpenBSD
  801                         (echoerror "$2 failed to download to $1"; exit 1)
  802 }
  803 
  804 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  805 #         NAME:  __fetch_verify
  806 #  DESCRIPTION:  Retrieves a URL, verifies its content and writes it to standard output
  807 #----------------------------------------------------------------------------------------------------------------------
  808 __fetch_verify() {
  809     fetch_verify_url="$1"
  810     fetch_verify_sum="$2"
  811     fetch_verify_size="$3"
  812 
  813     fetch_verify_tmpf=$(mktemp) && \
  814     __fetch_url "$fetch_verify_tmpf" "$fetch_verify_url" && \
  815     test "$(stat --format=%s "$fetch_verify_tmpf")" -eq "$fetch_verify_size" && \
  816     test "$(md5sum "$fetch_verify_tmpf" | awk '{ print $1 }')" = "$fetch_verify_sum" && \
  817     cat "$fetch_verify_tmpf" && \
  818     if rm -f "$fetch_verify_tmpf"; then
  819         return 0
  820     fi
  821     echo "Failed verification of $fetch_verify_url"
  822     return 1
  823 }
  824 
  825 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  826 #          NAME:  __gather_hardware_info
  827 #   DESCRIPTION:  Discover hardware information
  828 #----------------------------------------------------------------------------------------------------------------------
  829 __gather_hardware_info() {
  830     if [ -f /proc/cpuinfo ]; then
  831         CPU_VENDOR_ID=$(awk '/vendor_id|Processor/ {sub(/-.*$/,"",$3); print $3; exit}' /proc/cpuinfo )
  832     elif [ -f /usr/bin/kstat ]; then
  833         # SmartOS.
  834         # Solaris!?
  835         # This has only been tested for a GenuineIntel CPU
  836         CPU_VENDOR_ID=$(/usr/bin/kstat -p cpu_info:0:cpu_info0:vendor_id | awk '{print $2}')
  837     else
  838         CPU_VENDOR_ID=$( sysctl -n hw.model )
  839     fi
  840     # shellcheck disable=SC2034
  841     CPU_VENDOR_ID_L=$( echo "$CPU_VENDOR_ID" | tr '[:upper:]' '[:lower:]' )
  842     CPU_ARCH=$(uname -m 2>/dev/null || uname -p 2>/dev/null || echo "unknown")
  843     CPU_ARCH_L=$( echo "$CPU_ARCH" | tr '[:upper:]' '[:lower:]' )
  844 }
  845 __gather_hardware_info
  846 
  847 
  848 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  849 #          NAME:  __gather_os_info
  850 #   DESCRIPTION:  Discover operating system information
  851 #----------------------------------------------------------------------------------------------------------------------
  852 __gather_os_info() {
  853     OS_NAME=$(uname -s 2>/dev/null)
  854     OS_NAME_L=$( echo "$OS_NAME" | tr '[:upper:]' '[:lower:]' )
  855     OS_VERSION=$(uname -r)
  856     # shellcheck disable=SC2034
  857     OS_VERSION_L=$( echo "$OS_VERSION" | tr '[:upper:]' '[:lower:]' )
  858 }
  859 __gather_os_info
  860 
  861 
  862 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  863 #          NAME:  __parse_version_string
  864 #   DESCRIPTION:  Parse version strings ignoring the revision.
  865 #                 MAJOR.MINOR.REVISION becomes MAJOR.MINOR
  866 #----------------------------------------------------------------------------------------------------------------------
  867 __parse_version_string() {
  868     VERSION_STRING="$1"
  869     PARSED_VERSION=$(
  870         echo "$VERSION_STRING" |
  871         sed -e 's/^/#/' \
  872             -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\)\(\.[0-9][0-9]*\).*$/\1/' \
  873             -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \
  874             -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \
  875             -e 's/^#.*$//'
  876     )
  877     echo "$PARSED_VERSION"
  878 }
  879 
  880 
  881 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  882 #          NAME:  __derive_debian_numeric_version
  883 #   DESCRIPTION:  Derive the numeric version from a Debian version string.
  884 #----------------------------------------------------------------------------------------------------------------------
  885 __derive_debian_numeric_version() {
  886     NUMERIC_VERSION=""
  887     INPUT_VERSION="$1"
  888     if echo "$INPUT_VERSION" | grep -q '^[0-9]'; then
  889         NUMERIC_VERSION="$INPUT_VERSION"
  890     elif [ -z "$INPUT_VERSION" ] && [ -f "/etc/debian_version" ]; then
  891         INPUT_VERSION="$(cat /etc/debian_version)"
  892     fi
  893     if [ -z "$NUMERIC_VERSION" ]; then
  894         if [ "$INPUT_VERSION" = "wheezy/sid" ]; then
  895             # I've found an EC2 wheezy image which did not tell its version
  896             NUMERIC_VERSION=$(__parse_version_string "7.0")
  897         elif [ "$INPUT_VERSION" = "jessie/sid" ]; then
  898             NUMERIC_VERSION=$(__parse_version_string "8.0")
  899         elif [ "$INPUT_VERSION" = "stretch/sid" ]; then
  900             NUMERIC_VERSION=$(__parse_version_string "9.0")
  901         elif [ "$INPUT_VERSION" = "buster/sid" ]; then
  902             NUMERIC_VERSION=$(__parse_version_string "10.0")
  903         else
  904             echowarn "Unable to parse the Debian Version (codename: '$INPUT_VERSION')"
  905         fi
  906     fi
  907     echo "$NUMERIC_VERSION"
  908 }
  909 
  910 
  911 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  912 #          NAME:  __unquote_string
  913 #   DESCRIPTION:  Strip single or double quotes from the provided string.
  914 #----------------------------------------------------------------------------------------------------------------------
  915 __unquote_string() {
  916     # shellcheck disable=SC1117
  917     echo "$*" | sed -e "s/^\([\"\']\)\(.*\)\1\$/\2/g"
  918 }
  919 
  920 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  921 #          NAME:  __camelcase_split
  922 #   DESCRIPTION:  Convert 'CamelCased' strings to 'Camel Cased'
  923 #----------------------------------------------------------------------------------------------------------------------
  924 __camelcase_split() {
  925     echo "$*" | sed -e 's/\([^[:upper:][:punct:]]\)\([[:upper:]]\)/\1 \2/g'
  926 }
  927 
  928 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  929 #          NAME:  __strip_duplicates
  930 #   DESCRIPTION:  Strip duplicate strings
  931 #----------------------------------------------------------------------------------------------------------------------
  932 __strip_duplicates() {
  933     echo "$*" | tr -s '[:space:]' '\n' | awk '!x[$0]++'
  934 }
  935 
  936 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  937 #          NAME:  __sort_release_files
  938 #   DESCRIPTION:  Custom sort function. Alphabetical or numerical sort is not
  939 #                 enough.
  940 #----------------------------------------------------------------------------------------------------------------------
  941 __sort_release_files() {
  942     KNOWN_RELEASE_FILES=$(echo "(arch|alpine|centos|debian|ubuntu|fedora|redhat|suse|\
  943         mandrake|mandriva|gentoo|slackware|turbolinux|unitedlinux|void|lsb|system|\
  944         oracle|os)(-|_)(release|version)" | sed -E 's:[[:space:]]::g')
  945     primary_release_files=""
  946     secondary_release_files=""
  947     # Sort know VS un-known files first
  948     for release_file in $(echo "${@}" | sed -E 's:[[:space:]]:\n:g' | sort -f | uniq); do
  949         match=$(echo "$release_file" | grep -E -i "${KNOWN_RELEASE_FILES}")
  950         if [ "${match}" != "" ]; then
  951             primary_release_files="${primary_release_files} ${release_file}"
  952         else
  953             secondary_release_files="${secondary_release_files} ${release_file}"
  954         fi
  955     done
  956 
  957     # Now let's sort by know files importance, max important goes last in the max_prio list
  958     max_prio="redhat-release centos-release oracle-release fedora-release"
  959     for entry in $max_prio; do
  960         if [ "$(echo "${primary_release_files}" | grep "$entry")" != "" ]; then
  961             primary_release_files=$(echo "${primary_release_files}" | sed -e "s:\\(.*\\)\\($entry\\)\\(.*\\):\\2 \\1 \\3:g")
  962         fi
  963     done
  964     # Now, least important goes last in the min_prio list
  965     min_prio="lsb-release"
  966     for entry in $min_prio; do
  967         if [ "$(echo "${primary_release_files}" | grep "$entry")" != "" ]; then
  968             primary_release_files=$(echo "${primary_release_files}" | sed -e "s:\\(.*\\)\\($entry\\)\\(.*\\):\\1 \\3 \\2:g")
  969         fi
  970     done
  971 
  972     # Echo the results collapsing multiple white-space into a single white-space
  973     echo "${primary_release_files} ${secondary_release_files}" | sed -E 's:[[:space:]]+:\n:g'
  974 }
  975 
  976 
  977 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
  978 #          NAME:  __gather_linux_system_info
  979 #   DESCRIPTION:  Discover Linux system information
  980 #----------------------------------------------------------------------------------------------------------------------
  981 __gather_linux_system_info() {
  982     DISTRO_NAME=""
  983     DISTRO_VERSION=""
  984 
  985     # Let's test if the lsb_release binary is available
  986     rv=$(lsb_release >/dev/null 2>&1)
  987 
  988     # shellcheck disable=SC2181
  989     if [ $? -eq 0 ]; then
  990         DISTRO_NAME=$(lsb_release -si)
  991         if [ "${DISTRO_NAME}" = "Scientific" ]; then
  992             DISTRO_NAME="Scientific Linux"
  993         elif [ "$(echo "$DISTRO_NAME" | grep ^CloudLinux)" != "" ]; then
  994             DISTRO_NAME="Cloud Linux"
  995         elif [ "$(echo "$DISTRO_NAME" | grep ^RedHat)" != "" ]; then
  996             # Let's convert 'CamelCased' to 'Camel Cased'
  997             n=$(__camelcase_split "$DISTRO_NAME")
  998             # Skip setting DISTRO_NAME this time, splitting CamelCase has failed.
  999             # See https://github.com/saltstack/salt-bootstrap/issues/918
 1000             [ "$n" = "$DISTRO_NAME" ] && DISTRO_NAME="" || DISTRO_NAME="$n"
 1001         elif [ "$( echo "${DISTRO_NAME}" | grep openSUSE )" != "" ]; then
 1002             # lsb_release -si returns "openSUSE Tumbleweed" on openSUSE tumbleweed
 1003             # lsb_release -si returns "openSUSE project" on openSUSE 12.3
 1004             # lsb_release -si returns "openSUSE" on openSUSE 15.n
 1005             DISTRO_NAME="opensuse"
 1006         elif [ "${DISTRO_NAME}" = "SUSE LINUX" ]; then
 1007             if [ "$(lsb_release -sd | grep -i opensuse)" != "" ]; then
 1008                 # openSUSE 12.2 reports SUSE LINUX on lsb_release -si
 1009                 DISTRO_NAME="opensuse"
 1010             else
 1011                 # lsb_release -si returns "SUSE LINUX" on SLES 11 SP3
 1012                 DISTRO_NAME="suse"
 1013             fi
 1014         elif [ "${DISTRO_NAME}" = "EnterpriseEnterpriseServer" ]; then
 1015             # This the Oracle Linux Enterprise ID before ORACLE LINUX 5 UPDATE 3
 1016             DISTRO_NAME="Oracle Linux"
 1017         elif [ "${DISTRO_NAME}" = "OracleServer" ]; then
 1018             # This the Oracle Linux Server 6.5
 1019             DISTRO_NAME="Oracle Linux"
 1020         elif [ "${DISTRO_NAME}" = "AmazonAMI" ] || [ "${DISTRO_NAME}" = "Amazon" ]; then
 1021             DISTRO_NAME="Amazon Linux AMI"
 1022         elif [ "${DISTRO_NAME}" = "ManjaroLinux" ]; then
 1023             DISTRO_NAME="Arch Linux"
 1024         elif [ "${DISTRO_NAME}" = "Arch" ]; then
 1025             DISTRO_NAME="Arch Linux"
 1026             return
 1027         fi
 1028         rv=$(lsb_release -sr)
 1029         [ "${rv}" != "" ] && DISTRO_VERSION=$(__parse_version_string "$rv")
 1030     elif [ -f /etc/lsb-release ]; then
 1031         # We don't have the lsb_release binary, though, we do have the file it parses
 1032         DISTRO_NAME=$(grep DISTRIB_ID /etc/lsb-release | sed -e 's/.*=//')
 1033         rv=$(grep DISTRIB_RELEASE /etc/lsb-release | sed -e 's/.*=//')
 1034         [ "${rv}" != "" ] && DISTRO_VERSION=$(__parse_version_string "$rv")
 1035     fi
 1036 
 1037     if [ "$DISTRO_NAME" != "" ] && [ "$DISTRO_VERSION" != "" ]; then
 1038         # We already have the distribution name and version
 1039         return
 1040     fi
 1041     # shellcheck disable=SC2035,SC2086
 1042     for rsource in $(__sort_release_files "$(
 1043             cd /etc && /bin/ls *[_-]release *[_-]version 2>/dev/null | env -i sort | \
 1044             sed -e '/^redhat-release$/d' -e '/^lsb-release$/d'; \
 1045             echo redhat-release lsb-release
 1046             )"); do
 1047 
 1048         [ ! -f "/etc/${rsource}" ] && continue      # Does not exist
 1049 
 1050         n=$(echo "${rsource}" | sed -e 's/[_-]release$//' -e 's/[_-]version$//')
 1051         shortname=$(echo "${n}" | tr '[:upper:]' '[:lower:]')
 1052         if [ "$shortname" = "debian" ]; then
 1053             rv=$(__derive_debian_numeric_version "$(cat /etc/${rsource})")
 1054         else
 1055             rv=$( (grep VERSION "/etc/${rsource}"; cat "/etc/${rsource}") | grep '[0-9]' | sed -e 'q' )
 1056         fi
 1057         [ "${rv}" = "" ] && [ "$shortname" != "arch" ] && continue  # There's no version information. Continue to next rsource
 1058         v=$(__parse_version_string "$rv")
 1059         case $shortname in
 1060             redhat             )
 1061                 if [ "$(grep -E 'CentOS' /etc/${rsource})" != "" ]; then
 1062                     n="CentOS"
 1063                 elif [ "$(grep -E 'Scientific' /etc/${rsource})" != "" ]; then
 1064                     n="Scientific Linux"
 1065                 elif [ "$(grep -E 'Red Hat Enterprise Linux' /etc/${rsource})" != "" ]; then
 1066                     n="<R>ed <H>at <E>nterprise <L>inux"
 1067                 else
 1068                     n="<R>ed <H>at <L>inux"
 1069                 fi
 1070                 ;;
 1071             arch               ) n="Arch Linux"     ;;
 1072             alpine             ) n="Alpine Linux"   ;;
 1073             centos             ) n="CentOS"         ;;
 1074             debian             ) n="Debian"         ;;
 1075             ubuntu             ) n="Ubuntu"         ;;
 1076             fedora             ) n="Fedora"         ;;
 1077             suse|opensuse      ) n="SUSE"           ;;
 1078             mandrake*|mandriva ) n="Mandriva"       ;;
 1079             gentoo             ) n="Gentoo"         ;;
 1080             slackware          ) n="Slackware"      ;;
 1081             turbolinux         ) n="TurboLinux"     ;;
 1082             unitedlinux        ) n="UnitedLinux"    ;;
 1083             void               ) n="VoidLinux"      ;;
 1084             oracle             ) n="Oracle Linux"   ;;
 1085             system             )
 1086                 while read -r line; do
 1087                     [ "${n}x" != "systemx" ] && break
 1088                     case "$line" in
 1089                         *Amazon*Linux*AMI*)
 1090                             n="Amazon Linux AMI"
 1091                             break
 1092                     esac
 1093                 done < "/etc/${rsource}"
 1094                 ;;
 1095             os                 )
 1096                 nn="$(__unquote_string "$(grep '^ID=' /etc/os-release | sed -e 's/^ID=\(.*\)$/\1/g')")"
 1097                 rv="$(__unquote_string "$(grep '^VERSION_ID=' /etc/os-release | sed -e 's/^VERSION_ID=\(.*\)$/\1/g')")"
 1098                 [ "${rv}" != "" ] && v=$(__parse_version_string "$rv") || v=""
 1099                 case $(echo "${nn}" | tr '[:upper:]' '[:lower:]') in
 1100                     alpine      )
 1101                         n="Alpine Linux"
 1102                         v="${rv}"
 1103                         ;;
 1104                     amzn        )
 1105                         # Amazon AMI's after 2014.09 match here
 1106                         n="Amazon Linux AMI"
 1107                         ;;
 1108                     arch        )
 1109                         n="Arch Linux"
 1110                         v=""  # Arch Linux does not provide a version.
 1111                         ;;
 1112                     cloudlinux  )
 1113                         n="Cloud Linux"
 1114                         ;;
 1115                     debian      )
 1116                         n="Debian"
 1117                         v=$(__derive_debian_numeric_version "$v")
 1118                         ;;
 1119                     sles  )
 1120                         n="SUSE"
 1121                         v="${rv}"
 1122                         ;;
 1123                     opensuse-* )
 1124                         n="opensuse"
 1125                         v="${rv}"
 1126                         ;;
 1127                     *           )
 1128                         n=${nn}
 1129                         ;;
 1130                 esac
 1131                 ;;
 1132             *                  ) n="${n}"           ;
 1133         esac
 1134         DISTRO_NAME=$n
 1135         DISTRO_VERSION=$v
 1136         break
 1137     done
 1138 }
 1139 
 1140 
 1141 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1142 #          NAME:  __install_python()
 1143 #   DESCRIPTION:  Install a different version of python on a host. Currently this has only been tested on CentOS 6 and
 1144 #                 is considered experimental.
 1145 #----------------------------------------------------------------------------------------------------------------------
 1146 __install_python() {
 1147     if [ "$_PY_EXE" = "" ]; then
 1148         echoerror "Must specify -x <pythonversion> with -y to install a specific python version"
 1149         exit 1
 1150     fi
 1151 
 1152     __PACKAGES="$_PY_PKG_VER"
 1153 
 1154     if [ ${_DISABLE_REPOS} -eq ${BS_FALSE} ]; then
 1155         echoinfo "Attempting to install a repo to help provide a separate python package"
 1156         echoinfo "$DISTRO_NAME_L"
 1157         case "$DISTRO_NAME_L" in
 1158             "red_hat"|"centos")
 1159                 __PYTHON_REPO_URL="https://repo.ius.io/ius-release-el${DISTRO_MAJOR_VERSION}.rpm"
 1160                 ;;
 1161             *)
 1162                 echoerror "Installing a repo to provide a python package is only supported on Redhat/CentOS.
 1163                 If a repo is already available, please try running script with -r."
 1164                 exit 1
 1165                 ;;
 1166         esac
 1167 
 1168         echoinfo "Installing IUS repo"
 1169         __yum_install_noinput "${__PYTHON_REPO_URL}" || return 1
 1170     fi
 1171 
 1172     echoinfo "Installing ${__PACKAGES}"
 1173     __yum_install_noinput "${__PACKAGES}" || return 1
 1174 }
 1175 
 1176 
 1177 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1178 #          NAME:  __gather_sunos_system_info
 1179 #   DESCRIPTION:  Discover SunOS system info
 1180 #----------------------------------------------------------------------------------------------------------------------
 1181 __gather_sunos_system_info() {
 1182     if [ -f /sbin/uname ]; then
 1183         DISTRO_VERSION=$(/sbin/uname -X | awk '/[kK][eE][rR][nN][eE][lL][iI][dD]/ { print $3 }')
 1184     fi
 1185 
 1186     DISTRO_NAME=""
 1187     if [ -f /etc/release ]; then
 1188         while read -r line; do
 1189             [ "${DISTRO_NAME}" != "" ] && break
 1190             case "$line" in
 1191                 *OpenIndiana*oi_[0-9]*)
 1192                     DISTRO_NAME="OpenIndiana"
 1193                     DISTRO_VERSION=$(echo "$line" | sed -nE "s/OpenIndiana(.*)oi_([[:digit:]]+)(.*)/\\2/p")
 1194                     break
 1195                     ;;
 1196                 *OpenSolaris*snv_[0-9]*)
 1197                     DISTRO_NAME="OpenSolaris"
 1198                     DISTRO_VERSION=$(echo "$line" | sed -nE "s/OpenSolaris(.*)snv_([[:digit:]]+)(.*)/\\2/p")
 1199                     break
 1200                     ;;
 1201                 *Oracle*Solaris*[0-9]*)
 1202                     DISTRO_NAME="Oracle Solaris"
 1203                     DISTRO_VERSION=$(echo "$line" | sed -nE "s/(Oracle Solaris) ([[:digit:]]+)(.*)/\\2/p")
 1204                     break
 1205                     ;;
 1206                 *Solaris*)
 1207                     DISTRO_NAME="Solaris"
 1208                     # Let's make sure we not actually on a Joyent's SmartOS VM since some releases
 1209                     # don't have SmartOS in `/etc/release`, only `Solaris`
 1210                     if uname -v | grep joyent >/dev/null 2>&1; then
 1211                         DISTRO_NAME="SmartOS"
 1212                     fi
 1213                     break
 1214                     ;;
 1215                 *NexentaCore*)
 1216                     DISTRO_NAME="Nexenta Core"
 1217                     break
 1218                     ;;
 1219                 *SmartOS*)
 1220                     DISTRO_NAME="SmartOS"
 1221                     break
 1222                     ;;
 1223                 *OmniOS*)
 1224                     DISTRO_NAME="OmniOS"
 1225                     DISTRO_VERSION=$(echo "$line" | awk '{print $3}')
 1226                     _SIMPLIFY_VERSION=$BS_FALSE
 1227                     break
 1228                     ;;
 1229             esac
 1230         done < /etc/release
 1231     fi
 1232 
 1233     if [ "${DISTRO_NAME}" = "" ]; then
 1234         DISTRO_NAME="Solaris"
 1235         DISTRO_VERSION=$(
 1236             echo "${OS_VERSION}" |
 1237             sed -e 's;^4\.;1.;' \
 1238                 -e 's;^5\.\([0-6]\)[^0-9]*$;2.\1;' \
 1239                 -e 's;^5\.\([0-9][0-9]*\).*;\1;'
 1240         )
 1241     fi
 1242 
 1243     if [ "${DISTRO_NAME}" = "SmartOS" ]; then
 1244         VIRTUAL_TYPE="smartmachine"
 1245         if [ "$(zonename)" = "global" ]; then
 1246             VIRTUAL_TYPE="global"
 1247         fi
 1248     fi
 1249 }
 1250 
 1251 
 1252 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1253 #          NAME:  __gather_bsd_system_info
 1254 #   DESCRIPTION:  Discover OpenBSD, NetBSD and FreeBSD systems information
 1255 #----------------------------------------------------------------------------------------------------------------------
 1256 __gather_bsd_system_info() {
 1257     DISTRO_NAME=${OS_NAME}
 1258     DISTRO_VERSION=$(echo "${OS_VERSION}" | sed -e 's;[()];;' -e 's/-.*$//')
 1259 }
 1260 
 1261 
 1262 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1263 #          NAME:  __gather_osx_system_info
 1264 #   DESCRIPTION:  Discover MacOS X
 1265 #----------------------------------------------------------------------------------------------------------------------
 1266 __gather_osx_system_info() {
 1267     DISTRO_NAME="MacOSX"
 1268     DISTRO_VERSION=$(sw_vers -productVersion)
 1269 }
 1270 
 1271 
 1272 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1273 #          NAME:  __gather_system_info
 1274 #   DESCRIPTION:  Discover which system and distribution we are running.
 1275 #----------------------------------------------------------------------------------------------------------------------
 1276 __gather_system_info() {
 1277     case ${OS_NAME_L} in
 1278         linux )
 1279             __gather_linux_system_info
 1280             ;;
 1281         sunos )
 1282             __gather_sunos_system_info
 1283             ;;
 1284         openbsd|freebsd|netbsd )
 1285             __gather_bsd_system_info
 1286             ;;
 1287         darwin )
 1288             __gather_osx_system_info
 1289             ;;
 1290         * )
 1291             echoerror "${OS_NAME} not supported.";
 1292             exit 1
 1293             ;;
 1294     esac
 1295 
 1296 }
 1297 
 1298 
 1299 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1300 #          NAME:  __ubuntu_derivatives_translation
 1301 #   DESCRIPTION:  Map Ubuntu derivatives to their Ubuntu base versions.
 1302 #                 If distro has a known Ubuntu base version, use those install
 1303 #                 functions by pretending to be Ubuntu (i.e. change global vars)
 1304 #----------------------------------------------------------------------------------------------------------------------
 1305 # shellcheck disable=SC2034
 1306 __ubuntu_derivatives_translation() {
 1307     UBUNTU_DERIVATIVES="(trisquel|linuxmint|linaro|elementary_os|neon)"
 1308     # Mappings
 1309     trisquel_6_ubuntu_base="12.04"
 1310     linuxmint_13_ubuntu_base="12.04"
 1311     linuxmint_17_ubuntu_base="14.04"
 1312     linuxmint_18_ubuntu_base="16.04"
 1313     linuxmint_19_ubuntu_base="18.04"
 1314     linuxmint_20_ubuntu_base="20.04"
 1315     linaro_12_ubuntu_base="12.04"
 1316     elementary_os_02_ubuntu_base="12.04"
 1317     neon_16_ubuntu_base="16.04"
 1318     neon_18_ubuntu_base="18.04"
 1319     neon_20_ubuntu_base="20.04"
 1320 
 1321     # Translate Ubuntu derivatives to their base Ubuntu version
 1322     match=$(echo "$DISTRO_NAME_L" | grep -E ${UBUNTU_DERIVATIVES})
 1323 
 1324     if [ "${match}" != "" ]; then
 1325         case $match in
 1326             "elementary_os")
 1327                 _major=$(echo "$DISTRO_VERSION" | sed 's/\.//g')
 1328                 ;;
 1329             "linuxmint")
 1330                 export LSB_ETC_LSB_RELEASE=/etc/upstream-release/lsb-release
 1331                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1332                 ;;
 1333             *)
 1334                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1335                 ;;
 1336         esac
 1337 
 1338         _ubuntu_version=$(eval echo "\$${match}_${_major}_ubuntu_base")
 1339 
 1340         if [ "$_ubuntu_version" != "" ]; then
 1341             echodebug "Detected Ubuntu $_ubuntu_version derivative"
 1342             DISTRO_NAME_L="ubuntu"
 1343             DISTRO_VERSION="$_ubuntu_version"
 1344         fi
 1345     fi
 1346 }
 1347 
 1348 
 1349 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1350 #          NAME:  __check_dpkg_architecture
 1351 #   DESCRIPTION:  Determine the primary architecture for packages to install on Debian and derivatives
 1352 #                 and issue all necessary error messages.
 1353 #----------------------------------------------------------------------------------------------------------------------
 1354 __check_dpkg_architecture() {
 1355     if __check_command_exists dpkg; then
 1356         DPKG_ARCHITECTURE="$(dpkg --print-architecture)"
 1357     else
 1358         echoerror "dpkg: command not found."
 1359         return 1
 1360     fi
 1361 
 1362     __REPO_ARCH="$DPKG_ARCHITECTURE"
 1363     __REPO_ARCH_DEB='deb'
 1364     __return_code=0
 1365 
 1366     case $DPKG_ARCHITECTURE in
 1367         "i386")
 1368             error_msg="$_REPO_URL likely doesn't have all required 32-bit packages for $DISTRO_NAME $DISTRO_MAJOR_VERSION."
 1369             # amd64 is just a part of repository URI, 32-bit pkgs are hosted under the same location
 1370             __REPO_ARCH="amd64"
 1371             ;;
 1372         "amd64")
 1373             error_msg=""
 1374             ;;
 1375         "arm64")
 1376             if [ "$_CUSTOM_REPO_URL" != "null" ]; then
 1377                 warn_msg="Support for arm64 is experimental, make sure the custom repository used has the expected structure and contents."
 1378             else
 1379                 # Saltstack official repository does not yet have arm64 metadata,
 1380                 # use amd64 repositories on arm64, since all pkgs are arch-independent
 1381                 __REPO_ARCH="amd64"
 1382                 __REPO_ARCH_DEB="deb [arch=$__REPO_ARCH]"
 1383                 warn_msg="Support for arm64 packages is experimental and might rely on architecture-independent packages from the amd64 repository."
 1384             fi
 1385             error_msg=""
 1386             ;;
 1387         "armhf")
 1388             if [ "$DISTRO_NAME_L" = "ubuntu" ] || [ "$DISTRO_MAJOR_VERSION" -lt 8 ]; then
 1389                 error_msg="Support for armhf packages at $_REPO_URL is limited to Debian/Raspbian 8 platforms."
 1390                 __return_code=1
 1391             else
 1392                 error_msg=""
 1393             fi
 1394             ;;
 1395         *)
 1396             error_msg="$_REPO_URL doesn't have packages for your system architecture: $DPKG_ARCHITECTURE."
 1397             __return_code=1
 1398             ;;
 1399     esac
 1400 
 1401     if [ "${warn_msg:-}" != "" ]; then
 1402         # AArch64: Do not fail at this point, but warn the user about experimental support
 1403         # See https://github.com/saltstack/salt-bootstrap/issues/1240
 1404         echowarn "${warn_msg}"
 1405     fi
 1406     if [ "${error_msg}" != "" ]; then
 1407         echoerror "${error_msg}"
 1408         if [ "$ITYPE" != "git" ]; then
 1409             echoerror "You can try git installation mode, i.e.: sh ${__ScriptName} git v2017.7.2."
 1410             echoerror "It may be necessary to use git installation mode with pip and disable the SaltStack apt repository."
 1411             echoerror "For example:"
 1412             echoerror "    sh ${__ScriptName} -r -P git v2017.7.2"
 1413         fi
 1414     fi
 1415 
 1416     if [ "${__return_code}" -eq 0 ]; then
 1417         return 0
 1418     else
 1419         return 1
 1420     fi
 1421 }
 1422 
 1423 
 1424 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1425 #          NAME:  __ubuntu_codename_translation
 1426 #   DESCRIPTION:  Map Ubuntu major versions to their corresponding codenames
 1427 #----------------------------------------------------------------------------------------------------------------------
 1428 # shellcheck disable=SC2034
 1429 __ubuntu_codename_translation() {
 1430     case $DISTRO_MINOR_VERSION in
 1431         "04")
 1432             _april="yes"
 1433             ;;
 1434         "10")
 1435             _april=""
 1436             ;;
 1437         *)
 1438             _april="yes"
 1439             ;;
 1440     esac
 1441 
 1442     case $DISTRO_MAJOR_VERSION in
 1443         "12")
 1444             DISTRO_CODENAME="precise"
 1445             ;;
 1446         "14")
 1447             DISTRO_CODENAME="trusty"
 1448             ;;
 1449         "16")
 1450             DISTRO_CODENAME="xenial"
 1451             ;;
 1452         "18")
 1453             DISTRO_CODENAME="bionic"
 1454             ;;
 1455         "20")
 1456             DISTRO_CODENAME="focal"
 1457             ;;
 1458         *)
 1459             DISTRO_CODENAME="trusty"
 1460             ;;
 1461     esac
 1462 }
 1463 
 1464 
 1465 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1466 #          NAME:  __debian_derivatives_translation
 1467 #   DESCRIPTION:  Map Debian derivatives to their Debian base versions.
 1468 #                 If distro has a known Debian base version, use those install
 1469 #                 functions by pretending to be Debian (i.e. change global vars)
 1470 #----------------------------------------------------------------------------------------------------------------------
 1471 # shellcheck disable=SC2034
 1472 __debian_derivatives_translation() {
 1473     # If the file does not exist, return
 1474     [ ! -f /etc/os-release ] && return
 1475 
 1476     DEBIAN_DERIVATIVES="(cumulus|devuan|kali|linuxmint|raspbian|bunsenlabs|turnkey)"
 1477     # Mappings
 1478     cumulus_2_debian_base="7.0"
 1479     cumulus_3_debian_base="8.0"
 1480     cumulus_4_debian_base="10.0"
 1481     devuan_1_debian_base="8.0"
 1482     devuan_2_debian_base="9.0"
 1483     kali_1_debian_base="7.0"
 1484     linuxmint_1_debian_base="8.0"
 1485     raspbian_8_debian_base="8.0"
 1486     raspbian_9_debian_base="9.0"
 1487     raspbian_10_debian_base="10.0"
 1488     bunsenlabs_9_debian_base="9.0"
 1489     turnkey_9_debian_base="9.0"
 1490 
 1491     # Translate Debian derivatives to their base Debian version
 1492     match=$(echo "$DISTRO_NAME_L" | grep -E ${DEBIAN_DERIVATIVES})
 1493 
 1494     if [ "${match}" != "" ]; then
 1495         case $match in
 1496             cumulus*)
 1497                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1498                 _debian_derivative="cumulus"
 1499                 ;;
 1500             devuan)
 1501                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1502                 _debian_derivative="devuan"
 1503                 ;;
 1504             kali)
 1505                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1506                 _debian_derivative="kali"
 1507                 ;;
 1508             linuxmint)
 1509                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1510                 _debian_derivative="linuxmint"
 1511                 ;;
 1512             raspbian)
 1513                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1514                 _debian_derivative="raspbian"
 1515                 ;;
 1516             bunsenlabs)
 1517                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1518                 _debian_derivative="bunsenlabs"
 1519                 ;;
 1520             turnkey)
 1521                 _major=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1522                 _debian_derivative="turnkey"
 1523                 ;;
 1524         esac
 1525 
 1526         _debian_version=$(eval echo "\$${_debian_derivative}_${_major}_debian_base" 2>/dev/null)
 1527 
 1528         if [ "$_debian_version" != "" ]; then
 1529             echodebug "Detected Debian $_debian_version derivative"
 1530             DISTRO_NAME_L="debian"
 1531             DISTRO_VERSION="$_debian_version"
 1532             DISTRO_MAJOR_VERSION="$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')"
 1533         fi
 1534     fi
 1535 }
 1536 
 1537 
 1538 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1539 #          NAME:  __debian_codename_translation
 1540 #   DESCRIPTION:  Map Debian major versions to their corresponding code names
 1541 #----------------------------------------------------------------------------------------------------------------------
 1542 # shellcheck disable=SC2034
 1543 __debian_codename_translation() {
 1544 
 1545     case $DISTRO_MAJOR_VERSION in
 1546         "7")
 1547             DISTRO_CODENAME="wheezy"
 1548             ;;
 1549         "8")
 1550             DISTRO_CODENAME="jessie"
 1551             ;;
 1552         "9")
 1553             DISTRO_CODENAME="stretch"
 1554             ;;
 1555         "10")
 1556             DISTRO_CODENAME="buster"
 1557             ;;
 1558         *)
 1559             DISTRO_CODENAME="jessie"
 1560             ;;
 1561     esac
 1562 }
 1563 
 1564 
 1565 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1566 #          NAME:  __check_end_of_life_versions
 1567 #   DESCRIPTION:  Check for end of life distribution versions
 1568 #----------------------------------------------------------------------------------------------------------------------
 1569 __check_end_of_life_versions() {
 1570     case "${DISTRO_NAME_L}" in
 1571         debian)
 1572             # Debian versions below 7 are not supported
 1573             if [ "$DISTRO_MAJOR_VERSION" -lt 8 ]; then
 1574                 echoerror "End of life distributions are not supported."
 1575                 echoerror "Please consider upgrading to the next stable. See:"
 1576                 echoerror "    https://wiki.debian.org/DebianReleases"
 1577                 exit 1
 1578             fi
 1579             ;;
 1580 
 1581         ubuntu)
 1582             # Ubuntu versions not supported
 1583             #
 1584             #  < 14.04
 1585             #  = 14.10
 1586             #  = 15.04, 15.10
 1587             #  = 16.10
 1588             #  = 17.04, 17.10
 1589             if [ "$DISTRO_MAJOR_VERSION" -lt 14 ] || \
 1590                 [ "$DISTRO_MAJOR_VERSION" -eq 15 ] || \
 1591                 [ "$DISTRO_MAJOR_VERSION" -eq 17 ] || \
 1592                 { [ "$DISTRO_MAJOR_VERSION" -eq 16 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]; }; then
 1593                 echoerror "End of life distributions are not supported."
 1594                 echoerror "Please consider upgrading to the next stable. See:"
 1595                 echoerror "    https://wiki.ubuntu.com/Releases"
 1596                 exit 1
 1597             fi
 1598             ;;
 1599 
 1600         opensuse)
 1601             # openSUSE versions not supported
 1602             #
 1603             #  <= 13.X
 1604             #  <= 42.2
 1605             if [ "$DISTRO_MAJOR_VERSION" -lt 15 ] || \
 1606                 { [ "$DISTRO_MAJOR_VERSION" -eq 42 ] && [ "$DISTRO_MINOR_VERSION" -le 2 ]; }; then
 1607                 echoerror "End of life distributions are not supported."
 1608                 echoerror "Please consider upgrading to the next stable. See:"
 1609                 echoerror "    http://en.opensuse.org/Lifetime"
 1610                 exit 1
 1611             fi
 1612             ;;
 1613 
 1614         suse)
 1615             # SuSE versions not supported
 1616             #
 1617             # < 11 SP4
 1618             # < 12 SP2
 1619             # < 15 SP1
 1620             SUSE_PATCHLEVEL=$(awk -F'=' '/VERSION_ID/ { print $2 }' /etc/os-release | grep -oP "\.\K\w+")
 1621             if [ "${SUSE_PATCHLEVEL}" = "" ]; then
 1622                 SUSE_PATCHLEVEL="00"
 1623             fi
 1624             if [ "$DISTRO_MAJOR_VERSION" -lt 11 ] || \
 1625                 { [ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$SUSE_PATCHLEVEL" -lt 04 ]; } || \
 1626                 { [ "$DISTRO_MAJOR_VERSION" -eq 15 ] && [ "$SUSE_PATCHLEVEL" -lt 01 ]; } || \
 1627                 { [ "$DISTRO_MAJOR_VERSION" -eq 12 ] && [ "$SUSE_PATCHLEVEL" -lt 02 ]; }; then
 1628                 echoerror "Versions lower than SuSE 11 SP4, 12 SP2 or 15 SP1 are not supported."
 1629                 echoerror "Please consider upgrading to the next stable"
 1630                 echoerror "    https://www.suse.com/lifecycle/"
 1631                 exit 1
 1632             fi
 1633             ;;
 1634 
 1635         fedora)
 1636             # Fedora lower than 27 are no longer supported
 1637             if [ "$DISTRO_MAJOR_VERSION" -lt 30 ]; then
 1638                 echoerror "End of life distributions are not supported."
 1639                 echoerror "Please consider upgrading to the next stable. See:"
 1640                 echoerror "    https://fedoraproject.org/wiki/Releases"
 1641                 exit 1
 1642             fi
 1643             ;;
 1644 
 1645         centos)
 1646             # CentOS versions lower than 6 are no longer supported
 1647             if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then
 1648                 echoerror "End of life distributions are not supported."
 1649                 echoerror "Please consider upgrading to the next stable. See:"
 1650                 echoerror "    http://wiki.centos.org/Download"
 1651                 exit 1
 1652             fi
 1653             ;;
 1654 
 1655         red_hat*linux)
 1656             # Red Hat (Enterprise) Linux versions lower than 6 are no longer supported
 1657             if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then
 1658                 echoerror "End of life distributions are not supported."
 1659                 echoerror "Please consider upgrading to the next stable. See:"
 1660                 echoerror "    https://access.redhat.com/support/policy/updates/errata/"
 1661                 exit 1
 1662             fi
 1663             ;;
 1664 
 1665         oracle*linux)
 1666             # Oracle Linux versions lower than 6 are no longer supported
 1667             if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then
 1668                 echoerror "End of life distributions are not supported."
 1669                 echoerror "Please consider upgrading to the next stable. See:"
 1670                 echoerror "    http://www.oracle.com/us/support/library/elsp-lifetime-069338.pdf"
 1671                 exit 1
 1672             fi
 1673             ;;
 1674 
 1675         scientific*linux)
 1676             # Scientific Linux versions lower than 6 are no longer supported
 1677             if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then
 1678                 echoerror "End of life distributions are not supported."
 1679                 echoerror "Please consider upgrading to the next stable. See:"
 1680                 echoerror "    https://www.scientificlinux.org/downloads/sl-versions/"
 1681                 exit 1
 1682             fi
 1683             ;;
 1684 
 1685         cloud*linux)
 1686             # Cloud Linux versions lower than 6 are no longer supported
 1687             if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then
 1688                 echoerror "End of life distributions are not supported."
 1689                 echoerror "Please consider upgrading to the next stable. See:"
 1690                 echoerror "    https://docs.cloudlinux.com/index.html?cloudlinux_life-cycle.html"
 1691                 exit 1
 1692             fi
 1693             ;;
 1694 
 1695         amazon*linux*ami)
 1696             # Amazon Linux versions lower than 2012.0X no longer supported
 1697             # Except for Amazon Linux 2, which reset the major version counter
 1698             if [ "$DISTRO_MAJOR_VERSION" -lt 2012 ] && [ "$DISTRO_MAJOR_VERSION" -gt 10 ]; then
 1699                 echoerror "End of life distributions are not supported."
 1700                 echoerror "Please consider upgrading to the next stable. See:"
 1701                 echoerror "    https://aws.amazon.com/amazon-linux-ami/"
 1702                 exit 1
 1703             fi
 1704             ;;
 1705 
 1706         freebsd)
 1707             # FreeBSD versions lower than 11 are EOL
 1708             if [ "$DISTRO_MAJOR_VERSION" -lt 11 ]; then
 1709                 echoerror "Versions lower than FreeBSD 11 are EOL and no longer supported."
 1710                 exit 1
 1711             fi
 1712             ;;
 1713 
 1714         *)
 1715             ;;
 1716     esac
 1717 }
 1718 
 1719 
 1720 __gather_system_info
 1721 
 1722 echo
 1723 echoinfo "System Information:"
 1724 echoinfo "  CPU:          ${CPU_VENDOR_ID}"
 1725 echoinfo "  CPU Arch:     ${CPU_ARCH}"
 1726 echoinfo "  OS Name:      ${OS_NAME}"
 1727 echoinfo "  OS Version:   ${OS_VERSION}"
 1728 echoinfo "  Distribution: ${DISTRO_NAME} ${DISTRO_VERSION}"
 1729 echo
 1730 
 1731 # Simplify distro name naming on functions
 1732 DISTRO_NAME_L=$(echo "$DISTRO_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-zA-Z0-9_ ]//g' | sed -Ee 's/([[:space:]])+/_/g' | sed -Ee 's/tumbleweed//' )
 1733 
 1734 # Simplify version naming on functions
 1735 if [ "$DISTRO_VERSION" = "" ] || [ ${_SIMPLIFY_VERSION} -eq $BS_FALSE ]; then
 1736     DISTRO_MAJOR_VERSION=""
 1737     DISTRO_MINOR_VERSION=""
 1738     PREFIXED_DISTRO_MAJOR_VERSION=""
 1739     PREFIXED_DISTRO_MINOR_VERSION=""
 1740 else
 1741     DISTRO_MAJOR_VERSION=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')
 1742     DISTRO_MINOR_VERSION=$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).\([0-9]*\).*/\2/g')
 1743     PREFIXED_DISTRO_MAJOR_VERSION="_${DISTRO_MAJOR_VERSION}"
 1744     if [ "${PREFIXED_DISTRO_MAJOR_VERSION}" = "_" ]; then
 1745         PREFIXED_DISTRO_MAJOR_VERSION=""
 1746     fi
 1747     PREFIXED_DISTRO_MINOR_VERSION="_${DISTRO_MINOR_VERSION}"
 1748     if [ "${PREFIXED_DISTRO_MINOR_VERSION}" = "_" ]; then
 1749         PREFIXED_DISTRO_MINOR_VERSION=""
 1750     fi
 1751 fi
 1752 
 1753 # For Ubuntu derivatives, pretend to be their Ubuntu base version
 1754 __ubuntu_derivatives_translation
 1755 
 1756 # For Debian derivates, pretend to be their Debian base version
 1757 __debian_derivatives_translation
 1758 
 1759 # Fail soon for end of life versions
 1760 __check_end_of_life_versions
 1761 
 1762 echodebug "Binaries will be searched using the following \$PATH: ${PATH}"
 1763 
 1764 # Let users know that we'll use a proxy
 1765 if [ "${_HTTP_PROXY}" != "" ]; then
 1766     echoinfo "Using http proxy $_HTTP_PROXY"
 1767 fi
 1768 
 1769 # Let users know what's going to be installed/configured
 1770 if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 1771     if [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
 1772         echoinfo "Installing minion"
 1773     else
 1774         echoinfo "Configuring minion"
 1775     fi
 1776 fi
 1777 
 1778 if [ "$_INSTALL_MASTER" -eq $BS_TRUE ]; then
 1779     if [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
 1780         echoinfo "Installing master"
 1781     else
 1782         echoinfo "Configuring master"
 1783     fi
 1784 fi
 1785 
 1786 if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ]; then
 1787     if [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
 1788         echoinfo "Installing syndic"
 1789     else
 1790         echoinfo "Configuring syndic"
 1791     fi
 1792 fi
 1793 
 1794 if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ] && [ "$_CONFIG_ONLY" -eq $BS_FALSE ]; then
 1795     echoinfo "Installing salt-cloud and required python-libcloud package"
 1796 fi
 1797 
 1798 if [ $_START_DAEMONS -eq $BS_FALSE ]; then
 1799     echoinfo "Daemons will not be started"
 1800 fi
 1801 
 1802 if [ "${DISTRO_NAME_L}" = "ubuntu" ]; then
 1803   # For ubuntu versions, obtain the codename from the release version
 1804   __ubuntu_codename_translation
 1805 elif [ "${DISTRO_NAME_L}" = "debian" ]; then
 1806   # For debian versions, obtain the codename from the release version
 1807   __debian_codename_translation
 1808 fi
 1809 
 1810 if [ "$(echo "${DISTRO_NAME_L}" | grep -E '(debian|ubuntu|centos|gentoo|red_hat|oracle|scientific|amazon|fedora|macosx)')" = "" ] && [ "$ITYPE" = "stable" ] && [ "$STABLE_REV" != "latest" ]; then
 1811     echoerror "${DISTRO_NAME} does not have major version pegged packages support"
 1812     exit 1
 1813 fi
 1814 
 1815 # Only RedHat based distros have testing support
 1816 if [ "${ITYPE}" = "testing" ]; then
 1817     if [ "$(echo "${DISTRO_NAME_L}" | grep -E '(centos|red_hat|amazon|oracle)')" = "" ]; then
 1818         echoerror "${DISTRO_NAME} does not have testing packages support"
 1819         exit 1
 1820     fi
 1821     _EPEL_REPO="epel-testing"
 1822 fi
 1823 
 1824 # Only Ubuntu has support for installing to virtualenvs
 1825 if [ "${DISTRO_NAME_L}" != "ubuntu" ] && [ "$_VIRTUALENV_DIR" != "null" ]; then
 1826     echoerror "${DISTRO_NAME} does not have -V support"
 1827     exit 1
 1828 fi
 1829 
 1830 # Only Ubuntu has support for pip installing all packages
 1831 if [ "${DISTRO_NAME_L}" != "ubuntu" ] && [ $_PIP_ALL -eq $BS_TRUE ]; then
 1832     echoerror "${DISTRO_NAME} does not have -a support"
 1833     exit 1
 1834 fi
 1835 
 1836 if [ "$ITYPE" = "git" ]; then
 1837 
 1838     if [ "${GIT_REV}" = "master" ]; then
 1839         _POST_NEON_INSTALL=$BS_TRUE
 1840         __TAG_REGEX_MATCH="MATCH"
 1841     else
 1842         case ${OS_NAME_L} in
 1843             openbsd|freebsd|netbsd|darwin )
 1844                 __NEW_VS_TAG_REGEX_MATCH=$(echo "${GIT_REV}" | sed -E 's/^(v?3[0-9]{3}(\.[0-9]{1,2})?).*$/MATCH/')
 1845                 if [ "$__NEW_VS_TAG_REGEX_MATCH" = "MATCH" ]; then
 1846                     _POST_NEON_INSTALL=$BS_TRUE
 1847                     __TAG_REGEX_MATCH="${__NEW_VS_TAG_REGEX_MATCH}"
 1848                     if [ "$(echo "${GIT_REV}" | cut -c -1)" != "v" ]; then
 1849                         # We do this to properly clone tags
 1850                         GIT_REV="v${GIT_REV}"
 1851                     fi
 1852                     echodebug "Post Neon Tag Regex Match On: ${GIT_REV}"
 1853                 else
 1854                     __TAG_REGEX_MATCH=$(echo "${GIT_REV}" | sed -E 's/^(v?[0-9]{1,4}\.[0-9]{1,2})(\.[0-9]{1,2})?.*$/MATCH/')
 1855                     echodebug "Pre Neon Tag Regex Match On: ${GIT_REV}"
 1856                 fi
 1857                 ;;
 1858             * )
 1859                 __NEW_VS_TAG_REGEX_MATCH=$(echo "${GIT_REV}" | sed 's/^.*\(v\?3[[:digit:]]\{3\}\(\.[[:digit:]]\{1,2\}\)\?\).*$/MATCH/')
 1860                 if [ "$__NEW_VS_TAG_REGEX_MATCH" = "MATCH" ]; then
 1861                     _POST_NEON_INSTALL=$BS_TRUE
 1862                     __TAG_REGEX_MATCH="${__NEW_VS_TAG_REGEX_MATCH}"
 1863                     if [ "$(echo "${GIT_REV}" | cut -c -1)" != "v" ]; then
 1864                         # We do this to properly clone tags
 1865                         GIT_REV="v${GIT_REV}"
 1866                     fi
 1867                     echodebug "Post Neon Tag Regex Match On: ${GIT_REV}"
 1868                 else
 1869                     __TAG_REGEX_MATCH=$(echo "${GIT_REV}" | sed 's/^.*\(v\?[[:digit:]]\{1,4\}\.[[:digit:]]\{1,2\}\)\(\.[[:digit:]]\{1,2\}\)\?.*$/MATCH/')
 1870                     echodebug "Pre Neon Tag Regex Match On: ${GIT_REV}"
 1871                 fi
 1872                 ;;
 1873         esac
 1874     fi
 1875 
 1876     if [ "$_POST_NEON_INSTALL" -eq $BS_TRUE ]; then
 1877         echo
 1878         echowarn "Post Neon git based installations will always install salt"
 1879         echowarn "and its dependencies using pip which will be upgraded to"
 1880         echowarn "at least v${_MINIMUM_PIP_VERSION}, and, in case the setuptools version is also"
 1881         echowarn "too old, it will be upgraded to at least v${_MINIMUM_SETUPTOOLS_VERSION}"
 1882         echo
 1883         echowarn "You have 10 seconds to cancel and stop the bootstrap process..."
 1884         echo
 1885         sleep 10
 1886         _PIP_ALLOWED=$BS_TRUE
 1887     fi
 1888 fi
 1889 
 1890 
 1891 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1892 #          NAME:  __function_defined
 1893 #   DESCRIPTION:  Checks if a function is defined within this scripts scope
 1894 #    PARAMETERS:  function name
 1895 #       RETURNS:  0 or 1 as in defined or not defined
 1896 #----------------------------------------------------------------------------------------------------------------------
 1897 __function_defined() {
 1898     FUNC_NAME=$1
 1899     if [ "$(command -v "$FUNC_NAME")" != "" ]; then
 1900         echoinfo "Found function $FUNC_NAME"
 1901         return 0
 1902     fi
 1903     echodebug "$FUNC_NAME not found...."
 1904     return 1
 1905 }
 1906 
 1907 
 1908 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1909 #          NAME:  __wait_for_apt
 1910 #   DESCRIPTION:  Check if any apt, apt-get, aptitude, or dpkg processes are running before
 1911 #                 calling these again. This is useful when these process calls are part of
 1912 #                 a boot process, such as on AWS AMIs. This func will wait until the boot
 1913 #                 process is finished so the script doesn't exit on a locked proc.
 1914 #----------------------------------------------------------------------------------------------------------------------
 1915 __wait_for_apt(){
 1916     # Timeout set at 15 minutes
 1917     WAIT_TIMEOUT=900
 1918 
 1919     # Run our passed in apt command
 1920     "${@}" 2>"$APT_ERR"
 1921     APT_RETURN=$?
 1922 
 1923     # Make sure we're not waiting on a lock
 1924     while [ $APT_RETURN -ne 0 ] && grep -q '^E: Could not get lock' "$APT_ERR"; do
 1925         echoinfo "Aware of the lock. Patiently waiting $WAIT_TIMEOUT more seconds..."
 1926         sleep 1
 1927         WAIT_TIMEOUT=$((WAIT_TIMEOUT - 1))
 1928 
 1929         if [ "$WAIT_TIMEOUT" -eq 0 ]; then
 1930             echoerror "Apt, apt-get, aptitude, or dpkg process is taking too long."
 1931             echoerror "Bootstrap script cannot proceed. Aborting."
 1932             return 1
 1933         else
 1934             "${@}" 2>"$APT_ERR"
 1935             APT_RETURN=$?
 1936         fi
 1937     done
 1938 
 1939     return $APT_RETURN
 1940 }
 1941 
 1942 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1943 #          NAME:  __apt_get_install_noinput
 1944 #   DESCRIPTION:  (DRY) apt-get install with noinput options
 1945 #    PARAMETERS:  packages
 1946 #----------------------------------------------------------------------------------------------------------------------
 1947 __apt_get_install_noinput() {
 1948     __wait_for_apt apt-get install -y -o DPkg::Options::=--force-confold "${@}"; return $?
 1949 }   # ----------  end of function __apt_get_install_noinput  ----------
 1950 
 1951 
 1952 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1953 #          NAME:  __apt_get_upgrade_noinput
 1954 #   DESCRIPTION:  (DRY) apt-get upgrade with noinput options
 1955 #----------------------------------------------------------------------------------------------------------------------
 1956 __apt_get_upgrade_noinput() {
 1957     __wait_for_apt apt-get upgrade -y -o DPkg::Options::=--force-confold; return $?
 1958 }   # ----------  end of function __apt_get_upgrade_noinput  ----------
 1959 
 1960 
 1961 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1962 #          NAME:  __temp_gpg_pub
 1963 #   DESCRIPTION:  Create a temporary file for downloading a GPG public key.
 1964 #----------------------------------------------------------------------------------------------------------------------
 1965 __temp_gpg_pub() {
 1966     if __check_command_exists mktemp; then
 1967         tempfile="$(mktemp /tmp/salt-gpg-XXXXXXXX.pub 2>/dev/null)"
 1968 
 1969         if [ -z "$tempfile" ]; then
 1970             echoerror "Failed to create temporary file in /tmp"
 1971             return 1
 1972         fi
 1973     else
 1974         tempfile="/tmp/salt-gpg-$$.pub"
 1975     fi
 1976 
 1977     echo $tempfile
 1978 }   # ----------- end of function __temp_gpg_pub  -----------
 1979 
 1980 
 1981 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 1982 #          NAME:  __apt_key_fetch
 1983 #   DESCRIPTION:  Download and import GPG public key for "apt-secure"
 1984 #    PARAMETERS:  url
 1985 #----------------------------------------------------------------------------------------------------------------------
 1986 __apt_key_fetch() {
 1987     url=$1
 1988 
 1989     tempfile="$(__temp_gpg_pub)"
 1990 
 1991     __fetch_url "$tempfile" "$url" || return 1
 1992     apt-key add "$tempfile" || return 1
 1993     rm -f "$tempfile"
 1994 
 1995     return 0
 1996 }   # ----------  end of function __apt_key_fetch  ----------
 1997 
 1998 
 1999 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2000 #          NAME:  __rpm_import_gpg
 2001 #   DESCRIPTION:  Download and import GPG public key to rpm database
 2002 #    PARAMETERS:  url
 2003 #----------------------------------------------------------------------------------------------------------------------
 2004 __rpm_import_gpg() {
 2005     url=$1
 2006 
 2007     tempfile="$(__temp_gpg_pub)"
 2008 
 2009     __fetch_url "$tempfile" "$url" || return 1
 2010 
 2011     # At least on CentOS 8, a missing newline at the end causes:
 2012     #   error: /tmp/salt-gpg-n1gKUb1u.pub: key 1 not an armored public key.
 2013     # shellcheck disable=SC1003,SC2086
 2014     sed -i -e '$a\' $tempfile
 2015 
 2016     rpm --import "$tempfile" || return 1
 2017     rm -f "$tempfile"
 2018 
 2019     return 0
 2020 }   # ----------  end of function __rpm_import_gpg  ----------
 2021 
 2022 
 2023 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2024 #          NAME:  __yum_install_noinput
 2025 #   DESCRIPTION:  (DRY) yum install with noinput options
 2026 #----------------------------------------------------------------------------------------------------------------------
 2027 __yum_install_noinput() {
 2028 
 2029     ENABLE_EPEL_CMD=""
 2030     # Skip Amazon Linux for the first round, since EPEL is no longer required.
 2031     # See issue #724
 2032     if [ $_DISABLE_REPOS -eq $BS_FALSE ] && [ "$DISTRO_NAME_L" != "amazon_linux_ami" ]; then
 2033         ENABLE_EPEL_CMD="--enablerepo=${_EPEL_REPO}"
 2034     fi
 2035 
 2036     if [ "$DISTRO_NAME_L" = "oracle_linux" ]; then
 2037         # We need to install one package at a time because --enablerepo=X disables ALL OTHER REPOS!!!!
 2038         for package in "${@}"; do
 2039             yum -y install "${package}" || yum -y install "${package}" ${ENABLE_EPEL_CMD} || return $?
 2040         done
 2041     else
 2042         yum -y install "${@}" ${ENABLE_EPEL_CMD} || return $?
 2043     fi
 2044 }   # ----------  end of function __yum_install_noinput  ----------
 2045 
 2046 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2047 #          NAME:  __dnf_install_noinput
 2048 #   DESCRIPTION:  (DRY) dnf install with noinput options
 2049 #----------------------------------------------------------------------------------------------------------------------
 2050 __dnf_install_noinput() {
 2051 
 2052     dnf -y install "${@}" || return $?
 2053 }   # ----------  end of function __dnf_install_noinput  ----------
 2054 
 2055 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2056 #          NAME:  __git_clone_and_checkout
 2057 #   DESCRIPTION:  (DRY) Helper function to clone and checkout salt to a
 2058 #                 specific revision.
 2059 #----------------------------------------------------------------------------------------------------------------------
 2060 __git_clone_and_checkout() {
 2061 
 2062     echodebug "Installed git version: $(git --version | awk '{ print $3 }')"
 2063     # Turn off SSL verification if -I flag was set for insecure downloads
 2064     if [ "$_INSECURE_DL" -eq $BS_TRUE ]; then
 2065         export GIT_SSL_NO_VERIFY=1
 2066     fi
 2067 
 2068     __SALT_GIT_CHECKOUT_PARENT_DIR=$(dirname "${_SALT_GIT_CHECKOUT_DIR}" 2>/dev/null)
 2069     __SALT_GIT_CHECKOUT_PARENT_DIR="${__SALT_GIT_CHECKOUT_PARENT_DIR:-/tmp/git}"
 2070     __SALT_CHECKOUT_REPONAME="$(basename "${_SALT_GIT_CHECKOUT_DIR}" 2>/dev/null)"
 2071     __SALT_CHECKOUT_REPONAME="${__SALT_CHECKOUT_REPONAME:-salt}"
 2072     [ -d "${__SALT_GIT_CHECKOUT_PARENT_DIR}" ] || mkdir "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
 2073     # shellcheck disable=SC2164
 2074     cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
 2075     if [ -d "${_SALT_GIT_CHECKOUT_DIR}" ]; then
 2076         echodebug "Found a checked out Salt repository"
 2077         # shellcheck disable=SC2164
 2078         cd "${_SALT_GIT_CHECKOUT_DIR}"
 2079         echodebug "Fetching git changes"
 2080         git fetch || return 1
 2081         # Tags are needed because of salt's versioning, also fetch that
 2082         echodebug "Fetching git tags"
 2083         git fetch --tags || return 1
 2084 
 2085         # If we have the SaltStack remote set as upstream, we also need to fetch the tags from there
 2086         if [ "$(git remote -v | grep $_SALTSTACK_REPO_URL)" != "" ]; then
 2087             echodebug "Fetching upstream(SaltStack's Salt repository) git tags"
 2088             git fetch --tags upstream
 2089         else
 2090             echoinfo "Adding SaltStack's Salt repository as a remote"
 2091             git remote add upstream "$_SALTSTACK_REPO_URL"
 2092             echodebug "Fetching upstream(SaltStack's Salt repository) git tags"
 2093             git fetch --tags upstream
 2094         fi
 2095 
 2096         echodebug "Hard reseting the cloned repository to ${GIT_REV}"
 2097         git reset --hard "$GIT_REV" || return 1
 2098 
 2099         # Just calling `git reset --hard $GIT_REV` on a branch name that has
 2100         # already been checked out will not update that branch to the upstream
 2101         # HEAD; instead it will simply reset to itself.  Check the ref to see
 2102         # if it is a branch name, check out the branch, and pull in the
 2103         # changes.
 2104         if git branch -a | grep -q "${GIT_REV}"; then
 2105             echodebug "Rebasing the cloned repository branch"
 2106             git pull --rebase || return 1
 2107         fi
 2108     else
 2109         if [ "$_FORCE_SHALLOW_CLONE" -eq "${BS_TRUE}" ]; then
 2110             echoinfo "Forced shallow cloning of git repository."
 2111             __SHALLOW_CLONE=$BS_TRUE
 2112         elif [ "$__TAG_REGEX_MATCH" = "MATCH" ]; then
 2113             echoinfo "Git revision matches a Salt version tag, shallow cloning enabled."
 2114             __SHALLOW_CLONE=$BS_TRUE
 2115         else
 2116             echowarn "The git revision being installed does not match a Salt version tag. Shallow cloning disabled"
 2117             __SHALLOW_CLONE=$BS_FALSE
 2118         fi
 2119 
 2120         if [ "$__SHALLOW_CLONE" -eq $BS_TRUE ]; then
 2121             # Let's try shallow cloning to speed up.
 2122             # Test for "--single-branch" option introduced in git 1.7.10, the minimal version of git where the shallow
 2123             # cloning we need actually works
 2124             if [ "$(git clone 2>&1 | grep 'single-branch')" != "" ]; then
 2125                 # The "--single-branch" option is supported, attempt shallow cloning
 2126                 echoinfo "Attempting to shallow clone $GIT_REV from Salt's repository ${_SALT_REPO_URL}"
 2127                 if git clone --depth 1 --branch "$GIT_REV" "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME"; then
 2128                     # shellcheck disable=SC2164
 2129                     cd "${_SALT_GIT_CHECKOUT_DIR}"
 2130                     __SHALLOW_CLONE=$BS_TRUE
 2131                 else
 2132                     # Shallow clone above failed(missing upstream tags???), let's resume the old behaviour.
 2133                     echowarn "Failed to shallow clone."
 2134                     echoinfo "Resuming regular git clone and remote SaltStack repository addition procedure"
 2135                     __SHALLOW_CLONE=$BS_FALSE
 2136                 fi
 2137             else
 2138                 echodebug "Shallow cloning not possible. Required git version not met."
 2139                 __SHALLOW_CLONE=$BS_FALSE
 2140             fi
 2141         fi
 2142 
 2143         if [ "$__SHALLOW_CLONE" -eq $BS_FALSE ]; then
 2144             git clone "$_SALT_REPO_URL" "$__SALT_CHECKOUT_REPONAME" || return 1
 2145             # shellcheck disable=SC2164
 2146             cd "${_SALT_GIT_CHECKOUT_DIR}"
 2147 
 2148             if ! echo "$_SALT_REPO_URL" | grep -q -F -w "${_SALTSTACK_REPO_URL#*://}"; then
 2149                 # We need to add the saltstack repository as a remote and fetch tags for proper versioning
 2150                 echoinfo "Adding SaltStack's Salt repository as a remote"
 2151                 git remote add upstream "$_SALTSTACK_REPO_URL" || return 1
 2152 
 2153                 echodebug "Fetching upstream (SaltStack's Salt repository) git tags"
 2154                 git fetch --tags upstream || return 1
 2155 
 2156                 # Check if GIT_REV is a remote branch or just a commit hash
 2157                 if git branch -r | grep -q -F -w "origin/$GIT_REV"; then
 2158                     GIT_REV="origin/$GIT_REV"
 2159                 fi
 2160             fi
 2161 
 2162             echodebug "Checking out $GIT_REV"
 2163             git checkout "$GIT_REV" || return 1
 2164         fi
 2165 
 2166     fi
 2167 
 2168     echoinfo "Cloning Salt's git repository succeeded"
 2169     return 0
 2170 }
 2171 
 2172 
 2173 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2174 #          NAME:  __copyfile
 2175 #   DESCRIPTION:  Simple function to copy files. Overrides if asked.
 2176 #----------------------------------------------------------------------------------------------------------------------
 2177 __copyfile() {
 2178     overwrite=$_FORCE_OVERWRITE
 2179     if [ $# -eq 2 ]; then
 2180         sfile=$1
 2181         dfile=$2
 2182     elif [ $# -eq 3 ]; then
 2183         sfile=$1
 2184         dfile=$2
 2185         overwrite=$3
 2186     else
 2187         echoerror "Wrong number of arguments for __copyfile()"
 2188         echoinfo "USAGE: __copyfile <source> <dest>  OR  __copyfile <source> <dest> <overwrite>"
 2189         exit 1
 2190     fi
 2191 
 2192     # Does the source file exist?
 2193     if [ ! -f "$sfile" ]; then
 2194         echowarn "$sfile does not exist!"
 2195         return 1
 2196     fi
 2197 
 2198     # If the destination is a directory, let's make it a full path so the logic
 2199     # below works as expected
 2200     if [ -d "$dfile" ]; then
 2201         echodebug "The passed destination ($dfile) is a directory"
 2202         dfile="${dfile}/$(basename "$sfile")"
 2203         echodebug "Full destination path is now: $dfile"
 2204     fi
 2205 
 2206     if [ ! -f "$dfile" ]; then
 2207         # The destination file does not exist, copy
 2208         echodebug "Copying $sfile to $dfile"
 2209         cp "$sfile" "$dfile" || return 1
 2210     elif [ -f "$dfile" ] && [ "$overwrite" -eq $BS_TRUE ]; then
 2211         # The destination exist and we're overwriting
 2212         echodebug "Overwriting $dfile with $sfile"
 2213         cp -f "$sfile" "$dfile" || return 1
 2214     elif [ -f "$dfile" ] && [ "$overwrite" -ne $BS_TRUE ]; then
 2215         echodebug "Not overwriting $dfile with $sfile"
 2216     fi
 2217     return 0
 2218 }
 2219 
 2220 
 2221 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2222 #          NAME:  __movefile
 2223 #   DESCRIPTION:  Simple function to move files. Overrides if asked.
 2224 #----------------------------------------------------------------------------------------------------------------------
 2225 __movefile() {
 2226     overwrite=$_FORCE_OVERWRITE
 2227     if [ $# -eq 2 ]; then
 2228         sfile=$1
 2229         dfile=$2
 2230     elif [ $# -eq 3 ]; then
 2231         sfile=$1
 2232         dfile=$2
 2233         overwrite=$3
 2234     else
 2235         echoerror "Wrong number of arguments for __movefile()"
 2236         echoinfo "USAGE: __movefile <source> <dest>  OR  __movefile <source> <dest> <overwrite>"
 2237         exit 1
 2238     fi
 2239 
 2240     if [ $_KEEP_TEMP_FILES -eq $BS_TRUE ]; then
 2241         # We're being told not to move files, instead copy them so we can keep
 2242         # them around
 2243         echodebug "Since BS_KEEP_TEMP_FILES=1 we're copying files instead of moving them"
 2244         __copyfile "$sfile" "$dfile" "$overwrite"
 2245         return $?
 2246     fi
 2247 
 2248     # Does the source file exist?
 2249     if [ ! -f "$sfile" ]; then
 2250         echowarn "$sfile does not exist!"
 2251         return 1
 2252     fi
 2253 
 2254     # If the destination is a directory, let's make it a full path so the logic
 2255     # below works as expected
 2256     if [ -d "$dfile" ]; then
 2257         echodebug "The passed destination($dfile) is a directory"
 2258         dfile="${dfile}/$(basename "$sfile")"
 2259         echodebug "Full destination path is now: $dfile"
 2260     fi
 2261 
 2262     if [ ! -f "$dfile" ]; then
 2263         # The destination file does not exist, move
 2264         echodebug "Moving $sfile to $dfile"
 2265         mv "$sfile" "$dfile" || return 1
 2266     elif [ -f "$dfile" ] && [ "$overwrite" -eq $BS_TRUE ]; then
 2267         # The destination exist and we're overwriting
 2268         echodebug "Overriding $dfile with $sfile"
 2269         mv -f "$sfile" "$dfile" || return 1
 2270     elif [ -f "$dfile" ] && [ "$overwrite" -ne $BS_TRUE ]; then
 2271         echodebug "Not overriding $dfile with $sfile"
 2272     fi
 2273 
 2274     return 0
 2275 }
 2276 
 2277 
 2278 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2279 #          NAME:  __linkfile
 2280 #   DESCRIPTION:  Simple function to create symlinks. Overrides if asked. Accepts globs.
 2281 #----------------------------------------------------------------------------------------------------------------------
 2282 __linkfile() {
 2283     overwrite=$_FORCE_OVERWRITE
 2284     if [ $# -eq 2 ]; then
 2285         target=$1
 2286         linkname=$2
 2287     elif [ $# -eq 3 ]; then
 2288         target=$1
 2289         linkname=$2
 2290         overwrite=$3
 2291     else
 2292         echoerror "Wrong number of arguments for __linkfile()"
 2293         echoinfo "USAGE: __linkfile <target> <link>  OR  __linkfile <tagret> <link> <overwrite>"
 2294         exit 1
 2295     fi
 2296 
 2297     for sfile in $target; do
 2298         # Does the source file exist?
 2299         if [ ! -f "$sfile" ]; then
 2300             echowarn "$sfile does not exist!"
 2301             return 1
 2302         fi
 2303 
 2304         # If the destination is a directory, let's make it a full path so the logic
 2305         # below works as expected
 2306         if [ -d "$linkname" ]; then
 2307             echodebug "The passed link name ($linkname) is a directory"
 2308             linkname="${linkname}/$(basename "$sfile")"
 2309             echodebug "Full destination path is now: $linkname"
 2310         fi
 2311 
 2312         if [ ! -e "$linkname" ]; then
 2313             # The destination file does not exist, create link
 2314             echodebug "Creating $linkname symlink pointing to $sfile"
 2315             ln -s "$sfile" "$linkname" || return 1
 2316         elif [ -e "$linkname" ] && [ "$overwrite" -eq $BS_TRUE ]; then
 2317             # The destination exist and we're overwriting
 2318             echodebug "Overwriting $linkname symlink to point on $sfile"
 2319             ln -sf "$sfile" "$linkname" || return 1
 2320         elif [ -e "$linkname" ] && [ "$overwrite" -ne $BS_TRUE ]; then
 2321             echodebug "Not overwriting $linkname symlink to point on $sfile"
 2322         fi
 2323     done
 2324 
 2325     return 0
 2326 }
 2327 
 2328 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2329 #          NAME:  __overwriteconfig()
 2330 #   DESCRIPTION:  Simple function to overwrite master or minion config files.
 2331 #----------------------------------------------------------------------------------------------------------------------
 2332 __overwriteconfig() {
 2333     if [ $# -eq 2 ]; then
 2334         target=$1
 2335         json=$2
 2336     else
 2337         echoerror "Wrong number of arguments for __convert_json_to_yaml_str()"
 2338         echoinfo "USAGE: __convert_json_to_yaml_str <configfile> <jsonstring>"
 2339         exit 1
 2340     fi
 2341 
 2342     # Make a tempfile to dump any python errors into.
 2343     if __check_command_exists mktemp; then
 2344         tempfile="$(mktemp /tmp/salt-config-XXXXXXXX 2>/dev/null)"
 2345 
 2346         if [ -z "$tempfile" ]; then
 2347             echoerror "Failed to create temporary file in /tmp"
 2348             return 1
 2349         fi
 2350     else
 2351         tempfile="/tmp/salt-config-$$"
 2352     fi
 2353 
 2354     if [ -n "$_PY_EXE" ]; then
 2355         good_python="$_PY_EXE"
 2356     # If python does not have yaml installed we're on Arch and should use python2
 2357     elif python -c "import yaml" 2> /dev/null; then
 2358         good_python=python
 2359     else
 2360         good_python=python2
 2361     fi
 2362 
 2363     # Convert json string to a yaml string and write it to config file. Output is dumped into tempfile.
 2364     "$good_python" -c "import json; import yaml; jsn=json.loads('$json'); yml=yaml.safe_dump(jsn, line_break='\\n', default_flow_style=False); config_file=open('$target', 'w'); config_file.write(yml); config_file.close();" 2>$tempfile
 2365 
 2366     # No python errors output to the tempfile
 2367     if [ ! -s "$tempfile" ]; then
 2368         rm -f "$tempfile"
 2369         return 0
 2370     fi
 2371 
 2372     # Errors are present in the tempfile - let's expose them to the user.
 2373     fullerror=$(cat "$tempfile")
 2374     echodebug "$fullerror"
 2375     echoerror "Python error encountered. This is likely due to passing in a malformed JSON string. Please use -D to see stacktrace."
 2376 
 2377     rm -f "$tempfile"
 2378 
 2379     return 1
 2380 
 2381 }
 2382 
 2383 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2384 #          NAME:  __check_services_systemd
 2385 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2386 #    PARAMETERS:  servicename
 2387 #----------------------------------------------------------------------------------------------------------------------
 2388 __check_services_systemd() {
 2389     if [ $# -eq 0 ]; then
 2390         echoerror "You need to pass a service name to check!"
 2391         exit 1
 2392     elif [ $# -ne 1 ]; then
 2393         echoerror "You need to pass a service name to check as the single argument to the function"
 2394     fi
 2395 
 2396     servicename=$1
 2397     echodebug "Checking if service ${servicename} is enabled"
 2398 
 2399     if [ "$(systemctl is-enabled "${servicename}")" = "enabled" ]; then
 2400         echodebug "Service ${servicename} is enabled"
 2401         return 0
 2402     else
 2403         echodebug "Service ${servicename} is NOT enabled"
 2404         return 1
 2405     fi
 2406 }   # ----------  end of function __check_services_systemd  ----------
 2407 
 2408 
 2409 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2410 #          NAME:  __check_services_upstart
 2411 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2412 #    PARAMETERS:  servicename
 2413 #----------------------------------------------------------------------------------------------------------------------
 2414 __check_services_upstart() {
 2415     if [ $# -eq 0 ]; then
 2416         echoerror "You need to pass a service name to check!"
 2417         exit 1
 2418     elif [ $# -ne 1 ]; then
 2419         echoerror "You need to pass a service name to check as the single argument to the function"
 2420     fi
 2421 
 2422     servicename=$1
 2423     echodebug "Checking if service ${servicename} is enabled"
 2424 
 2425     # Check if service is enabled to start at boot
 2426     if initctl list | grep "${servicename}" > /dev/null 2>&1; then
 2427         echodebug "Service ${servicename} is enabled"
 2428         return 0
 2429     else
 2430         echodebug "Service ${servicename} is NOT enabled"
 2431         return 1
 2432     fi
 2433 }   # ----------  end of function __check_services_upstart  ----------
 2434 
 2435 
 2436 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2437 #          NAME:  __check_services_sysvinit
 2438 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2439 #    PARAMETERS:  servicename
 2440 #----------------------------------------------------------------------------------------------------------------------
 2441 __check_services_sysvinit() {
 2442     if [ $# -eq 0 ]; then
 2443         echoerror "You need to pass a service name to check!"
 2444         exit 1
 2445     elif [ $# -ne 1 ]; then
 2446         echoerror "You need to pass a service name to check as the single argument to the function"
 2447     fi
 2448 
 2449     servicename=$1
 2450     echodebug "Checking if service ${servicename} is enabled"
 2451 
 2452     if [ "$(LC_ALL=C /sbin/chkconfig --list | grep "\\<${servicename}\\>" | grep '[2-5]:on')" != "" ]; then
 2453         echodebug "Service ${servicename} is enabled"
 2454         return 0
 2455     else
 2456         echodebug "Service ${servicename} is NOT enabled"
 2457         return 1
 2458     fi
 2459 }   # ----------  end of function __check_services_sysvinit  ----------
 2460 
 2461 
 2462 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2463 #          NAME:  __check_services_debian
 2464 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2465 #    PARAMETERS:  servicename
 2466 #----------------------------------------------------------------------------------------------------------------------
 2467 __check_services_debian() {
 2468     if [ $# -eq 0 ]; then
 2469         echoerror "You need to pass a service name to check!"
 2470         exit 1
 2471     elif [ $# -ne 1 ]; then
 2472         echoerror "You need to pass a service name to check as the single argument to the function"
 2473     fi
 2474 
 2475     servicename=$1
 2476     echodebug "Checking if service ${servicename} is enabled"
 2477 
 2478     # Check if the service is going to be started at any runlevel, fixes bootstrap in container (Docker, LXC)
 2479     if ls /etc/rc?.d/S*"${servicename}" >/dev/null 2>&1; then
 2480         echodebug "Service ${servicename} is enabled"
 2481         return 0
 2482     else
 2483         echodebug "Service ${servicename} is NOT enabled"
 2484         return 1
 2485     fi
 2486 }   # ----------  end of function __check_services_debian  ----------
 2487 
 2488 
 2489 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2490 #          NAME:  __check_services_openbsd
 2491 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2492 #    PARAMETERS:  servicename
 2493 #----------------------------------------------------------------------------------------------------------------------
 2494 __check_services_openbsd() {
 2495     if [ $# -eq 0 ]; then
 2496         echoerror "You need to pass a service name to check!"
 2497         exit 1
 2498     elif [ $# -ne 1 ]; then
 2499         echoerror "You need to pass a service name to check as the single argument to the function"
 2500     fi
 2501 
 2502     servicename=$1
 2503     echodebug "Checking if service ${servicename} is enabled"
 2504 
 2505     # shellcheck disable=SC2086,SC2046,SC2144
 2506     if rcctl get ${servicename} status; then
 2507         echodebug "Service ${servicename} is enabled"
 2508         return 0
 2509     else
 2510         echodebug "Service ${servicename} is NOT enabled"
 2511         return 1
 2512     fi
 2513 }   # ----------  end of function __check_services_openbsd  ----------
 2514 
 2515 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2516 #          NAME:  __check_services_openrc
 2517 #   DESCRIPTION:  Return 0 or 1 in case the service is enabled or not
 2518 #    PARAMETERS:  servicename
 2519 #----------------------------------------------------------------------------------------------------------------------
 2520 __check_services_openrc() {
 2521     if [ $# -eq 0 ]; then
 2522         echoerror "You need to pass a service name to check!"
 2523         exit 1
 2524     elif [ $# -ne 1 ]; then
 2525         echoerror "You need to pass a service name to check as the single argument to the function"
 2526     fi
 2527 
 2528     servicename=$1
 2529     echodebug "Checking if service ${servicename} is enabled"
 2530 
 2531     # shellcheck disable=SC2086,SC2046,SC2144
 2532     if rc-status $(rc-status -r) | tail -n +2 | grep -q "\\<$servicename\\>"; then
 2533         echodebug "Service ${servicename} is enabled"
 2534         return 0
 2535     else
 2536         echodebug "Service ${servicename} is NOT enabled"
 2537         return 1
 2538     fi
 2539 }   # ----------  end of function __check_services_openrc  ----------
 2540 
 2541 
 2542 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2543 #          NAME:  __create_virtualenv
 2544 #   DESCRIPTION:  Return 0 or 1 depending on successful creation of virtualenv
 2545 #----------------------------------------------------------------------------------------------------------------------
 2546 __create_virtualenv() {
 2547     if [ ! -d "$_VIRTUALENV_DIR" ]; then
 2548         echoinfo "Creating virtualenv ${_VIRTUALENV_DIR}"
 2549         if [ $_PIP_ALL -eq $BS_TRUE ]; then
 2550             virtualenv --no-site-packages "${_VIRTUALENV_DIR}" || return 1
 2551         else
 2552             virtualenv --system-site-packages "${_VIRTUALENV_DIR}" || return 1
 2553         fi
 2554     fi
 2555     return 0
 2556 }   # ----------  end of function __create_virtualenv  ----------
 2557 
 2558 
 2559 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2560 #          NAME:  __activate_virtualenv
 2561 #   DESCRIPTION:  Return 0 or 1 depending on successful activation of virtualenv
 2562 #----------------------------------------------------------------------------------------------------------------------
 2563 __activate_virtualenv() {
 2564     set +o nounset
 2565     # Is virtualenv empty
 2566     if [ -z "$_VIRTUALENV_DIR" ]; then
 2567         __create_virtualenv || return 1
 2568         # shellcheck source=/dev/null
 2569         . "${_VIRTUALENV_DIR}/bin/activate" || return 1
 2570         echoinfo "Activated virtualenv ${_VIRTUALENV_DIR}"
 2571     fi
 2572     set -o nounset
 2573     return 0
 2574 }   # ----------  end of function __activate_virtualenv  ----------
 2575 
 2576 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2577 #          NAME:  __install_pip_pkgs
 2578 #   DESCRIPTION:  Return 0 or 1 if successfully able to install pip packages. Can provide a different python version to
 2579 #                 install pip packages with. If $py_ver is not specified it will use the default python version.
 2580 #    PARAMETERS:  pkgs, py_ver
 2581 #----------------------------------------------------------------------------------------------------------------------
 2582 
 2583 __install_pip_pkgs() {
 2584     _pip_pkgs="$1"
 2585     _py_exe="$2"
 2586     _py_pkg=$(echo "$_py_exe" | sed -E "s/\\.//g")
 2587     _pip_cmd="${_py_exe} -m pip"
 2588 
 2589     if [ "${_py_exe}" = "" ]; then
 2590         _py_exe='python'
 2591     fi
 2592 
 2593     __check_pip_allowed
 2594 
 2595     # Install pip and pip dependencies
 2596     if ! __check_command_exists "${_pip_cmd} --version"; then
 2597         __PACKAGES="${_py_pkg}-setuptools ${_py_pkg}-pip gcc"
 2598         # shellcheck disable=SC2086
 2599         if [ "$DISTRO_NAME_L" = "debian" ] || [ "$DISTRO_NAME_L" = "ubuntu" ];then
 2600             __PACKAGES="${__PACKAGES} ${_py_pkg}-dev"
 2601             __apt_get_install_noinput ${__PACKAGES} || return 1
 2602         else
 2603             __PACKAGES="${__PACKAGES} ${_py_pkg}-devel"
 2604             if [ "$DISTRO_NAME_L" = "fedora" ];then
 2605               __dnf_install_noinput ${__PACKAGES} || return 1
 2606             else
 2607               __yum_install_noinput ${__PACKAGES} || return 1
 2608             fi
 2609         fi
 2610 
 2611     fi
 2612 
 2613     echoinfo "Installing pip packages: ${_pip_pkgs} using ${_py_exe}"
 2614     # shellcheck disable=SC2086
 2615     ${_pip_cmd} install ${_pip_pkgs} || return 1
 2616 }
 2617 
 2618 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2619 #          NAME:  __install_tornado_pip
 2620 #    PARAMETERS:  python executable
 2621 #   DESCRIPTION:  Return 0 or 1 if successfully able to install tornado<5.0
 2622 #----------------------------------------------------------------------------------------------------------------------
 2623 __install_tornado_pip() {
 2624     # OS needs tornado <5.0 from pip
 2625     __check_pip_allowed "You need to allow pip based installations (-P) for Tornado <5.0 in order to install Salt on Python 3"
 2626     ## install pip if its not installed and install tornado
 2627     __install_pip_pkgs "tornado<5.0" "${1}" || return 1
 2628 }
 2629 
 2630 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2631 #          NAME:  __install_pip_deps
 2632 #   DESCRIPTION:  Return 0 or 1 if successfully able to install pip packages via requirements file
 2633 #    PARAMETERS:  requirements_file
 2634 #----------------------------------------------------------------------------------------------------------------------
 2635 __install_pip_deps() {
 2636     # Install virtualenv to system pip before activating virtualenv if thats going to be used
 2637     # We assume pip pkg is installed since that is distro specific
 2638     if [ "$_VIRTUALENV_DIR" != "null" ]; then
 2639         if ! __check_command_exists pip; then
 2640             echoerror "Pip not installed: required for -a installs"
 2641             exit 1
 2642         fi
 2643         pip install -U virtualenv
 2644         __activate_virtualenv || return 1
 2645     else
 2646         echoerror "Must have virtualenv dir specified for -a installs"
 2647     fi
 2648 
 2649     requirements_file=$1
 2650     if [ ! -f "${requirements_file}" ]; then
 2651         echoerror "Requirements file: ${requirements_file} cannot be found, needed for -a (pip pkg) installs"
 2652         exit 1
 2653     fi
 2654 
 2655     __PIP_PACKAGES=''
 2656     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 2657         # shellcheck disable=SC2089
 2658         __PIP_PACKAGES="${__PIP_PACKAGES} 'apache-libcloud>=$_LIBCLOUD_MIN_VERSION'"
 2659     fi
 2660 
 2661     # shellcheck disable=SC2086,SC2090
 2662     pip install -U -r ${requirements_file} ${__PIP_PACKAGES}
 2663 }   # ----------  end of function __install_pip_deps  ----------
 2664 
 2665 #---  FUNCTION  -------------------------------------------------------------------------------------------------------
 2666 #          NAME:  __install_salt_from_repo_post_neon
 2667 #   DESCRIPTION:  Return 0 or 1 if successfully able to install. Can provide a different python version to
 2668 #                 install pip packages with. If $py_exe is not specified it will use the default python version.
 2669 #    PARAMETERS:  py_exe
 2670 #----------------------------------------------------------------------------------------------------------------------
 2671 __install_salt_from_repo_post_neon() {
 2672     _py_exe="$1"
 2673 
 2674     if [ "${_py_exe}" = "" ]; then
 2675         _py_exe='python'
 2676     fi
 2677 
 2678     echodebug "__install_salt_from_repo_post_neon py_exe=$_py_exe"
 2679 
 2680     _py_version=$(${_py_exe} -c "import sys; print('{0}.{1}'.format(*sys.version_info))")
 2681     _pip_cmd="pip${_py_version}"
 2682     if ! __check_command_exists "${_pip_cmd}"; then
 2683         echodebug "The pip binary '${_pip_cmd}' was not found in PATH"
 2684         _pip_cmd="pip$(echo "${_py_version}" | cut -c -1)"
 2685         if ! __check_command_exists "${_pip_cmd}"; then
 2686             echodebug "The pip binary '${_pip_cmd}' was not found in PATH"
 2687             _pip_cmd="pip"
 2688             if ! __check_command_exists "${_pip_cmd}"; then
 2689                 echoerror "Unable to find a pip binary"
 2690                 return 1
 2691             fi
 2692         fi
 2693     fi
 2694 
 2695     __check_pip_allowed
 2696 
 2697     echodebug "Installed pip version: $(${_pip_cmd} --version)"
 2698 
 2699     CHECK_PIP_VERSION_SCRIPT=$(cat << EOM
 2700 import sys
 2701 try:
 2702     import pip
 2703     installed_pip_version=tuple([int(part.strip()) for part in pip.__version__.split('.') if part.isdigit()])
 2704     desired_pip_version=($(echo ${_MINIMUM_PIP_VERSION} | sed 's/\./, /g' ))
 2705     if installed_pip_version < desired_pip_version:
 2706         print('Desired pip version {!r} > Installed pip version {!r}'.format('.'.join(map(str, desired_pip_version)), '.'.join(map(str, installed_pip_version))))
 2707         sys.exit(1)
 2708     print('Desired pip version {!r} < Installed pip version {!r}'.format('.'.join(map(str, desired_pip_version)), '.'.join(map(str, installed_pip_version))))
 2709     sys.exit(0)
 2710 except ImportError:
 2711     print('Failed to import pip')
 2712     sys.exit(1)
 2713 EOM
 2714 )
 2715     if ! ${_py_exe} -c "$CHECK_PIP_VERSION_SCRIPT"; then
 2716         # Upgrade pip to at least 1.2 which is when we can start using "python -m pip"
 2717         echodebug "Running '${_pip_cmd} install ${_POST_NEON_PIP_INSTALL_ARGS} pip>=${_MINIMUM_PIP_VERSION}'"
 2718         ${_pip_cmd} install ${_POST_NEON_PIP_INSTALL_ARGS} -v "pip>=${_MINIMUM_PIP_VERSION}"
 2719         sleep 1
 2720         echodebug "PATH: ${PATH}"
 2721         _pip_cmd="pip${_py_version}"
 2722         if ! __check_command_exists "${_pip_cmd}"; then
 2723             echodebug "The pip binary '${_pip_cmd}' was not found in PATH"
 2724             _pip_cmd="pip$(echo "${_py_version}" | cut -c -1)"
 2725             if ! __check_command_exists "${_pip_cmd}"; then
 2726                 echodebug "The pip binary '${_pip_cmd}' was not found in PATH"
 2727                 _pip_cmd="pip"
 2728                 if ! __check_command_exists "${_pip_cmd}"; then
 2729                     echoerror "Unable to find a pip binary"
 2730                     return 1
 2731                 fi
 2732             fi
 2733         fi
 2734         echodebug "Installed pip version: $(${_pip_cmd} --version)"
 2735     fi
 2736 
 2737     # We also lock setuptools to <45 which is the latest release to support both py2 and py3
 2738     echodebug "Running '${_pip_cmd} install wheel setuptools>=${_MINIMUM_SETUPTOOLS_VERSION},<45'"
 2739     ${_pip_cmd} install ${_POST_NEON_PIP_INSTALL_ARGS} wheel "setuptools>=${_MINIMUM_SETUPTOOLS_VERSION},<45"
 2740 
 2741     echoinfo "Installing salt using ${_py_exe}"
 2742     cd "${_SALT_GIT_CHECKOUT_DIR}" || return 1
 2743 
 2744     mkdir /tmp/git/deps
 2745     echoinfo "Downloading Salt Dependencies from PyPi"
 2746     echodebug "Running '${_pip_cmd} download -d /tmp/git/deps .'"
 2747     ${_pip_cmd} download -d /tmp/git/deps . || (echo "Failed to download salt dependencies" && return 1)
 2748 
 2749     echoinfo "Installing Downloaded Salt Dependencies"
 2750     echodebug "Running '${_pip_cmd} install --ignore-installed ${_POST_NEON_PIP_INSTALL_ARGS} /tmp/git/deps/*'"
 2751     ${_pip_cmd} install --ignore-installed ${_POST_NEON_PIP_INSTALL_ARGS} /tmp/git/deps/* || return 1
 2752     rm -f /tmp/git/deps/*
 2753 
 2754     echoinfo "Building Salt Python Wheel"
 2755 
 2756     if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
 2757         SETUP_PY_INSTALL_ARGS="-v"
 2758     fi
 2759 
 2760     echodebug "Running '${_py_exe} setup.py --salt-config-dir=$_SALT_ETC_DIR --salt-cache-dir=${_SALT_CACHE_DIR} ${SETUP_PY_INSTALL_ARGS} bdist_wheel'"
 2761     ${_py_exe} setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} bdist_wheel || return 1
 2762     mv dist/salt*.whl /tmp/git/deps/ || return 1
 2763 
 2764     cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}" || return 1
 2765 
 2766     echoinfo "Installing Built Salt Wheel"
 2767     ${_pip_cmd} uninstall --yes salt 2>/dev/null || true
 2768     echodebug "Running '${_pip_cmd} install --no-deps --force-reinstall ${_POST_NEON_PIP_INSTALL_ARGS} /tmp/git/deps/salt*.whl'"
 2769     ${_pip_cmd} install --no-deps --force-reinstall \
 2770         ${_POST_NEON_PIP_INSTALL_ARGS} \
 2771         --global-option="--salt-config-dir=$_SALT_ETC_DIR --salt-cache-dir=${_SALT_CACHE_DIR} ${SETUP_PY_INSTALL_ARGS}" \
 2772         /tmp/git/deps/salt*.whl || return 1
 2773 
 2774     echoinfo "Checking if Salt can be imported using ${_py_exe}"
 2775     CHECK_SALT_SCRIPT=$(cat << EOM
 2776 import os
 2777 import sys
 2778 try:
 2779     import salt
 2780     import salt.version
 2781     print('\nInstalled Salt Version: {}'.format(salt.version.__version__))
 2782     print('Installed Salt Package Path: {}\n'.format(os.path.dirname(salt.__file__)))
 2783     sys.exit(0)
 2784 except ImportError:
 2785     print('\nFailed to import salt\n')
 2786     sys.exit(1)
 2787 EOM
 2788 )
 2789     if ! ${_py_exe} -c "$CHECK_SALT_SCRIPT"; then
 2790         return 1
 2791     fi
 2792     return 0
 2793 }   # ----------  end of function __install_salt_from_repo_post_neon  ----------
 2794 
 2795 
 2796 if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 2797     if [ "x${_PY_MAJOR_VERSION}" = "x" ]; then
 2798         # Default to python 2 for pre Neon installs
 2799         _PY_MAJOR_VERSION=2
 2800     fi
 2801 else
 2802     if [ "x${_PY_MAJOR_VERSION}" = "x" ]; then
 2803         # Default to python 3 for post Neon install
 2804         _PY_MAJOR_VERSION=3
 2805     fi
 2806 fi
 2807 
 2808 #######################################################################################################################
 2809 #
 2810 #   Distribution install functions
 2811 #
 2812 #   In order to install salt for a distribution you need to define:
 2813 #
 2814 #   To Install Dependencies, which is required, one of:
 2815 #       1. install_<distro>_<major_version>_<install_type>_deps
 2816 #       2. install_<distro>_<major_version>_<minor_version>_<install_type>_deps
 2817 #       3. install_<distro>_<major_version>_deps
 2818 #       4  install_<distro>_<major_version>_<minor_version>_deps
 2819 #       5. install_<distro>_<install_type>_deps
 2820 #       6. install_<distro>_deps
 2821 #
 2822 #   Optionally, define a salt configuration function, which will be called if
 2823 #   the -c (config-dir) option is passed. One of:
 2824 #       1. config_<distro>_<major_version>_<install_type>_salt
 2825 #       2. config_<distro>_<major_version>_<minor_version>_<install_type>_salt
 2826 #       3. config_<distro>_<major_version>_salt
 2827 #       4  config_<distro>_<major_version>_<minor_version>_salt
 2828 #       5. config_<distro>_<install_type>_salt
 2829 #       6. config_<distro>_salt
 2830 #       7. config_salt [THIS ONE IS ALREADY DEFINED AS THE DEFAULT]
 2831 #
 2832 #   Optionally, define a salt master pre-seed function, which will be called if
 2833 #   the -k (pre-seed master keys) option is passed. One of:
 2834 #       1. preseed_<distro>_<major_version>_<install_type>_master
 2835 #       2. preseed_<distro>_<major_version>_<minor_version>_<install_type>_master
 2836 #       3. preseed_<distro>_<major_version>_master
 2837 #       4  preseed_<distro>_<major_version>_<minor_version>_master
 2838 #       5. preseed_<distro>_<install_type>_master
 2839 #       6. preseed_<distro>_master
 2840 #       7. preseed_master [THIS ONE IS ALREADY DEFINED AS THE DEFAULT]
 2841 #
 2842 #   To install salt, which, of course, is required, one of:
 2843 #       1. install_<distro>_<major_version>_<install_type>
 2844 #       2. install_<distro>_<major_version>_<minor_version>_<install_type>
 2845 #       3. install_<distro>_<install_type>
 2846 #
 2847 #   Optionally, define a post install function, one of:
 2848 #       1. install_<distro>_<major_version>_<install_type>_post
 2849 #       2. install_<distro>_<major_version>_<minor_version>_<install_type>_post
 2850 #       3. install_<distro>_<major_version>_post
 2851 #       4  install_<distro>_<major_version>_<minor_version>_post
 2852 #       5. install_<distro>_<install_type>_post
 2853 #       6. install_<distro>_post
 2854 #
 2855 #   Optionally, define a start daemons function, one of:
 2856 #       1. install_<distro>_<major_version>_<install_type>_restart_daemons
 2857 #       2. install_<distro>_<major_version>_<minor_version>_<install_type>_restart_daemons
 2858 #       3. install_<distro>_<major_version>_restart_daemons
 2859 #       4  install_<distro>_<major_version>_<minor_version>_restart_daemons
 2860 #       5. install_<distro>_<install_type>_restart_daemons
 2861 #       6. install_<distro>_restart_daemons
 2862 #
 2863 #       NOTE: The start daemons function should be able to restart any daemons
 2864 #             which are running, or start if they're not running.
 2865 #
 2866 #   Optionally, define a daemons running function, one of:
 2867 #       1. daemons_running_<distro>_<major_version>_<install_type>
 2868 #       2. daemons_running_<distro>_<major_version>_<minor_version>_<install_type>
 2869 #       3. daemons_running_<distro>_<major_version>
 2870 #       4  daemons_running_<distro>_<major_version>_<minor_version>
 2871 #       5. daemons_running_<distro>_<install_type>
 2872 #       6. daemons_running_<distro>
 2873 #       7. daemons_running  [THIS ONE IS ALREADY DEFINED AS THE DEFAULT]
 2874 #
 2875 #   Optionally, check enabled Services:
 2876 #       1. install_<distro>_<major_version>_<install_type>_check_services
 2877 #       2. install_<distro>_<major_version>_<minor_version>_<install_type>_check_services
 2878 #       3. install_<distro>_<major_version>_check_services
 2879 #       4  install_<distro>_<major_version>_<minor_version>_check_services
 2880 #       5. install_<distro>_<install_type>_check_services
 2881 #       6. install_<distro>_check_services
 2882 #
 2883 #######################################################################################################################
 2884 
 2885 
 2886 #######################################################################################################################
 2887 #
 2888 #   Ubuntu Install Functions
 2889 #
 2890 __enable_universe_repository() {
 2891     if [ "$(grep -R universe /etc/apt/sources.list /etc/apt/sources.list.d/ | grep -v '#')" != "" ]; then
 2892         # The universe repository is already enabled
 2893         return 0
 2894     fi
 2895 
 2896     echodebug "Enabling the universe repository"
 2897 
 2898     add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) universe" || return 1
 2899 
 2900     return 0
 2901 }
 2902 
 2903 __install_saltstack_ubuntu_repository() {
 2904     # Workaround for latest non-LTS ubuntu
 2905     if [ "$DISTRO_MAJOR_VERSION" -eq 19 ] || \
 2906         { [ "$DISTRO_MAJOR_VERSION" -eq 18 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]; }; then
 2907         echowarn "Non-LTS Ubuntu detected, but stable packages requested. Trying packages for previous LTS release. You may experience problems."
 2908         UBUNTU_VERSION=18.04
 2909         UBUNTU_CODENAME="bionic"
 2910     else
 2911         UBUNTU_VERSION=${DISTRO_VERSION}
 2912         UBUNTU_CODENAME=${DISTRO_CODENAME}
 2913     fi
 2914 
 2915     # Install downloader backend for GPG keys fetching
 2916     __PACKAGES='wget'
 2917 
 2918     # Required as it is not installed by default on Ubuntu 18+
 2919     if [ "$DISTRO_MAJOR_VERSION" -ge 18 ]; then
 2920         __PACKAGES="${__PACKAGES} gnupg"
 2921     fi
 2922 
 2923     # Make sure https transport is available
 2924     if [ "$HTTP_VAL" = "https" ] ; then
 2925         __PACKAGES="${__PACKAGES} apt-transport-https ca-certificates"
 2926     fi
 2927 
 2928     # shellcheck disable=SC2086,SC2090
 2929     __apt_get_install_noinput ${__PACKAGES} || return 1
 2930 
 2931     __PY_VERSION_REPO="apt"
 2932     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 2933         __PY_VERSION_REPO="py3"
 2934     fi
 2935 
 2936     # SaltStack's stable Ubuntu repository:
 2937     SALTSTACK_UBUNTU_URL="${HTTP_VAL}://${_REPO_URL}/${__PY_VERSION_REPO}/ubuntu/${UBUNTU_VERSION}/${__REPO_ARCH}/${STABLE_REV}"
 2938     echo "$__REPO_ARCH_DEB $SALTSTACK_UBUNTU_URL $UBUNTU_CODENAME main" > /etc/apt/sources.list.d/saltstack.list
 2939 
 2940     __apt_key_fetch "$SALTSTACK_UBUNTU_URL/SALTSTACK-GPG-KEY.pub" || return 1
 2941 
 2942     __wait_for_apt apt-get update || return 1
 2943 }
 2944 
 2945 install_ubuntu_deps() {
 2946     if [ $_DISABLE_REPOS -eq $BS_FALSE ]; then
 2947         # Install add-apt-repository
 2948         if ! __check_command_exists add-apt-repository; then
 2949             __apt_get_install_noinput software-properties-common || return 1
 2950         fi
 2951 
 2952         __enable_universe_repository || return 1
 2953 
 2954         __wait_for_apt apt-get update || return 1
 2955     fi
 2956 
 2957     __PACKAGES=''
 2958 
 2959     if [ "$DISTRO_MAJOR_VERSION" -lt 16 ]; then
 2960         # Minimal systems might not have upstart installed, install it
 2961         __PACKAGES="upstart"
 2962     fi
 2963 
 2964     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 2965         PY_PKG_VER=3
 2966     else
 2967         PY_PKG_VER=""
 2968     fi
 2969 
 2970     if [ "$DISTRO_MAJOR_VERSION" -ge 16 ] && [ -z "$_PY_EXE" ]; then
 2971         __PACKAGES="${__PACKAGES} python2.7"
 2972     fi
 2973 
 2974     if [ "$_VIRTUALENV_DIR" != "null" ]; then
 2975         __PACKAGES="${__PACKAGES} python-virtualenv"
 2976     fi
 2977     # Need python-apt for managing packages via Salt
 2978     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-apt"
 2979 
 2980     # requests is still used by many salt modules
 2981     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-requests"
 2982 
 2983     # YAML module is used for generating custom master/minion configs
 2984     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-yaml"
 2985 
 2986     # Additionally install procps and pciutils which allows for Docker bootstraps. See 366#issuecomment-39666813
 2987     __PACKAGES="${__PACKAGES} procps pciutils"
 2988 
 2989     # shellcheck disable=SC2086,SC2090
 2990     __apt_get_install_noinput ${__PACKAGES} || return 1
 2991 
 2992     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 2993         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 2994         # shellcheck disable=SC2086
 2995         __apt_get_install_noinput ${_EXTRA_PACKAGES} || return 1
 2996     fi
 2997 
 2998     return 0
 2999 }
 3000 
 3001 install_ubuntu_stable_deps() {
 3002     if [ "${_SLEEP}" -eq "${__DEFAULT_SLEEP}" ] && [ "$DISTRO_MAJOR_VERSION" -lt 16 ]; then
 3003         # The user did not pass a custom sleep value as an argument, let's increase the default value
 3004         echodebug "On Ubuntu systems we increase the default sleep value to 10."
 3005         echodebug "See https://github.com/saltstack/salt/issues/12248 for more info."
 3006         _SLEEP=10
 3007     fi
 3008 
 3009     if [ "$DISTRO_MAJOR_VERSION" -ge 20 ]; then
 3010         # Default Ubuntu 20.04 to Py3
 3011         if [ "x${_PY_EXE}" = "x" ]; then
 3012             _PY_EXE=python3
 3013             _PY_MAJOR_VERSION=3
 3014             PY_PKG_VER=3
 3015         fi
 3016     fi
 3017 
 3018     if [ $_START_DAEMONS -eq $BS_FALSE ]; then
 3019         echowarn "Not starting daemons on Debian based distributions is not working mostly because starting them is the default behaviour."
 3020     fi
 3021 
 3022     # No user interaction, libc6 restart services for example
 3023     export DEBIAN_FRONTEND=noninteractive
 3024 
 3025     __wait_for_apt apt-get update || return 1
 3026 
 3027     if [ "${_UPGRADE_SYS}" -eq $BS_TRUE ]; then
 3028         if [ "${_INSECURE_DL}" -eq $BS_TRUE ]; then
 3029             __apt_get_install_noinput --allow-unauthenticated debian-archive-keyring &&
 3030                 apt-key update && apt-get update || return 1
 3031         fi
 3032 
 3033         __apt_get_upgrade_noinput || return 1
 3034     fi
 3035 
 3036     if [ "$_DISABLE_REPOS" -eq "$BS_FALSE" ] || [ "$_CUSTOM_REPO_URL" != "null" ]; then
 3037         __check_dpkg_architecture || return 1
 3038         __install_saltstack_ubuntu_repository || return 1
 3039     fi
 3040 
 3041     install_ubuntu_deps || return 1
 3042 }
 3043 
 3044 install_ubuntu_git_deps() {
 3045     __wait_for_apt apt-get update || return 1
 3046 
 3047     if ! __check_command_exists git; then
 3048         __apt_get_install_noinput git-core || return 1
 3049     fi
 3050 
 3051     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 3052         __apt_get_install_noinput ca-certificates
 3053     fi
 3054 
 3055     __git_clone_and_checkout || return 1
 3056 
 3057     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3058         PY_PKG_VER=3
 3059     else
 3060         PY_PKG_VER=""
 3061     fi
 3062 
 3063     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 3064 
 3065         __PACKAGES=""
 3066 
 3067         # See how we are installing packages
 3068         if [ "${_PIP_ALL}" -eq $BS_TRUE ]; then
 3069             __PACKAGES="${__PACKAGES} python-dev swig libssl-dev libzmq3 libzmq3-dev"
 3070 
 3071             if ! __check_command_exists pip; then
 3072                 __PACKAGES="${__PACKAGES} python-setuptools python-pip"
 3073             fi
 3074 
 3075             # Get just the apt packages that are required to build all the pythons
 3076             # shellcheck disable=SC2086
 3077             __apt_get_install_noinput ${__PACKAGES} || return 1
 3078             # Install the pythons from requirements (only zmq for now)
 3079             __install_pip_deps "${_SALT_GIT_CHECKOUT_DIR}/requirements/zeromq.txt" || return 1
 3080         else
 3081             install_ubuntu_stable_deps || return 1
 3082 
 3083             if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3084                 __PACKAGES="${__PACKAGES} python3-setuptools"
 3085             else
 3086                 # There is no m2crypto package for Py3 at this time - only install for Py2
 3087                 __PACKAGES="${__PACKAGES} python-m2crypto"
 3088             fi
 3089 
 3090             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
 3091             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests"
 3092             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-tornado python${PY_PKG_VER}-yaml"
 3093             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-zmq"
 3094             __PACKAGES="${__PACKAGES} python-concurrent.futures"
 3095 
 3096             if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 3097                 # Install python-libcloud if asked to
 3098                 __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-libcloud"
 3099             fi
 3100 
 3101             # shellcheck disable=SC2086
 3102             __apt_get_install_noinput ${__PACKAGES} || return 1
 3103         fi
 3104     else
 3105         __PACKAGES="python${PY_PKG_VER}-dev python${PY_PKG_VER}-pip python${PY_PKG_VER}-setuptools gcc"
 3106         # shellcheck disable=SC2086
 3107         __apt_get_install_noinput ${__PACKAGES} || return 1
 3108     fi
 3109 
 3110     # Let's trigger config_salt()
 3111     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 3112         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 3113         CONFIG_SALT_FUNC="config_salt"
 3114     fi
 3115 
 3116     return 0
 3117 }
 3118 
 3119 install_ubuntu_stable() {
 3120     __PACKAGES=""
 3121 
 3122     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ];then
 3123         __PACKAGES="${__PACKAGES} salt-cloud"
 3124     fi
 3125     if [ "$_INSTALL_MASTER" -eq $BS_TRUE ]; then
 3126         __PACKAGES="${__PACKAGES} salt-master"
 3127     fi
 3128     if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 3129         __PACKAGES="${__PACKAGES} salt-minion"
 3130     fi
 3131     if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ]; then
 3132         __PACKAGES="${__PACKAGES} salt-syndic"
 3133     fi
 3134 
 3135     # shellcheck disable=SC2086
 3136     __apt_get_install_noinput ${__PACKAGES} || return 1
 3137 
 3138     return 0
 3139 }
 3140 
 3141 install_ubuntu_git() {
 3142     # Activate virtualenv before install
 3143     if [ "${_VIRTUALENV_DIR}" != "null" ]; then
 3144         __activate_virtualenv || return 1
 3145     fi
 3146 
 3147     if [ -n "$_PY_EXE" ]; then
 3148         _PYEXE=${_PY_EXE}
 3149     else
 3150         _PYEXE=python2.7
 3151     fi
 3152 
 3153     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3154         # We can use --prefix on debian based ditributions
 3155         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3156             _POST_NEON_PIP_INSTALL_ARGS="--target=/usr/lib/python3/dist-packages --install-option=--install-scripts=/usr/bin"
 3157         else
 3158             _POST_NEON_PIP_INSTALL_ARGS="--target=/usr/lib/python2.7/dist-packages --install-option=--install-scripts=/usr/bin"
 3159         fi
 3160         _POST_NEON_PIP_INSTALL_ARGS=""
 3161         __install_salt_from_repo_post_neon "${_PY_EXE}" || return 1
 3162         cd "${_SALT_GIT_CHECKOUT_DIR}" || return 1
 3163         sed -i 's:/usr/bin:/usr/local/bin:g' pkg/*.service
 3164         return 0
 3165     fi
 3166 
 3167     if [ -f "${_SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
 3168         # shellcheck disable=SC2086
 3169         "${_PYEXE}" setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} install --install-layout=deb || return 1
 3170     else
 3171         # shellcheck disable=SC2086
 3172         "${_PYEXE}" setup.py ${SETUP_PY_INSTALL_ARGS} install --install-layout=deb || return 1
 3173     fi
 3174 
 3175     return 0
 3176 }
 3177 
 3178 install_ubuntu_stable_post() {
 3179     for fname in api master minion syndic; do
 3180         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3181         [ $fname = "api" ] && continue
 3182 
 3183         # Skip if not meant to be installed
 3184         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3185         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3186         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3187 
 3188         if [ -f /bin/systemctl ]; then
 3189             # Using systemd
 3190             /bin/systemctl is-enabled salt-$fname.service > /dev/null 2>&1 || (
 3191                 /bin/systemctl preset salt-$fname.service > /dev/null 2>&1 &&
 3192                 /bin/systemctl enable salt-$fname.service > /dev/null 2>&1
 3193             )
 3194             sleep 1
 3195             /bin/systemctl daemon-reload
 3196         elif [ -f /etc/init.d/salt-$fname ]; then
 3197             update-rc.d salt-$fname defaults
 3198         fi
 3199     done
 3200 
 3201     return 0
 3202 }
 3203 
 3204 install_ubuntu_git_post() {
 3205     for fname in api master minion syndic; do
 3206         # Skip if not meant to be installed
 3207         [ $fname = "api" ] && \
 3208             ([ "$_INSTALL_MASTER" -eq $BS_FALSE ] || ! __check_command_exists "salt-${fname}") && continue
 3209         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3210         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3211         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3212 
 3213         if [ -f /bin/systemctl ] && [ "$DISTRO_MAJOR_VERSION" -ge 16 ]; then
 3214             __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.service" "/lib/systemd/system/salt-${fname}.service"
 3215 
 3216             # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3217             [ $fname = "api" ] && continue
 3218 
 3219             systemctl is-enabled salt-$fname.service || (systemctl preset salt-$fname.service && systemctl enable salt-$fname.service)
 3220             sleep 1
 3221             systemctl daemon-reload
 3222         elif [ -f /sbin/initctl ]; then
 3223             _upstart_conf="/etc/init/salt-$fname.conf"
 3224             # We have upstart support
 3225             echodebug "There's upstart support"
 3226             if [ ! -f $_upstart_conf ]; then
 3227                 # upstart does not know about our service, let's copy the proper file
 3228                 echowarn "Upstart does not appear to know about salt-$fname"
 3229                 echodebug "Copying ${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-$fname.upstart to $_upstart_conf"
 3230                 __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.upstart" "$_upstart_conf"
 3231                 # Set service to know about virtualenv
 3232                 if [ "${_VIRTUALENV_DIR}" != "null" ]; then
 3233                     echo "SALT_USE_VIRTUALENV=${_VIRTUALENV_DIR}" > /etc/default/salt-${fname}
 3234                 fi
 3235                 /sbin/initctl reload-configuration || return 1
 3236             fi
 3237         # No upstart support in Ubuntu!?
 3238         elif [ -f "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.init" ]; then
 3239             echodebug "There's NO upstart support!?"
 3240             echodebug "Copying ${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.init to /etc/init.d/salt-$fname"
 3241             __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.init" "/etc/init.d/salt-$fname"
 3242             chmod +x /etc/init.d/salt-$fname
 3243 
 3244             # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3245             [ $fname = "api" ] && continue
 3246 
 3247             update-rc.d salt-$fname defaults
 3248         else
 3249             echoerror "Neither upstart nor init.d was setup for salt-$fname"
 3250         fi
 3251     done
 3252 
 3253     return 0
 3254 }
 3255 
 3256 install_ubuntu_restart_daemons() {
 3257     [ $_START_DAEMONS -eq $BS_FALSE ] && return
 3258 
 3259     # Ensure upstart configs / systemd units are loaded
 3260     if [ -f /bin/systemctl ] && [ "$DISTRO_MAJOR_VERSION" -ge 16 ]; then
 3261         systemctl daemon-reload
 3262     elif [ -f /sbin/initctl ]; then
 3263         /sbin/initctl reload-configuration
 3264     fi
 3265 
 3266     for fname in api master minion syndic; do
 3267         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3268         [ $fname = "api" ] && continue
 3269 
 3270         # Skip if not meant to be installed
 3271         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3272         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3273         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3274 
 3275         if [ -f /bin/systemctl ] && [ "$DISTRO_MAJOR_VERSION" -ge 16 ]; then
 3276             echodebug "There's systemd support while checking salt-$fname"
 3277             systemctl stop salt-$fname > /dev/null 2>&1
 3278             systemctl start salt-$fname.service && continue
 3279             # We failed to start the service, let's test the SysV code below
 3280             echodebug "Failed to start salt-$fname using systemd"
 3281             if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
 3282                 systemctl status salt-$fname.service
 3283                 journalctl -xe
 3284             fi
 3285         fi
 3286 
 3287         if [ -f /sbin/initctl ]; then
 3288             echodebug "There's upstart support while checking salt-$fname"
 3289 
 3290             if status salt-$fname 2>/dev/null | grep -q running; then
 3291                 stop salt-$fname || (echodebug "Failed to stop salt-$fname" && return 1)
 3292             fi
 3293 
 3294             start salt-$fname && continue
 3295             # We failed to start the service, let's test the SysV code below
 3296             echodebug "Failed to start salt-$fname using Upstart"
 3297         fi
 3298 
 3299         if [ ! -f /etc/init.d/salt-$fname ]; then
 3300             echoerror "No init.d support for salt-$fname was found"
 3301             return 1
 3302         fi
 3303 
 3304         /etc/init.d/salt-$fname stop > /dev/null 2>&1
 3305         /etc/init.d/salt-$fname start
 3306     done
 3307 
 3308     return 0
 3309 }
 3310 
 3311 install_ubuntu_check_services() {
 3312     for fname in api master minion syndic; do
 3313         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3314         [ $fname = "api" ] && continue
 3315 
 3316         # Skip if not meant to be installed
 3317         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3318         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3319         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3320 
 3321         if [ -f /bin/systemctl ] && [ "$DISTRO_MAJOR_VERSION" -ge 16 ]; then
 3322             __check_services_systemd salt-$fname || return 1
 3323         elif [ -f /sbin/initctl ] && [ -f /etc/init/salt-${fname}.conf ]; then
 3324             __check_services_upstart salt-$fname || return 1
 3325         elif [ -f /etc/init.d/salt-$fname ]; then
 3326             __check_services_debian salt-$fname || return 1
 3327         fi
 3328     done
 3329 
 3330     return 0
 3331 }
 3332 #
 3333 #   End of Ubuntu Install Functions
 3334 #
 3335 #######################################################################################################################
 3336 
 3337 #######################################################################################################################
 3338 #
 3339 #   Debian Install Functions
 3340 #
 3341 __install_saltstack_debian_repository() {
 3342     DEBIAN_RELEASE="$DISTRO_MAJOR_VERSION"
 3343     DEBIAN_CODENAME="$DISTRO_CODENAME"
 3344 
 3345     __PY_VERSION_REPO="apt"
 3346     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3347         __PY_VERSION_REPO="py3"
 3348     fi
 3349 
 3350     # Install downloader backend for GPG keys fetching
 3351     __PACKAGES='wget'
 3352 
 3353     # Required as it is not installed by default on Debian 9+
 3354     if [ "$DISTRO_MAJOR_VERSION" -ge 9 ]; then
 3355         __PACKAGES="${__PACKAGES} gnupg2"
 3356     fi
 3357 
 3358     # Make sure https transport is available
 3359     if [ "$HTTP_VAL" = "https" ] ; then
 3360         __PACKAGES="${__PACKAGES} apt-transport-https ca-certificates"
 3361     fi
 3362 
 3363     # shellcheck disable=SC2086,SC2090
 3364     __apt_get_install_noinput ${__PACKAGES} || return 1
 3365 
 3366     # amd64 is just a part of repository URI, 32-bit pkgs are hosted under the same location
 3367     SALTSTACK_DEBIAN_URL="${HTTP_VAL}://${_REPO_URL}/${__PY_VERSION_REPO}/debian/${DEBIAN_RELEASE}/${__REPO_ARCH}/${STABLE_REV}"
 3368     echo "$__REPO_ARCH_DEB $SALTSTACK_DEBIAN_URL $DEBIAN_CODENAME main" > "/etc/apt/sources.list.d/saltstack.list"
 3369 
 3370     __apt_key_fetch "$SALTSTACK_DEBIAN_URL/SALTSTACK-GPG-KEY.pub" || return 1
 3371 
 3372     __wait_for_apt apt-get update || return 1
 3373 }
 3374 
 3375 install_debian_deps() {
 3376     if [ $_START_DAEMONS -eq $BS_FALSE ]; then
 3377         echowarn "Not starting daemons on Debian based distributions is not working mostly because starting them is the default behaviour."
 3378     fi
 3379 
 3380     # No user interaction, libc6 restart services for example
 3381     export DEBIAN_FRONTEND=noninteractive
 3382 
 3383     __wait_for_apt apt-get update || return 1
 3384 
 3385     if [ "${_UPGRADE_SYS}" -eq $BS_TRUE ]; then
 3386         # Try to update GPG keys first if allowed
 3387         if [ "${_INSECURE_DL}" -eq $BS_TRUE ]; then
 3388             __apt_get_install_noinput --allow-unauthenticated debian-archive-keyring &&
 3389                 apt-key update && apt-get update || return 1
 3390         fi
 3391 
 3392         __apt_get_upgrade_noinput || return 1
 3393     fi
 3394 
 3395     if [ "$DISTRO_MAJOR_VERSION" -ge 10 ]; then
 3396         # Default Debian 10 to Py3
 3397         if [ "x${_PY_EXE}" = "x" ]; then
 3398             _PY_EXE=python3
 3399             _PY_MAJOR_VERSION=3
 3400             PY_PKG_VER=3
 3401         fi
 3402     fi
 3403 
 3404     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3405         PY_PKG_VER=3
 3406     else
 3407         PY_PKG_VER=""
 3408     fi
 3409 
 3410     # Additionally install procps and pciutils which allows for Docker bootstraps. See 366#issuecomment-39666813
 3411     __PACKAGES='procps pciutils'
 3412 
 3413     # YAML module is used for generating custom master/minion configs
 3414     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-yaml"
 3415 
 3416     # shellcheck disable=SC2086
 3417     __apt_get_install_noinput ${__PACKAGES} || return 1
 3418 
 3419     if [ "$_DISABLE_REPOS" -eq "$BS_FALSE" ] || [ "$_CUSTOM_REPO_URL" != "null" ]; then
 3420         __check_dpkg_architecture || return 1
 3421         __install_saltstack_debian_repository || return 1
 3422     fi
 3423 
 3424     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 3425         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 3426         # shellcheck disable=SC2086
 3427         __apt_get_install_noinput ${_EXTRA_PACKAGES} || return 1
 3428     fi
 3429 
 3430     return 0
 3431 }
 3432 
 3433 install_debian_git_pre() {
 3434     if ! __check_command_exists git; then
 3435         __apt_get_install_noinput git || return 1
 3436     fi
 3437 
 3438     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 3439         __apt_get_install_noinput ca-certificates
 3440     fi
 3441 
 3442     __git_clone_and_checkout || return 1
 3443 
 3444     # Let's trigger config_salt()
 3445     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 3446         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 3447         CONFIG_SALT_FUNC="config_salt"
 3448     fi
 3449 }
 3450 
 3451 install_debian_git_deps() {
 3452     install_debian_deps || return 1
 3453     install_debian_git_pre || return 1
 3454 
 3455     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3456         PY_PKG_VER=3
 3457     else
 3458         PY_PKG_VER=""
 3459     fi
 3460 
 3461     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 3462         __PACKAGES="libzmq3 libzmq3-dev lsb-release python-apt python-backports.ssl-match-hostname"
 3463         __PACKAGES="${__PACKAGES} python-crypto python-jinja2 python-msgpack python-m2crypto"
 3464         __PACKAGES="${__PACKAGES} python-requests python-tornado python-yaml python-zmq"
 3465 
 3466         if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 3467             # Install python-libcloud if asked to
 3468             __PACKAGES="${__PACKAGES} python-libcloud"
 3469         fi
 3470 
 3471         # shellcheck disable=SC2086
 3472         __apt_get_install_noinput ${__PACKAGES} || return 1
 3473     else
 3474         __PACKAGES="python${PY_PKG_VER}-dev python${PY_PKG_VER}-pip python${PY_PKG_VER}-setuptools gcc"
 3475         echodebug "install_debian_git_deps() Installing ${__PACKAGES}"
 3476         # shellcheck disable=SC2086
 3477         __apt_get_install_noinput ${__PACKAGES} || return 1
 3478     fi
 3479 
 3480     return 0
 3481 }
 3482 
 3483 install_debian_7_git_deps() {
 3484     install_debian_deps || return 1
 3485     install_debian_git_deps || return 1
 3486 
 3487     return 0
 3488 }
 3489 
 3490 install_debian_8_git_deps() {
 3491 
 3492     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3493         echodebug "CALLING install_debian_git_deps"
 3494         install_debian_git_deps || return 1
 3495         return 0
 3496     fi
 3497 
 3498     install_debian_deps || return 1
 3499 
 3500     if ! __check_command_exists git; then
 3501         __apt_get_install_noinput git || return 1
 3502     fi
 3503 
 3504     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 3505         __apt_get_install_noinput ca-certificates
 3506     fi
 3507 
 3508     __git_clone_and_checkout || return 1
 3509 
 3510     __PACKAGES="libzmq3 libzmq3-dev lsb-release python-apt python-crypto python-jinja2"
 3511     __PACKAGES="${__PACKAGES} python-m2crypto python-msgpack python-requests python-systemd"
 3512     __PACKAGES="${__PACKAGES} python-yaml python-zmq python-concurrent.futures"
 3513 
 3514     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 3515         # Install python-libcloud if asked to
 3516         __PACKAGES="${__PACKAGES} python-libcloud"
 3517     fi
 3518 
 3519     __PIP_PACKAGES=''
 3520     if (__check_pip_allowed >/dev/null 2>&1); then
 3521         __PIP_PACKAGES='tornado<5.0'
 3522         # Install development environment for building tornado Python module
 3523         __PACKAGES="${__PACKAGES} build-essential python-dev"
 3524 
 3525         if ! __check_command_exists pip; then
 3526             __PACKAGES="${__PACKAGES} python-pip"
 3527         fi
 3528     # Attempt to configure backports repo on non-x86_64 system
 3529     elif [ $_DISABLE_REPOS -eq $BS_FALSE ] && [ "$DPKG_ARCHITECTURE" != "amd64" ]; then
 3530         # Check if Debian Backports repo already configured
 3531         if ! apt-cache policy | grep -q 'Debian Backports'; then
 3532             echo 'deb http://httpredir.debian.org/debian jessie-backports main' > \
 3533                 /etc/apt/sources.list.d/backports.list
 3534         fi
 3535 
 3536         __wait_for_apt apt-get update || return 1
 3537 
 3538         # python-tornado package should be installed from backports repo
 3539         __PACKAGES="${__PACKAGES} python-backports.ssl-match-hostname python-tornado/jessie-backports"
 3540     else
 3541         __PACKAGES="${__PACKAGES} python-backports.ssl-match-hostname python-tornado"
 3542     fi
 3543 
 3544     # shellcheck disable=SC2086
 3545     __apt_get_install_noinput ${__PACKAGES} || return 1
 3546 
 3547     if [ "${__PIP_PACKAGES}" != "" ]; then
 3548         # shellcheck disable=SC2086,SC2090
 3549         pip install -U ${__PIP_PACKAGES} || return 1
 3550     fi
 3551 
 3552     # Let's trigger config_salt()
 3553     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 3554         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 3555         CONFIG_SALT_FUNC="config_salt"
 3556     fi
 3557 
 3558     return 0
 3559 }
 3560 
 3561 install_debian_9_git_deps() {
 3562 
 3563     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3564         install_debian_git_deps || return 1
 3565         return 0
 3566     fi
 3567 
 3568     install_debian_deps || return 1
 3569     install_debian_git_pre || return 1
 3570 
 3571     __PACKAGES="libzmq5 lsb-release"
 3572 
 3573     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3574         PY_PKG_VER=3
 3575     else
 3576         PY_PKG_VER=""
 3577 
 3578         # These packages are PY2-ONLY
 3579         __PACKAGES="${__PACKAGES} python-backports-abc python-m2crypto python-concurrent.futures"
 3580     fi
 3581 
 3582     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-apt python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
 3583     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests python${PY_PKG_VER}-systemd"
 3584     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-tornado python${PY_PKG_VER}-yaml python${PY_PKG_VER}-zmq"
 3585 
 3586     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 3587         # Install python-libcloud if asked to
 3588         __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-libcloud"
 3589     fi
 3590 
 3591     # shellcheck disable=SC2086
 3592     __apt_get_install_noinput ${__PACKAGES} || return 1
 3593 
 3594     return 0
 3595 }
 3596 
 3597 install_debian_10_git_deps() {
 3598 
 3599     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3600         install_debian_git_deps || return 1
 3601         return 0
 3602     fi
 3603 
 3604     install_debian_deps || return 1
 3605     install_debian_git_pre || return 1
 3606 
 3607     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3608         _py=${_PY_EXE}
 3609         PY_PKG_VER=3
 3610         __PACKAGES="python${PY_PKG_VER}-distutils"
 3611     else
 3612         _py="python"
 3613         PY_PKG_VER=""
 3614         __PACKAGES=""
 3615     fi
 3616 
 3617     __install_tornado_pip ${_py}|| return 1
 3618     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-jinja2"
 3619     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-tornado python${PY_PKG_VER}-yaml python${PY_PKG_VER}-zmq"
 3620 
 3621     # shellcheck disable=SC2086
 3622     __apt_get_install_noinput ${__PACKAGES} || return 1
 3623 
 3624     return 0
 3625 }
 3626 
 3627 install_debian_stable() {
 3628     __PACKAGES=""
 3629 
 3630     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ];then
 3631         __PACKAGES="${__PACKAGES} salt-cloud"
 3632     fi
 3633     if [ "$_INSTALL_MASTER" -eq $BS_TRUE ]; then
 3634         __PACKAGES="${__PACKAGES} salt-master"
 3635     fi
 3636     if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 3637         __PACKAGES="${__PACKAGES} salt-minion"
 3638     fi
 3639     if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ]; then
 3640         __PACKAGES="${__PACKAGES} salt-syndic"
 3641     fi
 3642 
 3643     # shellcheck disable=SC2086
 3644     __apt_get_install_noinput ${__PACKAGES} || return 1
 3645 
 3646     return 0
 3647 }
 3648 
 3649 install_debian_7_stable() {
 3650     install_debian_stable || return 1
 3651     return 0
 3652 }
 3653 
 3654 install_debian_8_stable() {
 3655     install_debian_stable || return 1
 3656     return 0
 3657 }
 3658 
 3659 install_debian_9_stable() {
 3660     install_debian_stable || return 1
 3661     return 0
 3662 }
 3663 
 3664 install_debian_git() {
 3665     if [ -n "$_PY_EXE" ]; then
 3666         _PYEXE=${_PY_EXE}
 3667     else
 3668         _PYEXE=python
 3669     fi
 3670 
 3671     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3672         # We can use --prefix on debian based ditributions
 3673         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3674             _POST_NEON_PIP_INSTALL_ARGS="--target=/usr/lib/python3/dist-packages --install-option=--install-scripts=/usr/bin"
 3675         else
 3676             _POST_NEON_PIP_INSTALL_ARGS="--target=/usr/lib/python2.7/dist-packages --install-option=--install-scripts=/usr/bin"
 3677         fi
 3678         _POST_NEON_PIP_INSTALL_ARGS=""
 3679         __install_salt_from_repo_post_neon "${_PY_EXE}" || return 1
 3680         cd "${_SALT_GIT_CHECKOUT_DIR}" || return 1
 3681         sed -i 's:/usr/bin:/usr/local/bin:g' pkg/*.service
 3682         return 0
 3683     fi
 3684 
 3685     if [ -f "${_SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
 3686         # shellcheck disable=SC2086
 3687         "${_PYEXE}" setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} install --install-layout=deb || return 1
 3688     else
 3689         # shellcheck disable=SC2086
 3690         "${_PYEXE}" setup.py ${SETUP_PY_INSTALL_ARGS} install --install-layout=deb || return 1
 3691     fi
 3692 }
 3693 
 3694 install_debian_7_git() {
 3695     install_debian_git || return 1
 3696     return 0
 3697 }
 3698 
 3699 install_debian_8_git() {
 3700     install_debian_git || return 1
 3701     return 0
 3702 }
 3703 
 3704 install_debian_9_git() {
 3705     install_debian_git || return 1
 3706     return 0
 3707 }
 3708 
 3709 install_debian_git_post() {
 3710     for fname in api master minion syndic; do
 3711         # Skip if not meant to be installed
 3712         [ "$fname" = "api" ] && \
 3713             ([ "$_INSTALL_MASTER" -eq $BS_FALSE ] || ! __check_command_exists "salt-${fname}") && continue
 3714         [ "$fname" = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3715         [ "$fname" = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3716         [ "$fname" = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3717 
 3718         # Configure SystemD for Debian 8 "Jessie" and later
 3719         if [ -f /bin/systemctl ]; then
 3720             if [ ! -f /lib/systemd/system/salt-${fname}.service ] || \
 3721                 { [ -f /lib/systemd/system/salt-${fname}.service ] && [ $_FORCE_OVERWRITE -eq $BS_TRUE ]; }; then
 3722                 if [ -f "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.service" ]; then
 3723                     __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.service" /lib/systemd/system
 3724                     __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.environment" "/etc/default/salt-${fname}"
 3725                 else
 3726                     # workaround before adding Debian-specific unit files to the Salt main repo
 3727                     __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/salt-${fname}.service" /lib/systemd/system
 3728                     sed -i -e '/^Type/ s/notify/simple/' /lib/systemd/system/salt-${fname}.service
 3729                 fi
 3730             fi
 3731 
 3732             # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3733             [ "$fname" = "api" ] && continue
 3734 
 3735             /bin/systemctl enable "salt-${fname}.service"
 3736             SYSTEMD_RELOAD=$BS_TRUE
 3737 
 3738         # Install initscripts for Debian 7 "Wheezy"
 3739         elif [ ! -f "/etc/init.d/salt-$fname" ] || \
 3740             { [ -f "/etc/init.d/salt-$fname" ] && [ "$_FORCE_OVERWRITE" -eq $BS_TRUE ]; }; then
 3741             __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/deb/salt-${fname}.init" "/etc/init.d/salt-${fname}"
 3742             __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/deb/salt-${fname}.environment" "/etc/default/salt-${fname}"
 3743 
 3744             if [ ! -f "/etc/init.d/salt-${fname}" ]; then
 3745                 echowarn "The init script for salt-${fname} was not found, skipping it..."
 3746                 continue
 3747             fi
 3748 
 3749             chmod +x "/etc/init.d/salt-${fname}"
 3750 
 3751             # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3752             [ "$fname" = "api" ] && continue
 3753 
 3754             update-rc.d "salt-${fname}" defaults
 3755         fi
 3756     done
 3757 }
 3758 
 3759 install_debian_restart_daemons() {
 3760     [ "$_START_DAEMONS" -eq $BS_FALSE ] && return 0
 3761 
 3762     for fname in api master minion syndic; do
 3763         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3764         [ $fname = "api" ] && continue
 3765 
 3766         # Skip if not meant to be installed
 3767         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3768         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3769         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3770 
 3771         if [ -f /bin/systemctl ]; then
 3772             # Debian 8 uses systemd
 3773             /bin/systemctl stop salt-$fname > /dev/null 2>&1
 3774             /bin/systemctl start salt-$fname.service && continue
 3775             if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
 3776                 systemctl status salt-$fname.service
 3777                 journalctl -xe
 3778             fi
 3779         elif [ -f /etc/init.d/salt-$fname ]; then
 3780             # Still in SysV init
 3781             /etc/init.d/salt-$fname stop > /dev/null 2>&1
 3782             /etc/init.d/salt-$fname start
 3783         fi
 3784     done
 3785 }
 3786 
 3787 install_debian_check_services() {
 3788     for fname in api master minion syndic; do
 3789         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3790         [ $fname = "api" ] && continue
 3791 
 3792         # Skip if not meant to be installed
 3793         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3794         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3795         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3796 
 3797         if [ -f /bin/systemctl ]; then
 3798             __check_services_systemd salt-$fname || return 1
 3799         elif [ -f /etc/init.d/salt-$fname ]; then
 3800             __check_services_debian salt-$fname || return 1
 3801         fi
 3802     done
 3803     return 0
 3804 }
 3805 #
 3806 #   Ended Debian Install Functions
 3807 #
 3808 #######################################################################################################################
 3809 
 3810 #######################################################################################################################
 3811 #
 3812 #   Fedora Install Functions
 3813 #
 3814 
 3815 install_fedora_deps() {
 3816     if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then
 3817         dnf -y update || return 1
 3818     fi
 3819 
 3820     __PACKAGES="${__PACKAGES:=}"
 3821     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -lt 3 ]; then
 3822         echoerror "There are no Python 2 stable packages for Fedora, only Py3 packages"
 3823         return 1
 3824     fi
 3825 
 3826     # Salt on Fedora is Py3
 3827     PY_PKG_VER=3
 3828 
 3829     __PACKAGES="${__PACKAGES} dnf-utils libyaml procps-ng python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
 3830     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests python${PY_PKG_VER}-zmq"
 3831     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-pip python${PY_PKG_VER}-m2crypto python${PY_PKG_VER}-pyyaml"
 3832     __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-systemd"
 3833     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 3834         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 3835     fi
 3836 
 3837     # shellcheck disable=SC2086
 3838     __dnf_install_noinput ${__PACKAGES} ${_EXTRA_PACKAGES} || return 1
 3839 
 3840     return 0
 3841 }
 3842 
 3843 install_fedora_stable() {
 3844     if [ "$STABLE_REV" = "latest" ]; then
 3845         __SALT_VERSION=""
 3846     else
 3847         __SALT_VERSION="$(dnf list --showduplicates salt | grep "$STABLE_REV" | head -n 1 | awk '{print $2}')"
 3848         if [ "x${__SALT_VERSION}" = "x" ]; then
 3849             echoerror "Could not find a stable install for Salt ${STABLE_REV}"
 3850             exit 1
 3851         fi
 3852         echoinfo "Installing Stable Package Version ${__SALT_VERSION}"
 3853         __SALT_VERSION="-${__SALT_VERSION}"
 3854     fi
 3855     __PACKAGES=""
 3856 
 3857     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ];then
 3858         __PACKAGES="${__PACKAGES} salt-cloud${__SALT_VERSION}"
 3859     fi
 3860     if [ "$_INSTALL_MASTER" -eq $BS_TRUE ]; then
 3861         __PACKAGES="${__PACKAGES} salt-master${__SALT_VERSION}"
 3862     fi
 3863     if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 3864         __PACKAGES="${__PACKAGES} salt-minion${__SALT_VERSION}"
 3865     fi
 3866     if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ]; then
 3867         __PACKAGES="${__PACKAGES} salt-syndic${__SALT_VERSION}"
 3868     fi
 3869 
 3870     # shellcheck disable=SC2086
 3871     __dnf_install_noinput ${__PACKAGES} || return 1
 3872 
 3873     __python="python3"
 3874     if ! __check_command_exists python3; then
 3875         echoerror "Could not find a python3 binary?!"
 3876         return 1
 3877     fi
 3878 
 3879     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 3880         __check_pip_allowed "You need to allow pip based installations (-P) for Tornado <5.0 in order to install Salt"
 3881         __installed_tornado_rpm=$(rpm -qa | grep python${PY_PKG_VER}-tornado)
 3882         if [ -n "${__installed_tornado_rpm}" ]; then
 3883             echodebug "Removing system package ${__installed_tornado_rpm}"
 3884             rpm -e --nodeps "${__installed_tornado_rpm}" || return 1
 3885         fi
 3886         __get_site_packages_dir_code=$(cat << EOM
 3887 import site
 3888 print([d for d in site.getsitepackages() if d.startswith('/usr/lib/python')][0])
 3889 EOM
 3890 )
 3891         __target_path=$(${__python} -c "${__get_site_packages_dir_code}")
 3892         echodebug "Running '${__python}' -m pip install --target ${__target_path} 'tornado<5.0'"
 3893         "${__python}" -m pip install --target "${__target_path}" "tornado<5" || return 1
 3894     fi
 3895 
 3896     return 0
 3897 }
 3898 
 3899 install_fedora_stable_post() {
 3900     for fname in api master minion syndic; do
 3901         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 3902         [ $fname = "api" ] && continue
 3903 
 3904         # Skip if not meant to be installed
 3905         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 3906         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 3907         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 3908 
 3909         systemctl is-enabled salt-$fname.service || (systemctl preset salt-$fname.service && systemctl enable salt-$fname.service)
 3910         sleep 1
 3911         systemctl daemon-reload
 3912     done
 3913 }
 3914 
 3915 install_fedora_git_deps() {
 3916     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3917         # Packages are named python3-<whatever>
 3918         PY_PKG_VER=3
 3919     else
 3920         PY_PKG_VER=2
 3921     fi
 3922 
 3923     __PACKAGES=""
 3924     if ! __check_command_exists ps; then
 3925         __PACKAGES="${__PACKAGES} procps-ng"
 3926     fi
 3927     if ! __check_command_exists git; then
 3928         __PACKAGES="${__PACKAGES} git"
 3929     fi
 3930 
 3931     if [ -n "${__PACKAGES}" ]; then
 3932         # shellcheck disable=SC2086
 3933         __dnf_install_noinput ${__PACKAGES} || return 1
 3934         __PACKAGES=""
 3935     fi
 3936 
 3937     __git_clone_and_checkout || return 1
 3938 
 3939     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 3940 
 3941         if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 3942             __PACKAGES="${__PACKAGES} ca-certificates"
 3943         fi
 3944         if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 3945             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-libcloud python${PY_PKG_VER}-netaddr"
 3946         fi
 3947 
 3948         install_fedora_deps || return 1
 3949 
 3950         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 3951             if __check_command_exists python3; then
 3952                 __python="python3"
 3953             fi
 3954         elif [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 2 ]; then
 3955             if __check_command_exists python2; then
 3956                 __python="python2"
 3957             fi
 3958         else
 3959             if ! __check_command_exists python; then
 3960                 echoerror "Unable to find a python binary?!"
 3961                 return 1
 3962             fi
 3963             # Let's hope it's the right one
 3964             __python="python"
 3965         fi
 3966 
 3967         grep tornado "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" | while IFS='
 3968     '         read -r dep; do
 3969                 echodebug "Running '${__python}' -m pip install '${dep}'"
 3970                 "${__python}" -m pip install "${dep}" || return 1
 3971             done
 3972     else
 3973         __PACKAGES="python${PY_PKG_VER}-devel python${PY_PKG_VER}-pip python${PY_PKG_VER}-setuptools gcc"
 3974         # shellcheck disable=SC2086
 3975         __dnf_install_noinput ${__PACKAGES} || return 1
 3976     fi
 3977 
 3978     # Let's trigger config_salt()
 3979     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 3980         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 3981         CONFIG_SALT_FUNC="config_salt"
 3982     fi
 3983 
 3984     return 0
 3985 }
 3986 
 3987 install_fedora_git() {
 3988     if [ "${_PY_EXE}" != "" ]; then
 3989         _PYEXE=${_PY_EXE}
 3990         echoinfo "Using the following python version: ${_PY_EXE} to install salt"
 3991     else
 3992         _PYEXE='python2'
 3993     fi
 3994 
 3995     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 3996          __install_salt_from_repo_post_neon "${_PY_EXE}" || return 1
 3997         return 0
 3998     fi
 3999 
 4000     if [ -f "${_SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
 4001         ${_PYEXE} setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} install --prefix=/usr || return 1
 4002     else
 4003         ${_PYEXE} setup.py ${SETUP_PY_INSTALL_ARGS} install --prefix=/usr || return 1
 4004     fi
 4005     return 0
 4006 }
 4007 
 4008 install_fedora_git_post() {
 4009     for fname in api master minion syndic; do
 4010         # Skip if not meant to be installed
 4011         [ $fname = "api" ] && \
 4012             ([ "$_INSTALL_MASTER" -eq $BS_FALSE ] || ! __check_command_exists "salt-${fname}") && continue
 4013         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4014         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4015         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4016 
 4017         __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/rpm/salt-${fname}.service" "/lib/systemd/system/salt-${fname}.service"
 4018 
 4019         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4020         [ $fname = "api" ] && continue
 4021 
 4022         systemctl is-enabled salt-$fname.service || (systemctl preset salt-$fname.service && systemctl enable salt-$fname.service)
 4023         sleep 1
 4024         systemctl daemon-reload
 4025     done
 4026 }
 4027 
 4028 install_fedora_restart_daemons() {
 4029     [ $_START_DAEMONS -eq $BS_FALSE ] && return
 4030 
 4031     for fname in api master minion syndic; do
 4032         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4033         [ $fname = "api" ] && continue
 4034 
 4035         # Skip if not meant to be installed
 4036         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4037         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4038         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4039 
 4040         systemctl stop salt-$fname > /dev/null 2>&1
 4041         systemctl start salt-$fname.service && continue
 4042         echodebug "Failed to start salt-$fname using systemd"
 4043         if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
 4044             systemctl status salt-$fname.service
 4045             journalctl -xe
 4046         fi
 4047     done
 4048 }
 4049 
 4050 install_fedora_check_services() {
 4051     for fname in api master minion syndic; do
 4052         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4053         [ $fname = "api" ] && continue
 4054 
 4055         # Skip if not meant to be installed
 4056         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4057         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4058         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4059 
 4060         __check_services_systemd salt-$fname || return 1
 4061     done
 4062 
 4063     return 0
 4064 }
 4065 #
 4066 #   Ended Fedora Install Functions
 4067 #
 4068 #######################################################################################################################
 4069 
 4070 #######################################################################################################################
 4071 #
 4072 #   CentOS Install Functions
 4073 #
 4074 __install_epel_repository() {
 4075     if [ ${_EPEL_REPOS_INSTALLED} -eq $BS_TRUE ]; then
 4076         return 0
 4077     fi
 4078 
 4079     # Check if epel repo is already enabled and flag it accordingly
 4080     if yum repolist | grep -q "^[!]\\?${_EPEL_REPO}/"; then
 4081         _EPEL_REPOS_INSTALLED=$BS_TRUE
 4082         return 0
 4083     fi
 4084 
 4085     # Download latest 'epel-release' package for the distro version directly
 4086     epel_repo_url="${HTTP_VAL}://dl.fedoraproject.org/pub/epel/epel-release-latest-${DISTRO_MAJOR_VERSION}.noarch.rpm"
 4087     rpm -Uvh --force "$epel_repo_url" || return 1
 4088 
 4089     _EPEL_REPOS_INSTALLED=$BS_TRUE
 4090 
 4091     return 0
 4092 }
 4093 
 4094 __install_saltstack_rhel_repository() {
 4095     if [ "$ITYPE" = "stable" ]; then
 4096         repo_rev="$STABLE_REV"
 4097     else
 4098         repo_rev="latest"
 4099     fi
 4100 
 4101     __PY_VERSION_REPO="yum"
 4102     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4103         __PY_VERSION_REPO="py3"
 4104     fi
 4105 
 4106     # Avoid using '$releasever' variable for yum.
 4107     # Instead, this should work correctly on all RHEL variants.
 4108     base_url="${HTTP_VAL}://${_REPO_URL}/${__PY_VERSION_REPO}/redhat/${DISTRO_MAJOR_VERSION}/\$basearch/${repo_rev}/"
 4109     gpg_key="SALTSTACK-GPG-KEY.pub"
 4110     repo_file="/etc/yum.repos.d/saltstack.repo"
 4111 
 4112     if [ ! -s "$repo_file" ] || [ "$_FORCE_OVERWRITE" -eq $BS_TRUE ]; then
 4113         cat <<_eof > "$repo_file"
 4114 [saltstack]
 4115 name=SaltStack ${repo_rev} Release Channel for RHEL/CentOS \$releasever
 4116 baseurl=${base_url}
 4117 skip_if_unavailable=True
 4118 gpgcheck=1
 4119 gpgkey=${base_url}${gpg_key}
 4120 enabled=1
 4121 enabled_metadata=1
 4122 _eof
 4123 
 4124         fetch_url="${HTTP_VAL}://${_REPO_URL}/${__PY_VERSION_REPO}/redhat/${DISTRO_MAJOR_VERSION}/${CPU_ARCH_L}/${repo_rev}/"
 4125         __rpm_import_gpg "${fetch_url}${gpg_key}" || return 1
 4126         yum clean metadata || return 1
 4127     elif [ "$repo_rev" != "latest" ]; then
 4128         echowarn "saltstack.repo already exists, ignoring salt version argument."
 4129         echowarn "Use -F (forced overwrite) to install $repo_rev."
 4130     fi
 4131 
 4132     return 0
 4133 }
 4134 
 4135 install_centos_stable_deps() {
 4136     if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then
 4137         yum -y update || return 1
 4138     fi
 4139 
 4140     if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4141         # CentOS/RHEL 8 Default to Py3
 4142         if [ "x${_PY_EXE}" = "x" ]; then
 4143             _PY_EXE=python3
 4144             _PY_MAJOR_VERSION=3
 4145         fi
 4146     fi
 4147 
 4148     if [ "$_DISABLE_REPOS" -eq "$BS_TRUE" ] && [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4149         echowarn "Detected -r or -R option while installing Salt packages for Python 3."
 4150         echowarn "Python 3 packages for older Salt releases requires the EPEL repository to be installed."
 4151         echowarn "Installing the EPEL repository automatically is disabled when using the -r or -R options."
 4152     fi
 4153 
 4154     if [ "$_DISABLE_REPOS" -eq "$BS_FALSE" ]; then
 4155         __install_epel_repository || return 1
 4156         __install_saltstack_rhel_repository || return 1
 4157     fi
 4158 
 4159     # If -R was passed, we need to configure custom repo url with rsync-ed packages
 4160     # Which is still handled in __install_saltstack_rhel_repository. This call has
 4161     # its own check in case -r was passed without -R.
 4162     if [ "$_CUSTOM_REPO_URL" != "null" ]; then
 4163         __install_saltstack_rhel_repository || return 1
 4164     fi
 4165 
 4166     if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4167         __PACKAGES="dnf-utils chkconfig"
 4168     else
 4169         __PACKAGES="yum-utils chkconfig"
 4170     fi
 4171 
 4172     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 4173         if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4174             # YAML module is used for generating custom master/minion configs
 4175             if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4176                 __PACKAGES="${__PACKAGES} python3-pyyaml"
 4177             else
 4178                 __PACKAGES="${__PACKAGES} python2-pyyaml"
 4179             fi
 4180         elif [ "$DISTRO_MAJOR_VERSION" -eq 7 ]; then
 4181             # YAML module is used for generating custom master/minion configs
 4182             if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4183                 __PACKAGES="${__PACKAGES} python36-PyYAML"
 4184             else
 4185                 __PACKAGES="${__PACKAGES} PyYAML"
 4186             fi
 4187         else
 4188             # YAML module is used for generating custom master/minion configs
 4189             if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4190                 __PACKAGES="${__PACKAGES} python34-PyYAML"
 4191             else
 4192                 __PACKAGES="${__PACKAGES} PyYAML"
 4193             fi
 4194         fi
 4195     fi
 4196 
 4197     # shellcheck disable=SC2086
 4198     __yum_install_noinput ${__PACKAGES} || return 1
 4199 
 4200     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 4201         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 4202         # shellcheck disable=SC2086
 4203         __yum_install_noinput ${_EXTRA_PACKAGES} || return 1
 4204     fi
 4205 
 4206 
 4207     return 0
 4208 }
 4209 
 4210 install_centos_stable() {
 4211     __PACKAGES=""
 4212 
 4213     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ];then
 4214         __PACKAGES="${__PACKAGES} salt-cloud"
 4215     fi
 4216     if [ "$_INSTALL_MASTER" -eq $BS_TRUE ];then
 4217         __PACKAGES="${__PACKAGES} salt-master"
 4218     fi
 4219     if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 4220         __PACKAGES="${__PACKAGES} salt-minion"
 4221     fi
 4222     if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ];then
 4223         __PACKAGES="${__PACKAGES} salt-syndic"
 4224     fi
 4225 
 4226     # shellcheck disable=SC2086
 4227     __yum_install_noinput ${__PACKAGES} || return 1
 4228 
 4229     return 0
 4230 }
 4231 
 4232 install_centos_stable_post() {
 4233     SYSTEMD_RELOAD=$BS_FALSE
 4234 
 4235     for fname in api master minion syndic; do
 4236         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4237         [ $fname = "api" ] && continue
 4238 
 4239         # Skip if not meant to be installed
 4240         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4241         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4242         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4243 
 4244         if [ -f /bin/systemctl ]; then
 4245             /bin/systemctl is-enabled salt-${fname}.service > /dev/null 2>&1 || (
 4246                 /bin/systemctl preset salt-${fname}.service > /dev/null 2>&1 &&
 4247                 /bin/systemctl enable salt-${fname}.service > /dev/null 2>&1
 4248             )
 4249 
 4250             SYSTEMD_RELOAD=$BS_TRUE
 4251         elif [ -f "/etc/init.d/salt-${fname}" ]; then
 4252             /sbin/chkconfig salt-${fname} on
 4253         fi
 4254     done
 4255 
 4256     if [ "$SYSTEMD_RELOAD" -eq $BS_TRUE ]; then
 4257         /bin/systemctl daemon-reload
 4258     fi
 4259 
 4260     return 0
 4261 }
 4262 
 4263 install_centos_git_deps() {
 4264     install_centos_stable_deps || return 1
 4265 
 4266     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 4267         __yum_install_noinput ca-certificates || return 1
 4268     fi
 4269 
 4270     if ! __check_command_exists git; then
 4271         __yum_install_noinput git || return 1
 4272     fi
 4273 
 4274     __git_clone_and_checkout || return 1
 4275 
 4276     __PACKAGES=""
 4277 
 4278     if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4279         if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4280             # Packages are named python3-<whatever>
 4281             PY_PKG_VER=3
 4282             __PACKAGES="${__PACKAGES} python3"
 4283         else
 4284             # Packages are named python36-<whatever>
 4285             PY_PKG_VER=36
 4286             __PACKAGES="${__PACKAGES} python36"
 4287         fi
 4288     else
 4289         PY_PKG_VER=""
 4290         if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4291             __PACKAGES="${__PACKAGES} python2"
 4292         elif [ "$DISTRO_MAJOR_VERSION" -eq 6 ]; then
 4293             PY_PKG_VER=27
 4294             __PACKAGES="${__PACKAGES} python27"
 4295         else
 4296             __PACKAGES="${__PACKAGES} python"
 4297         fi
 4298     fi
 4299 
 4300     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 4301         _install_m2crypto_req=false
 4302         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 4303             _py=${_PY_EXE}
 4304             if [ "$DISTRO_MAJOR_VERSION" -gt 6 ]; then
 4305                 _install_m2crypto_req=true
 4306             fi
 4307         else
 4308             if [ "$DISTRO_MAJOR_VERSION" -eq 6 ]; then
 4309                 _install_m2crypto_req=true
 4310             fi
 4311             _py="python"
 4312 
 4313             # Only Py2 needs python-futures
 4314             __PACKAGES="${__PACKAGES} python-futures"
 4315 
 4316             # There is no systemd-python3 package as of this writing
 4317             if [ "$DISTRO_MAJOR_VERSION" -ge 7 ]; then
 4318                 __PACKAGES="${__PACKAGES} systemd-python"
 4319             fi
 4320         fi
 4321 
 4322         if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then
 4323             __install_tornado_pip ${_py} || return 1
 4324             __PACKAGES="${__PACKAGES} python3-m2crypto"
 4325         else
 4326             __PACKAGES="${__PACKAGES} m2crypto python${PY_PKG_VER}-crypto"
 4327         fi
 4328 
 4329         __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-jinja2"
 4330         __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests"
 4331         __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-tornado python${PY_PKG_VER}-zmq"
 4332 
 4333         if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 4334             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-libcloud"
 4335         fi
 4336 
 4337         if [ "${_INSTALL_PY}" -eq "${BS_TRUE}" ]; then
 4338             # Install Python if "-y" was passed in.
 4339             __install_python || return 1
 4340         fi
 4341 
 4342         if [ "${_PY_EXE}" != "" ] && [ "$_PIP_ALLOWED" -eq "$BS_TRUE" ]; then
 4343             # If "-x" is defined, install dependencies with pip based on the Python version given.
 4344             _PIP_PACKAGES="m2crypto!=0.33.0 jinja2 msgpack-python pycrypto PyYAML tornado<5.0 zmq futures>=2.0"
 4345 
 4346             # install swig and openssl on cent6
 4347             if $_install_m2crypto_req; then
 4348                 __yum_install_noinput openssl-devel swig || return 1
 4349             fi
 4350 
 4351             if [ -f "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
 4352                 # Filter out any commented lines from the requirements file
 4353                 _REQ_LINES="$(grep '^[^#]' "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
 4354                 for SINGLE_PACKAGE in ${_PIP_PACKAGES}; do
 4355                     __REQUIRED_VERSION="$(grep "${SINGLE_PACKAGE}" "${_REQ_LINES}")"
 4356                     if [ "${__REQUIRED_VERSION}" != "" ]; then
 4357                         _PIP_PACKAGES=$(echo "$_PIP_PACKAGES" | sed "s/${SINGLE_PACKAGE}/${__REQUIRED_VERSION}/")
 4358                     fi
 4359                 done
 4360             fi
 4361 
 4362             if [ "$_INSTALL_CLOUD" -eq "${BS_TRUE}" ]; then
 4363                 _PIP_PACKAGES="${_PIP_PACKAGES} apache-libcloud"
 4364             fi
 4365 
 4366             __install_pip_pkgs "${_PIP_PACKAGES}" "${_PY_EXE}" || return 1
 4367         else
 4368             # shellcheck disable=SC2086
 4369             __yum_install_noinput ${__PACKAGES} || return 1
 4370         fi
 4371     else
 4372         if [ "${_INSTALL_PY}" -eq "${BS_TRUE}" ] && [ "$DISTRO_MAJOR_VERSION" -lt 8 ]; then
 4373             # Install Python if "-y" was passed in.
 4374             __install_python || return 1
 4375         fi
 4376         __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-devel python${PY_PKG_VER}-pip python${PY_PKG_VER}-setuptools gcc"
 4377         # shellcheck disable=SC2086
 4378         __yum_install_noinput ${__PACKAGES} || return 1
 4379     fi
 4380 
 4381     # Let's trigger config_salt()
 4382     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 4383         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 4384         CONFIG_SALT_FUNC="config_salt"
 4385     fi
 4386 
 4387     return 0
 4388 }
 4389 
 4390 install_centos_git() {
 4391     if [ "${_PY_EXE}" != "" ]; then
 4392         _PYEXE=${_PY_EXE}
 4393         echoinfo "Using the following python version: ${_PY_EXE} to install salt"
 4394     else
 4395         _PYEXE='python2'
 4396     fi
 4397 
 4398     echodebug "_PY_EXE: $_PY_EXE"
 4399     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 4400          __install_salt_from_repo_post_neon "${_PY_EXE}" || return 1
 4401         return 0
 4402     fi
 4403 
 4404     if [ -f "${_SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
 4405         $_PYEXE setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} install --prefix=/usr || return 1
 4406     else
 4407         $_PYEXE setup.py ${SETUP_PY_INSTALL_ARGS} install --prefix=/usr || return 1
 4408     fi
 4409 
 4410     return 0
 4411 }
 4412 
 4413 install_centos_git_post() {
 4414     SYSTEMD_RELOAD=$BS_FALSE
 4415 
 4416     for fname in api master minion syndic; do
 4417         # Skip if not meant to be installed
 4418         [ $fname = "api" ] && \
 4419             ([ "$_INSTALL_MASTER" -eq $BS_FALSE ] || ! __check_command_exists "salt-${fname}") && continue
 4420         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4421         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4422         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4423 
 4424         if [ -f /bin/systemctl ]; then
 4425             if [ ! -f "/usr/lib/systemd/system/salt-${fname}.service" ] || \
 4426                 { [ -f "/usr/lib/systemd/system/salt-${fname}.service" ] && [ "$_FORCE_OVERWRITE" -eq $BS_TRUE ]; }; then
 4427                 __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/rpm/salt-${fname}.service" /usr/lib/systemd/system
 4428             fi
 4429 
 4430             SYSTEMD_RELOAD=$BS_TRUE
 4431         elif [ ! -f "/etc/init.d/salt-$fname" ] || \
 4432             { [ -f "/etc/init.d/salt-$fname" ] && [ "$_FORCE_OVERWRITE" -eq $BS_TRUE ]; }; then
 4433             __copyfile "${_SALT_GIT_CHECKOUT_DIR}/pkg/rpm/salt-${fname}" /etc/init.d
 4434             chmod +x /etc/init.d/salt-${fname}
 4435         fi
 4436     done
 4437 
 4438     if [ "$SYSTEMD_RELOAD" -eq $BS_TRUE ]; then
 4439         /bin/systemctl daemon-reload
 4440     fi
 4441 
 4442     install_centos_stable_post || return 1
 4443 
 4444     return 0
 4445 }
 4446 
 4447 install_centos_restart_daemons() {
 4448     [ $_START_DAEMONS -eq $BS_FALSE ] && return
 4449 
 4450     for fname in api master minion syndic; do
 4451         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4452         [ $fname = "api" ] && continue
 4453 
 4454         # Skip if not meant to be installed
 4455         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4456         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4457         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4458 
 4459         if [ -f /sbin/initctl ] && [ -f /etc/init/salt-${fname}.conf ]; then
 4460             # We have upstart support and upstart knows about our service
 4461             if ! /sbin/initctl status salt-$fname > /dev/null 2>&1; then
 4462                 # Everything is in place and upstart gave us an error code? Fail!
 4463                 return 1
 4464             fi
 4465 
 4466             # upstart knows about this service.
 4467             # Let's try to stop it, and then start it
 4468             /sbin/initctl stop salt-$fname > /dev/null 2>&1
 4469             # Restart service
 4470             if ! /sbin/initctl start salt-$fname > /dev/null 2>&1; then
 4471                 # Failed the restart?!
 4472                 return 1
 4473             fi
 4474         elif [ -f /etc/init.d/salt-$fname ]; then
 4475             # Disable stdin to fix shell session hang on killing tee pipe
 4476             service salt-$fname stop < /dev/null > /dev/null 2>&1
 4477             service salt-$fname start < /dev/null
 4478         elif [ -f /usr/bin/systemctl ]; then
 4479             # CentOS 7 uses systemd
 4480             /usr/bin/systemctl stop salt-$fname > /dev/null 2>&1
 4481             /usr/bin/systemctl start salt-$fname.service && continue
 4482             echodebug "Failed to start salt-$fname using systemd"
 4483             if [ "$_ECHO_DEBUG" -eq $BS_TRUE ]; then
 4484                 systemctl status salt-$fname.service
 4485                 journalctl -xe
 4486             fi
 4487         fi
 4488     done
 4489 }
 4490 
 4491 install_centos_testing_deps() {
 4492     install_centos_stable_deps || return 1
 4493     return 0
 4494 }
 4495 
 4496 install_centos_testing() {
 4497     install_centos_stable || return 1
 4498     return 0
 4499 }
 4500 
 4501 install_centos_testing_post() {
 4502     install_centos_stable_post || return 1
 4503     return 0
 4504 }
 4505 
 4506 install_centos_check_services() {
 4507     for fname in api master minion syndic; do
 4508         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 4509         [ $fname = "api" ] && continue
 4510 
 4511         # Skip if not meant to be installed
 4512         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 4513         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 4514         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 4515 
 4516         if [ -f /sbin/initctl ] && [ -f /etc/init/salt-${fname}.conf ]; then
 4517             __check_services_upstart salt-$fname || return 1
 4518         elif [ -f /etc/init.d/salt-$fname ]; then
 4519             __check_services_sysvinit salt-$fname || return 1
 4520         elif [ -f /usr/bin/systemctl ]; then
 4521             __check_services_systemd salt-$fname || return 1
 4522         fi
 4523     done
 4524 
 4525     return 0
 4526 }
 4527 #
 4528 #   Ended CentOS Install Functions
 4529 #
 4530 #######################################################################################################################
 4531 
 4532 #######################################################################################################################
 4533 #
 4534 #   RedHat Install Functions
 4535 #
 4536 install_red_hat_linux_stable_deps() {
 4537     install_centos_stable_deps || return 1
 4538     return 0
 4539 }
 4540 
 4541 install_red_hat_linux_git_deps() {
 4542     install_centos_git_deps || return 1
 4543     return 0
 4544 }
 4545 
 4546 install_red_hat_enterprise_stable_deps() {
 4547     install_red_hat_linux_stable_deps || return 1
 4548     return 0
 4549 }
 4550 
 4551 install_red_hat_enterprise_git_deps() {
 4552     install_red_hat_linux_git_deps || return 1
 4553     return 0
 4554 }
 4555 
 4556 install_red_hat_enterprise_linux_stable_deps() {
 4557     install_red_hat_linux_stable_deps || return 1
 4558     return 0
 4559 }
 4560 
 4561 install_red_hat_enterprise_linux_git_deps() {
 4562     install_red_hat_linux_git_deps || return 1
 4563     return 0
 4564 }
 4565 
 4566 install_red_hat_enterprise_server_stable_deps() {
 4567     install_red_hat_linux_stable_deps || return 1
 4568     return 0
 4569 }
 4570 
 4571 install_red_hat_enterprise_server_git_deps() {
 4572     install_red_hat_linux_git_deps || return 1
 4573     return 0
 4574 }
 4575 
 4576 install_red_hat_enterprise_workstation_stable_deps() {
 4577     install_red_hat_linux_stable_deps || return 1
 4578     return 0
 4579 }
 4580 
 4581 install_red_hat_enterprise_workstation_git_deps() {
 4582     install_red_hat_linux_git_deps || return 1
 4583     return 0
 4584 }
 4585 
 4586 install_red_hat_linux_stable() {
 4587     install_centos_stable || return 1
 4588     return 0
 4589 }
 4590 
 4591 install_red_hat_linux_git() {
 4592     install_centos_git || return 1
 4593     return 0
 4594 }
 4595 
 4596 install_red_hat_enterprise_stable() {
 4597     install_red_hat_linux_stable || return 1
 4598     return 0
 4599 }
 4600 
 4601 install_red_hat_enterprise_git() {
 4602     install_red_hat_linux_git || return 1
 4603     return 0
 4604 }
 4605 
 4606 install_red_hat_enterprise_linux_stable() {
 4607     install_red_hat_linux_stable || return 1
 4608     return 0
 4609 }
 4610 
 4611 install_red_hat_enterprise_linux_git() {
 4612     install_red_hat_linux_git || return 1
 4613     return 0
 4614 }
 4615 
 4616 install_red_hat_enterprise_server_stable() {
 4617     install_red_hat_linux_stable || return 1
 4618     return 0
 4619 }
 4620 
 4621 install_red_hat_enterprise_server_git() {
 4622     install_red_hat_linux_git || return 1
 4623     return 0
 4624 }
 4625 
 4626 install_red_hat_enterprise_workstation_stable() {
 4627     install_red_hat_linux_stable || return 1
 4628     return 0
 4629 }
 4630 
 4631 install_red_hat_enterprise_workstation_git() {
 4632     install_red_hat_linux_git || return 1
 4633     return 0
 4634 }
 4635 
 4636 install_red_hat_linux_stable_post() {
 4637     install_centos_stable_post || return 1
 4638     return 0
 4639 }
 4640 
 4641 install_red_hat_linux_restart_daemons() {
 4642     install_centos_restart_daemons || return 1
 4643     return 0
 4644 }
 4645 
 4646 install_red_hat_linux_git_post() {
 4647     install_centos_git_post || return 1
 4648     return 0
 4649 }
 4650 
 4651 install_red_hat_enterprise_stable_post() {
 4652     install_red_hat_linux_stable_post || return 1
 4653     return 0
 4654 }
 4655 
 4656 install_red_hat_enterprise_restart_daemons() {
 4657     install_red_hat_linux_restart_daemons || return 1
 4658     return 0
 4659 }
 4660 
 4661 install_red_hat_enterprise_git_post() {
 4662     install_red_hat_linux_git_post || return 1
 4663     return 0
 4664 }
 4665 
 4666 install_red_hat_enterprise_linux_stable_post() {
 4667     install_red_hat_linux_stable_post || return 1
 4668     return 0
 4669 }
 4670 
 4671 install_red_hat_enterprise_linux_restart_daemons() {
 4672     install_red_hat_linux_restart_daemons || return 1
 4673     return 0
 4674 }
 4675 
 4676 install_red_hat_enterprise_linux_git_post() {
 4677     install_red_hat_linux_git_post || return 1
 4678     return 0
 4679 }
 4680 
 4681 install_red_hat_enterprise_server_stable_post() {
 4682     install_red_hat_linux_stable_post || return 1
 4683     return 0
 4684 }
 4685 
 4686 install_red_hat_enterprise_server_restart_daemons() {
 4687     install_red_hat_linux_restart_daemons || return 1
 4688     return 0
 4689 }
 4690 
 4691 install_red_hat_enterprise_server_git_post() {
 4692     install_red_hat_linux_git_post || return 1
 4693     return 0
 4694 }
 4695 
 4696 install_red_hat_enterprise_workstation_stable_post() {
 4697     install_red_hat_linux_stable_post || return 1
 4698     return 0
 4699 }
 4700 
 4701 install_red_hat_enterprise_workstation_restart_daemons() {
 4702     install_red_hat_linux_restart_daemons || return 1
 4703     return 0
 4704 }
 4705 
 4706 install_red_hat_enterprise_workstation_git_post() {
 4707     install_red_hat_linux_git_post || return 1
 4708     return 0
 4709 }
 4710 
 4711 install_red_hat_linux_testing_deps() {
 4712     install_centos_testing_deps || return 1
 4713     return 0
 4714 }
 4715 
 4716 install_red_hat_linux_testing() {
 4717     install_centos_testing || return 1
 4718     return 0
 4719 }
 4720 
 4721 install_red_hat_linux_testing_post() {
 4722     install_centos_testing_post || return 1
 4723     return 0
 4724 }
 4725 
 4726 install_red_hat_enterprise_testing_deps() {
 4727     install_centos_testing_deps || return 1
 4728     return 0
 4729 }
 4730 
 4731 install_red_hat_enterprise_testing() {
 4732     install_centos_testing || return 1
 4733     return 0
 4734 }
 4735 
 4736 install_red_hat_enterprise_testing_post() {
 4737     install_centos_testing_post || return 1
 4738     return 0
 4739 }
 4740 
 4741 install_red_hat_enterprise_server_testing_deps() {
 4742     install_centos_testing_deps || return 1
 4743     return 0
 4744 }
 4745 
 4746 install_red_hat_enterprise_server_testing() {
 4747     install_centos_testing || return 1
 4748     return 0
 4749 }
 4750 
 4751 install_red_hat_enterprise_server_testing_post() {
 4752     install_centos_testing_post || return 1
 4753     return 0
 4754 }
 4755 
 4756 install_red_hat_enterprise_workstation_testing_deps() {
 4757     install_centos_testing_deps || return 1
 4758     return 0
 4759 }
 4760 
 4761 install_red_hat_enterprise_workstation_testing() {
 4762     install_centos_testing || return 1
 4763     return 0
 4764 }
 4765 
 4766 install_red_hat_enterprise_workstation_testing_post() {
 4767     install_centos_testing_post || return 1
 4768     return 0
 4769 }
 4770 #
 4771 #   Ended RedHat Install Functions
 4772 #
 4773 #######################################################################################################################
 4774 
 4775 #######################################################################################################################
 4776 #
 4777 #   Oracle Linux Install Functions
 4778 #
 4779 install_oracle_linux_stable_deps() {
 4780     install_centos_stable_deps || return 1
 4781     return 0
 4782 }
 4783 
 4784 install_oracle_linux_git_deps() {
 4785     install_centos_git_deps || return 1
 4786     return 0
 4787 }
 4788 
 4789 install_oracle_linux_testing_deps() {
 4790     install_centos_testing_deps || return 1
 4791     return 0
 4792 }
 4793 
 4794 install_oracle_linux_stable() {
 4795     install_centos_stable || return 1
 4796     return 0
 4797 }
 4798 
 4799 install_oracle_linux_git() {
 4800     install_centos_git || return 1
 4801     return 0
 4802 }
 4803 
 4804 install_oracle_linux_testing() {
 4805     install_centos_testing || return 1
 4806     return 0
 4807 }
 4808 
 4809 install_oracle_linux_stable_post() {
 4810     install_centos_stable_post || return 1
 4811     return 0
 4812 }
 4813 
 4814 install_oracle_linux_git_post() {
 4815     install_centos_git_post || return 1
 4816     return 0
 4817 }
 4818 
 4819 install_oracle_linux_testing_post() {
 4820     install_centos_testing_post || return 1
 4821     return 0
 4822 }
 4823 
 4824 install_oracle_linux_restart_daemons() {
 4825     install_centos_restart_daemons || return 1
 4826     return 0
 4827 }
 4828 
 4829 install_oracle_linux_check_services() {
 4830     install_centos_check_services || return 1
 4831     return 0
 4832 }
 4833 #
 4834 #   Ended Oracle Linux Install Functions
 4835 #
 4836 #######################################################################################################################
 4837 
 4838 #######################################################################################################################
 4839 #
 4840 #   Scientific Linux Install Functions
 4841 #
 4842 install_scientific_linux_stable_deps() {
 4843     install_centos_stable_deps || return 1
 4844     return 0
 4845 }
 4846 
 4847 install_scientific_linux_git_deps() {
 4848     install_centos_git_deps || return 1
 4849     return 0
 4850 }
 4851 
 4852 install_scientific_linux_testing_deps() {
 4853     install_centos_testing_deps || return 1
 4854     return 0
 4855 }
 4856 
 4857 install_scientific_linux_stable() {
 4858     install_centos_stable || return 1
 4859     return 0
 4860 }
 4861 
 4862 install_scientific_linux_git() {
 4863     install_centos_git || return 1
 4864     return 0
 4865 }
 4866 
 4867 install_scientific_linux_testing() {
 4868     install_centos_testing || return 1
 4869     return 0
 4870 }
 4871 
 4872 install_scientific_linux_stable_post() {
 4873     install_centos_stable_post || return 1
 4874     return 0
 4875 }
 4876 
 4877 install_scientific_linux_git_post() {
 4878     install_centos_git_post || return 1
 4879     return 0
 4880 }
 4881 
 4882 install_scientific_linux_testing_post() {
 4883     install_centos_testing_post || return 1
 4884     return 0
 4885 }
 4886 
 4887 install_scientific_linux_restart_daemons() {
 4888     install_centos_restart_daemons || return 1
 4889     return 0
 4890 }
 4891 
 4892 install_scientific_linux_check_services() {
 4893     install_centos_check_services || return 1
 4894     return 0
 4895 }
 4896 #
 4897 #   Ended Scientific Linux Install Functions
 4898 #
 4899 #######################################################################################################################
 4900 
 4901 #######################################################################################################################
 4902 #
 4903 #   CloudLinux Install Functions
 4904 #
 4905 install_cloud_linux_stable_deps() {
 4906     install_centos_stable_deps || return 1
 4907     return 0
 4908 }
 4909 
 4910 install_cloud_linux_git_deps() {
 4911     install_centos_git_deps || return 1
 4912     return 0
 4913 }
 4914 
 4915 install_cloud_linux_testing_deps() {
 4916     install_centos_testing_deps || return 1
 4917     return 0
 4918 }
 4919 
 4920 install_cloud_linux_stable() {
 4921     install_centos_stable || return 1
 4922     return 0
 4923 }
 4924 
 4925 install_cloud_linux_git() {
 4926     install_centos_git || return 1
 4927     return 0
 4928 }
 4929 
 4930 install_cloud_linux_testing() {
 4931     install_centos_testing || return 1
 4932     return 0
 4933 }
 4934 
 4935 install_cloud_linux_stable_post() {
 4936     install_centos_stable_post || return 1
 4937     return 0
 4938 }
 4939 
 4940 install_cloud_linux_git_post() {
 4941     install_centos_git_post || return 1
 4942     return 0
 4943 }
 4944 
 4945 install_cloud_linux_testing_post() {
 4946     install_centos_testing_post || return 1
 4947     return 0
 4948 }
 4949 
 4950 install_cloud_linux_restart_daemons() {
 4951     install_centos_restart_daemons || return 1
 4952     return 0
 4953 }
 4954 
 4955 install_cloud_linux_check_services() {
 4956     install_centos_check_services || return 1
 4957     return 0
 4958 }
 4959 #
 4960 #   End of CloudLinux Install Functions
 4961 #
 4962 #######################################################################################################################
 4963 
 4964 #######################################################################################################################
 4965 #
 4966 #   Alpine Linux Install Functions
 4967 #
 4968 install_alpine_linux_stable_deps() {
 4969     if ! grep -q '^[^#].\+alpine/.\+/community' /etc/apk/repositories; then
 4970         # Add community repository entry based on the "main" repo URL
 4971         __REPO=$(grep '^[^#].\+alpine/.\+/main\>' /etc/apk/repositories)
 4972         echo "${__REPO}" | sed -e 's/main/community/' >> /etc/apk/repositories
 4973     fi
 4974 
 4975     apk update
 4976 
 4977     # Get latest root CA certs
 4978     apk -U add ca-certificates
 4979 
 4980     if ! __check_command_exists openssl; then
 4981         # Install OpenSSL to be able to pull from https:// URLs
 4982         apk -U add openssl
 4983     fi
 4984 }
 4985 
 4986 install_alpine_linux_git_deps() {
 4987     install_alpine_linux_stable_deps || return 1
 4988 
 4989     if ! __check_command_exists git; then
 4990         apk -U add git  || return 1
 4991     fi
 4992 
 4993     __git_clone_and_checkout || return 1
 4994 
 4995     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 4996         apk -U add python2 py-virtualenv py2-crypto py2-m2crypto py2-setuptools \
 4997             py2-jinja2 py2-yaml py2-markupsafe py2-msgpack py2-psutil \
 4998             py2-zmq zeromq py2-requests || return 1
 4999 
 5000         if [ -f "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
 5001             # We're on the master branch, install whichever tornado is on the requirements file
 5002             __REQUIRED_TORNADO="$(grep tornado "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
 5003             if [ "${__REQUIRED_TORNADO}" != "" ]; then
 5004                 apk -U add py2-tornado || return 1
 5005             fi
 5006         fi
 5007     else
 5008         apk -U add python2 py2-pip py2-setuptools || return 1
 5009         _PY_EXE=python2
 5010         return 0
 5011     fi
 5012 
 5013     # Let's trigger config_salt()
 5014     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 5015         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 5016         CONFIG_SALT_FUNC="config_salt"
 5017     fi
 5018 }
 5019 
 5020 install_alpine_linux_stable() {
 5021     __PACKAGES="salt"
 5022 
 5023     if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ];then
 5024         __PACKAGES="${__PACKAGES} salt-cloud"
 5025     fi
 5026     if [ "$_INSTALL_MASTER" -eq $BS_TRUE ]; then
 5027         __PACKAGES="${__PACKAGES} salt-master"
 5028     fi
 5029     if [ "$_INSTALL_MINION" -eq $BS_TRUE ]; then
 5030         __PACKAGES="${__PACKAGES} salt-minion"
 5031     fi
 5032     if [ "$_INSTALL_SYNDIC" -eq $BS_TRUE ]; then
 5033         __PACKAGES="${__PACKAGES} salt-syndic"
 5034     fi
 5035 
 5036     # shellcheck disable=SC2086
 5037     apk -U add ${__PACKAGES} || return 1
 5038     return 0
 5039 }
 5040 
 5041 install_alpine_linux_git() {
 5042 
 5043     if [ "${_POST_NEON_INSTALL}" -eq $BS_TRUE ]; then
 5044          __install_salt_from_repo_post_neon "${_PY_EXE}" || return 1
 5045         return 0
 5046     fi
 5047 
 5048     if [ -f "${_SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
 5049         python2 setup.py --salt-config-dir="$_SALT_ETC_DIR" --salt-cache-dir="${_SALT_CACHE_DIR}" ${SETUP_PY_INSTALL_ARGS} install || return 1
 5050     else
 5051         python2 setup.py ${SETUP_PY_INSTALL_ARGS} install || return 1
 5052     fi
 5053 }
 5054 
 5055 install_alpine_linux_post() {
 5056     for fname in api master minion syndic; do
 5057         # Skip if not meant to be installed
 5058         [ $fname = "api" ] && \
 5059             ([ "$_INSTALL_MASTER" -eq $BS_FALSE ] || ! __check_command_exists "salt-${fname}") && continue
 5060         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 5061         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 5062         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 5063 
 5064         if [ -f /sbin/rc-update ]; then
 5065             script_url="${_SALTSTACK_REPO_URL%.git}/raw/master/pkg/alpine/salt-$fname"
 5066             [ -f "/etc/init.d/salt-$fname" ] || __fetch_url "/etc/init.d/salt-$fname" "$script_url"
 5067 
 5068             # shellcheck disable=SC2181
 5069             if [ $? -eq 0 ]; then
 5070                 chmod +x "/etc/init.d/salt-$fname"
 5071             else
 5072                 echoerror "Failed to get OpenRC init script for $OS_NAME from $script_url."
 5073                 return 1
 5074             fi
 5075 
 5076             # Skip salt-api since the service should be opt-in and not necessarily started on boot
 5077             [ $fname = "api" ] && continue
 5078 
 5079             /sbin/rc-update add "salt-$fname" > /dev/null 2>&1 || return 1
 5080         fi
 5081     done
 5082 }
 5083 
 5084 install_alpine_linux_restart_daemons() {
 5085     [ "${_START_DAEMONS}" -eq $BS_FALSE ] && return
 5086 
 5087     for fname in api master minion syndic; do
 5088         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 5089         [ $fname = "api" ] && continue
 5090 
 5091         # Skip if not meant to be installed
 5092         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 5093         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 5094         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 5095 
 5096         # Disable stdin to fix shell session hang on killing tee pipe
 5097         /sbin/rc-service salt-$fname stop < /dev/null > /dev/null 2>&1
 5098         /sbin/rc-service salt-$fname start < /dev/null || return 1
 5099     done
 5100 }
 5101 
 5102 install_alpine_linux_check_services() {
 5103     for fname in api master minion syndic; do
 5104         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 5105         [ $fname = "api" ] && continue
 5106 
 5107         # Skip if not meant to be installed
 5108         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 5109         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 5110         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 5111 
 5112         __check_services_openrc salt-$fname || return 1
 5113     done
 5114 
 5115     return 0
 5116 }
 5117 
 5118 daemons_running_alpine_linux() {
 5119     [ "${_START_DAEMONS}" -eq $BS_FALSE ] && return
 5120 
 5121     FAILED_DAEMONS=0
 5122     for fname in api master minion syndic; do
 5123         # Skip salt-api since the service should be opt-in and not necessarily started on boot
 5124         [ $fname = "api" ] && continue
 5125 
 5126         # Skip if not meant to be installed
 5127         [ $fname = "minion" ] && [ "$_INSTALL_MINION" -eq $BS_FALSE ] && continue
 5128         [ $fname = "master" ] && [ "$_INSTALL_MASTER" -eq $BS_FALSE ] && continue
 5129         [ $fname = "syndic" ] && [ "$_INSTALL_SYNDIC" -eq $BS_FALSE ] && continue
 5130 
 5131         # shellcheck disable=SC2009
 5132         if [ "$(ps wwwaux | grep -v grep | grep salt-$fname)" = "" ]; then
 5133             echoerror "salt-$fname was not found running"
 5134             FAILED_DAEMONS=$((FAILED_DAEMONS + 1))
 5135         fi
 5136     done
 5137 
 5138     return $FAILED_DAEMONS
 5139 }
 5140 
 5141 #
 5142 #   Ended Alpine Linux Install Functions
 5143 #
 5144 #######################################################################################################################
 5145 
 5146 
 5147 #######################################################################################################################
 5148 #
 5149 #   Amazon Linux AMI Install Functions
 5150 #
 5151 
 5152 install_amazon_linux_ami_deps() {
 5153     # Shim to figure out if we're using old (rhel) or new (aws) rpms.
 5154     _USEAWS=$BS_FALSE
 5155     pkg_append="python"
 5156 
 5157     if [ "$ITYPE" = "stable" ]; then
 5158         repo_rev="$STABLE_REV"
 5159     else
 5160         repo_rev="latest"
 5161     fi
 5162 
 5163     if echo $repo_rev | grep -E -q '^archive'; then
 5164         year=$(echo "$repo_rev" | cut -d '/' -f 2 | cut -c1-4)
 5165     else
 5166         year=$(echo "$repo_rev" | cut -c1-4)
 5167     fi
 5168 
 5169     if echo "$repo_rev" | grep -E -q '^(latest|2016\.11)$' || \
 5170             [ "$year" -gt 2016 ]; then
 5171        _USEAWS=$BS_TRUE
 5172        pkg_append="python27"
 5173     fi
 5174 
 5175     # We need to install yum-utils before doing anything else when installing on
 5176     # Amazon Linux ECS-optimized images. See issue #974.
 5177     __yum_install_noinput yum-utils
 5178 
 5179     # Do upgrade early
 5180     if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then
 5181         yum -y update || return 1
 5182     fi
 5183 
 5184     if [ $_DISABLE_REPOS -eq $BS_FALSE ] || [ "$_CUSTOM_REPO_URL" != "null" ]; then
 5185         __REPO_FILENAME="saltstack-repo.repo"
 5186 
 5187         # Set a few vars to make life easier.
 5188         if [ $_USEAWS -eq $BS_TRUE ]; then
 5189            base_url="$HTTP_VAL://${_REPO_URL}/yum/amazon/latest/\$basearch/$repo_rev/"
 5190            gpg_key="${base_url}SALTSTACK-GPG-KEY.pub"
 5191            repo_name="SaltStack repo for Amazon Linux"
 5192         else
 5193            base_url="$HTTP_VAL://${_REPO_URL}/yum/redhat/6/\$basearch/$repo_rev/"
 5194            gpg_key="${base_url}SALTSTACK-GPG-KEY.pub"
 5195            repo_name="SaltStack repo for RHEL/CentOS 6"
 5196         fi
 5197 
 5198         # This should prob be refactored to use __install_saltstack_rhel_repository()
 5199         # With args passed in to do the right thing.  Reformatted to be more like the
 5200         # amazon linux yum file.
 5201         if [ ! -s "/etc/yum.repos.d/${__REPO_FILENAME}" ]; then
 5202           cat <<_eof > "/etc/yum.repos.d/${__REPO_FILENAME}"
 5203 [saltstack-repo]
 5204 name=$repo_name
 5205 failovermethod=priority
 5206 priority=10
 5207 gpgcheck=1
 5208 gpgkey=$gpg_key
 5209 baseurl=$base_url
 5210 _eof
 5211         fi
 5212 
 5213     fi
 5214 
 5215     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 5216         # Package python-ordereddict-1.1-2.el6.noarch is obsoleted by python26-2.6.9-2.88.amzn1.x86_64
 5217         # which is already installed
 5218         __PACKAGES="m2crypto ${pkg_append}-crypto ${pkg_append}-jinja2 ${pkg_append}-PyYAML"
 5219         __PACKAGES="${__PACKAGES} ${pkg_append}-msgpack ${pkg_append}-requests ${pkg_append}-zmq"
 5220         __PACKAGES="${__PACKAGES} ${pkg_append}-futures"
 5221         # shellcheck disable=SC2086
 5222         __yum_install_noinput ${__PACKAGES} || return 1
 5223     fi
 5224 
 5225     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 5226         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 5227         # shellcheck disable=SC2086
 5228         __yum_install_noinput ${_EXTRA_PACKAGES} || return 1
 5229     fi
 5230 }
 5231 
 5232 install_amazon_linux_ami_git_deps() {
 5233     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 5234         yum -y install ca-certificates || return 1
 5235     fi
 5236 
 5237     PIP_EXE='pip'
 5238     if __check_command_exists python2.7; then
 5239         if ! __check_command_exists pip2.7; then
 5240             if ! __check_command_exists easy_install-2.7; then
 5241                 __yum_install_noinput python27-setuptools
 5242             fi
 5243             /usr/bin/easy_install-2.7 pip || return 1
 5244         fi
 5245         PIP_EXE='/usr/local/bin/pip2.7'
 5246         _PY_EXE='python2.7'
 5247     fi
 5248 
 5249     install_amazon_linux_ami_deps || return 1
 5250 
 5251     if ! __check_command_exists git; then
 5252         __yum_install_noinput git || return 1
 5253     fi
 5254 
 5255     __git_clone_and_checkout || return 1
 5256 
 5257     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 5258         __PACKAGES=""
 5259         __PIP_PACKAGES=""
 5260 
 5261         if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
 5262             __check_pip_allowed "You need to allow pip based installations (-P) in order to install apache-libcloud"
 5263             __PACKAGES="${__PACKAGES} python27-pip"
 5264             __PIP_PACKAGES="${__PIP_PACKAGES} apache-libcloud>=$_LIBCLOUD_MIN_VERSION"
 5265         fi
 5266 
 5267         if [ -f "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
 5268             # We're on the master branch, install whichever tornado is on the requirements file
 5269             __REQUIRED_TORNADO="$(grep tornado "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
 5270             if [ "${__REQUIRED_TORNADO}" != "" ]; then
 5271                 __PACKAGES="${__PACKAGES} ${pkg_append}-tornado"
 5272             fi
 5273         fi
 5274 
 5275         if [ "${__PACKAGES}" != "" ]; then
 5276             # shellcheck disable=SC2086
 5277             __yum_install_noinput ${__PACKAGES} || return 1
 5278         fi
 5279 
 5280         if [ "${__PIP_PACKAGES}" != "" ]; then
 5281             # shellcheck disable=SC2086
 5282             ${PIP_EXE} install ${__PIP_PACKAGES} || return 1
 5283         fi
 5284     else
 5285         __PACKAGES="python27-pip python27-setuptools python27-devel gcc"
 5286             # shellcheck disable=SC2086
 5287         __yum_install_noinput ${__PACKAGES} || return 1
 5288     fi
 5289 
 5290     # Let's trigger config_salt()
 5291     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 5292         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 5293         CONFIG_SALT_FUNC="config_salt"
 5294     fi
 5295 
 5296     return 0
 5297 }
 5298 
 5299 install_amazon_linux_ami_2_git_deps() {
 5300     if [ "$_INSECURE_DL" -eq $BS_FALSE ] && [ "${_SALT_REPO_URL%%://*}" = "https" ]; then
 5301         yum -y install ca-certificates || return 1
 5302     fi
 5303 
 5304     install_amazon_linux_ami_2_deps || return 1
 5305 
 5306     if [ "$_PY_MAJOR_VERSION" -eq 2 ]; then
 5307         PY_PKG_VER=2
 5308         PIP_EXE='/bin/pip'
 5309     else
 5310         PY_PKG_VER=3
 5311         PIP_EXE='/bin/pip3'
 5312     fi
 5313     __PACKAGES="python${PY_PKG_VER}-pip"
 5314 
 5315     if ! __check_command_exists "${PIP_EXE}"; then
 5316         # shellcheck disable=SC2086
 5317         __yum_install_noinput ${__PACKAGES} || return 1
 5318     fi
 5319 
 5320     if ! __check_command_exists git; then
 5321         __yum_install_noinput git || return 1
 5322     fi
 5323 
 5324     __git_clone_and_checkout || return 1
 5325 
 5326     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 5327 
 5328         __PACKAGES=""
 5329         __PIP_PACKAGES=""
 5330 
 5331         if [ "$_INSTALL_CLOUD" -eq "$BS_TRUE" ]; then
 5332             __check_pip_allowed "You need to allow pip based installations (-P) in order to install apache-libcloud"
 5333             if [ "$PARSED_VERSION" -eq "2" ]; then
 5334                 if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq "3" ]; then
 5335                     __PACKAGES="${__PACKAGES} python3-pip"
 5336                     __PIP_PACKAGES="${__PIP_PACKAGES} tornado<$_TORNADO_MAX_PY3_VERSION"
 5337                 else
 5338                     __PACKAGES="${__PACKAGES} python2-pip"
 5339                 fi
 5340             else
 5341                 __PACKAGES="${__PACKAGES} python27-pip"
 5342             fi
 5343             __PIP_PACKAGES="${__PIP_PACKAGES} apache-libcloud>=$_LIBCLOUD_MIN_VERSION"
 5344         fi
 5345 
 5346         if [ -f "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
 5347             # We're on the master branch, install whichever tornado is on the requirements file
 5348             __REQUIRED_TORNADO="$(grep tornado "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
 5349             if [ "${__REQUIRED_TORNADO}" != "" ]; then
 5350                 if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq "3" ]; then
 5351                     __PIP_PACKAGES="${__PIP_PACKAGES} tornado<$_TORNADO_MAX_PY3_VERSION"
 5352                 else
 5353                     __PACKAGES="${__PACKAGES} ${pkg_append}${PY_PKG_VER}-tornado"
 5354                 fi
 5355             fi
 5356         fi
 5357 
 5358         if [ "${__PIP_PACKAGES}" != "" ]; then
 5359             __check_pip_allowed "You need to allow pip based installations (-P) in order to install ${__PIP_PACKAGES}"
 5360             __PACKAGES="${__PACKAGES} python${PY_PKG_VER}-pip"
 5361         fi
 5362 
 5363         if [ "${__PACKAGES}" != "" ]; then
 5364             # shellcheck disable=SC2086
 5365             __yum_install_noinput ${__PACKAGES} || return 1
 5366         fi
 5367 
 5368         if [ "${__PIP_PACKAGES}" != "" ]; then
 5369             # shellcheck disable=SC2086
 5370             ${PIP_EXE} install ${__PIP_PACKAGES} || return 1
 5371         fi
 5372     else
 5373         __PACKAGES="python${PY_PKG_VER}-pip python${PY_PKG_VER}-setuptools python${PY_PKG_VER}-devel gcc"
 5374         # shellcheck disable=SC2086
 5375         __yum_install_noinput ${__PACKAGES} || return 1
 5376     fi
 5377 
 5378     # Let's trigger config_salt()
 5379     if [ "$_TEMP_CONFIG_DIR" = "null" ]; then
 5380         _TEMP_CONFIG_DIR="${_SALT_GIT_CHECKOUT_DIR}/conf/"
 5381         CONFIG_SALT_FUNC="config_salt"
 5382     fi
 5383 
 5384     return 0
 5385 }
 5386 
 5387 install_amazon_linux_ami_2_deps() {
 5388     # Shim to figure out if we're using old (rhel) or new (aws) rpms.
 5389     _USEAWS=$BS_FALSE
 5390     pkg_append="python"
 5391 
 5392     if [ "$ITYPE" = "stable" ]; then
 5393         repo_rev="$STABLE_REV"
 5394     else
 5395         repo_rev="latest"
 5396     fi
 5397 
 5398     if echo $repo_rev | grep -E -q '^archive'; then
 5399         year=$(echo "$repo_rev" | cut -d '/' -f 2 | cut -c1-4)
 5400     else
 5401         year=$(echo "$repo_rev" | cut -c1-4)
 5402     fi
 5403 
 5404     if echo "$repo_rev" | grep -E -q '^(latest|2016\.11)$' || \
 5405             [ "$year" -gt 2016 ]; then
 5406        _USEAWS=$BS_TRUE
 5407        pkg_append="python"
 5408     fi
 5409 
 5410     # We need to install yum-utils before doing anything else when installing on
 5411     # Amazon Linux ECS-optimized images. See issue #974.
 5412     __yum_install_noinput yum-utils
 5413 
 5414     # Do upgrade early
 5415     if [ "$_UPGRADE_SYS" -eq $BS_TRUE ]; then
 5416         yum -y update || return 1
 5417     fi
 5418 
 5419     if [ $_DISABLE_REPOS -eq $BS_FALSE ] || [ "$_CUSTOM_REPO_URL" != "null" ]; then
 5420         __REPO_FILENAME="saltstack-repo.repo"
 5421         __PY_VERSION_REPO="yum"
 5422         PY_PKG_VER=""
 5423         repo_label="saltstack-repo"
 5424         repo_name="SaltStack repo for Amazon Linux 2"
 5425         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 5426             __REPO_FILENAME="saltstack-py3-repo.repo"
 5427             __PY_VERSION_REPO="py3"
 5428             PY_PKG_VER=3
 5429             repo_label="saltstack-py3-repo"
 5430             repo_name="SaltStack Python 3 repo for Amazon Linux 2"
 5431         fi
 5432 
 5433         base_url="$HTTP_VAL://${_REPO_URL}/${__PY_VERSION_REPO}/amazon/2/\$basearch/$repo_rev/"
 5434         gpg_key="${base_url}SALTSTACK-GPG-KEY.pub,${base_url}base/RPM-GPG-KEY-CentOS-7"
 5435         if [ -n "$_PY_EXE" ] && [ "$_PY_MAJOR_VERSION" -eq 3 ]; then
 5436             gpg_key="${base_url}SALTSTACK-GPG-KEY.pub"
 5437         fi
 5438 
 5439         # This should prob be refactored to use __install_saltstack_rhel_repository()
 5440         # With args passed in to do the right thing.  Reformatted to be more like the
 5441         # amazon linux yum file.
 5442         if [ ! -s "/etc/yum.repos.d/${__REPO_FILENAME}" ]; then
 5443           cat <<_eof > "/etc/yum.repos.d/${__REPO_FILENAME}"
 5444 [$repo_label]
 5445 name=$repo_name
 5446 failovermethod=priority
 5447 priority=10
 5448 gpgcheck=1
 5449 gpgkey=$gpg_key
 5450 baseurl=$base_url
 5451 _eof
 5452         fi
 5453 
 5454     fi
 5455 
 5456     if [ "${_POST_NEON_INSTALL}" -eq $BS_FALSE ]; then
 5457         # Package python-ordereddict-1.1-2.el6.noarch is obsoleted by python26-2.6.9-2.88.amzn1.x86_64
 5458         # which is already installed
 5459         if [ -n "${PY_PKG_VER}" ] && [ "${PY_PKG_VER}" -eq 3 ]; then
 5460             __PACKAGES="${pkg_append}${PY_PKG_VER}-m2crypto ${pkg_append}${PY_PKG_VER}-pyyaml"
 5461         else
 5462             __PACKAGES="m2crypto PyYAML ${pkg_append}-futures"
 5463         fi
 5464 
 5465         __PACKAGES="${__PACKAGES} ${pkg_append}${PY_PKG_VER}-crypto ${pkg_append}${PY_PKG_VER}-jinja2 procps-ng"
 5466         __PACKAGES="${__PACKAGES} ${pkg_append}${PY_PKG_VER}-msgpack ${pkg_append}${PY_PKG_VER}-requests ${pkg_append}${PY_PKG_VER}-zmq"
 5467 
 5468         # shellcheck disable=SC2086
 5469         __yum_install_noinput ${__PACKAGES} || return 1
 5470     fi
 5471 
 5472     if [ "${_EXTRA_PACKAGES}" != "" ]; then
 5473         echoinfo "Installing the following extra packages as requested: ${_EXTRA_PACKAGES}"
 5474         # shellcheck disable=SC2086
 5475         __yum_install_noinput ${_EXTRA_PACKAGES} || return 1
 5476     fi
 5477 }
 5478 
 5479 install_amazon_linux_ami_stable() {
 5480     install_centos_stable || return 1
 5481     return 0
 5482 }
 5483 
 5484 install_amazon_linux_ami_stable_post() {
 5485     install_centos_stable_post || return 1
 5486     return 0
 5487 }
 5488 
 5489 install_amazon_linux_ami_restart_daemons() {
 5490     install_centos_restart_daemons || return 1
 5491     return 0
 5492 }
 5493 
 5494 install_amazon_linux_ami_git() {
 5495     install_centos_git || return 1
 5496     return 0
 5497 }
 5498 
 5499 install_amazon_linux_ami_git_post() {
 5500     install_centos_git_post || return 1
 5501     return 0
 5502 }
 5503 
 5504 install_amazon_linux_ami_testing() {
 5505     install_centos_testing || return 1
 5506     return 0
 5507 }
 5508 
 5509 install_amazon_linux_ami_testing_post() {
 5510     install_centos_testing_post || return 1
 5511     return 0
 5512 }
 5513 
 5514 install_amazon_linux_ami_2_stable() {
 5515     install_centos_stable || return 1
 5516     return 0
 5517 }
 5518 
 5519 install_amazon_linux_ami_2_stable_post() {
 5520     install_centos_stable_post || return 1
 5521     return 0
 5522 }
 5523 
 5524 install_amazon_linux_ami_2_restart_daemons() {
 5525     install_centos_restart_daemons || return 1
 5526     return 0
 5527 }
 5528 
 5529 install_amazon_linux_ami_2_git() {
 5530     install_centos_git || return 1
 5531     return 0
 5532 }
 5533 
 5534 install_amazon_linux_ami_2_git_post() {
 5535     install_centos_git_post || return 1
 5536     return 0
 5537 }
 5538 
 5539 install_amazon_linux_ami_2_testing() {
 5540     install_centos_testing || return 1
 5541     return 0
 5542 }
 5543 
 5544 install_amazon_linux_ami_2_testing_post() {
 5545     install_centos_testing_post || return 1
 5546     return 0
 5547 }
 5548 
 5549 install_amazon_linux_ami_2_check_services() {
 5550     install_centos_check_services || return 1
 5551     return 0
 5552 }
 5553 
 5554 #
 5555 #   Ended Amazon Linux AMI Install Functions
 5556 #
 5557 #######################################################################################################################
 5558 
 5559 #######################################################################################################################
 5560 #
 5561 #   Arch Install Functions
 5562 #
 5563 install_arch_linux_stable_deps() {
 5564     if [ ! -f /etc/pacman.d/gnupg ]; then
 5565         pacman-key --init && pacman-key --populate archlinux || return 1
 5566     fi
 5567 
 5568     # Pacman does not resolve dependencies on outdated versions
 5569     # They always need to be updated
 5570     pacman -Syy --noconfirm
 5571 
 5572     pacman -S --noconfirm --needed archlinux-keyring || return 1
 5573 <