X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/972f9d0c4c32082e873bcbe29d5f7ac87b66af4a..cfd1df694f8add55ea34324407208a1f100aea42:/tools/salt-install/provision.sh diff --git a/tools/salt-install/provision.sh b/tools/salt-install/provision.sh index 5f6c389b76..4f9c209ef0 100755 --- a/tools/salt-install/provision.sh +++ b/tools/salt-install/provision.sh @@ -41,13 +41,13 @@ usage() { echo >&2 " -h, --help Display this help and exit" echo >&2 " --dump-config Dumps the pillars and states to a directory" echo >&2 " This parameter does not perform any installation at all. It's" - echo >&2 " intended to give you a parsed sot of configuration files so" + echo >&2 " intended to give you a parsed set of configuration files so" echo >&2 " you can inspect them or use them in you Saltstack infrastructure." echo >&2 " It" echo >&2 " - parses the pillar and states templates," echo >&2 " - downloads the helper formulas with their desired versions," echo >&2 " - prepares the 'top.sls' files both for pillars and states" - echo >&2 " for the selected role/s" + echo >&2 " for the selected role(s)" echo >&2 " - writes the resulting files into " echo >&2 " -v, --vagrant Run in vagrant and use the /vagrant shared dir" echo >&2 " --development Run in dev mode, using snakeoil certs" @@ -189,7 +189,7 @@ WORKBENCH2_EXT_SSL_PORT=3001 SSL_MODE="self-signed" USE_LETSENCRYPT_ROUTE53="no" -CUSTOM_CERTS_DIR="${SCRIPT_DIR}/certs" +CUSTOM_CERTS_DIR="${SCRIPT_DIR}/local_config_dir/certs" ## These are ARVADOS-related parameters # For a stable release, change RELEASE "production" and VERSION to the @@ -206,12 +206,17 @@ VERSION="latest" # ARVADOS_TAG="2.2.0" # BRANCH="main" +# We pin the salt version to avoid potential incompatibilities when a new +# stable version is released. +SALT_VERSION="3004" + # Other formula versions we depend on POSTGRES_TAG="v0.44.0" NGINX_TAG="v2.8.1" DOCKER_TAG="v2.4.2" LOCALE_TAG="v0.3.4" LETSENCRYPT_TAG="v2.1.0" +LOGROTATE_TAG="v0.14.0" # Salt's dir DUMP_SALT_CONFIG_DIR="" @@ -226,6 +231,8 @@ T_DIR="/tmp/cluster_tests" arguments ${@} +declare -A NODES + if [ -s ${CONFIG_FILE} ]; then source ${CONFIG_FILE} else @@ -244,14 +251,14 @@ if [ ! -d ${CONFIG_DIR} ]; then exit 1 fi -if grep -q 'fixme_or_this_wont_work' ${CONFIG_FILE} ; then +if grep -rni 'fixme' ${CONFIG_FILE} ${CONFIG_DIR} ; then echo >&2 "The config file ${CONFIG_FILE} has some parameters that need to be modified." echo >&2 "Please, fix them and re-run the provision script." exit 1 fi if ! grep -qE '^[[:alnum:]]{5}$' <<<${CLUSTER} ; then - echo >&2 "ERROR: must be exactly 5 alphanumeric characters long" + echo >&2 "ERROR: must be exactly 5 lowercase alphanumeric characters long" echo >&2 "Fix the cluster name in the 'local.params' file and re-run the provision script" exit 1 fi @@ -263,7 +270,7 @@ if [ ! -z "${HOSTNAME_EXT}" ] ; then # Make sure that the value configured as IP_INT is a real IP on the system. # If we don't error out early here when there is a mismatch, the formula will # fail with hard to interpret nginx errors later on. - ip addr list |grep -q "${IP_INT}/" + ip addr list |grep "${IP_INT}/" >/dev/null if [[ $? -ne 0 ]]; then echo "Unable to find the IP_INT address '${IP_INT}' on the system, please correct the value in local.params. Exiting..." exit 1 @@ -291,7 +298,10 @@ else yum install -y curl git jq ;; "debian"|"ubuntu") - DEBIAN_FRONTEND=noninteractive apt update + # Wait 2 minutes for any apt locks to clear + # This option is supported from apt 1.9.1 and ignored in older apt versions. + # Cf. https://blog.sinjakli.co.uk/2021/10/25/waiting-for-apt-locks-without-the-hacky-bash-scripts/ + DEBIAN_FRONTEND=noninteractive apt -o DPkg::Lock::Timeout=120 update DEBIAN_FRONTEND=noninteractive apt install -y curl git jq ;; esac @@ -300,7 +310,7 @@ else echo "Salt already installed" else curl -L https://bootstrap.saltstack.com -o /tmp/bootstrap_salt.sh - sh /tmp/bootstrap_salt.sh -XdfP -x python3 + sh /tmp/bootstrap_salt.sh -XdfP -x python3 stable ${SALT_VERSION} /bin/systemctl stop salt-minion.service /bin/systemctl disable salt-minion.service fi @@ -326,34 +336,43 @@ mkdir -p ${S_DIR} ${F_DIR} ${P_DIR} ${T_DIR} # Get the formula and dependencies cd ${F_DIR} || exit 1 echo "Cloning formulas" -rm -rf ${F_DIR}/* || exit 1 -git clone --quiet https://github.com/saltstack-formulas/docker-formula.git ${F_DIR}/docker -( cd docker && git checkout --quiet tags/"${DOCKER_TAG}" -b "${DOCKER_TAG}" ) +test -d docker && ( cd docker && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/docker-formula.git ${F_DIR}/docker +( cd docker && git checkout --quiet tags/"${DOCKER_TAG}" ) echo "...locale" -git clone --quiet https://github.com/saltstack-formulas/locale-formula.git ${F_DIR}/locale -( cd locale && git checkout --quiet tags/"${LOCALE_TAG}" -b "${LOCALE_TAG}" ) +test -d locale && ( cd locale && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/locale-formula.git ${F_DIR}/locale +( cd locale && git checkout --quiet tags/"${LOCALE_TAG}" ) echo "...nginx" -git clone --quiet https://github.com/saltstack-formulas/nginx-formula.git ${F_DIR}/nginx -( cd nginx && git checkout --quiet tags/"${NGINX_TAG}" -b "${NGINX_TAG}" ) +test -d nginx && ( cd nginx && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/nginx-formula.git ${F_DIR}/nginx +( cd nginx && git checkout --quiet tags/"${NGINX_TAG}" ) echo "...postgres" -git clone --quiet https://github.com/saltstack-formulas/postgres-formula.git ${F_DIR}/postgres -( cd postgres && git checkout --quiet tags/"${POSTGRES_TAG}" -b "${POSTGRES_TAG}" ) +test -d postgres && ( cd postgres && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/postgres-formula.git ${F_DIR}/postgres +( cd postgres && git checkout --quiet tags/"${POSTGRES_TAG}" ) echo "...letsencrypt" -git clone --quiet https://github.com/saltstack-formulas/letsencrypt-formula.git ${F_DIR}/letsencrypt -( cd letsencrypt && git checkout --quiet tags/"${LETSENCRYPT_TAG}" -b "${LETSENCRYPT_TAG}" ) +test -d letsencrypt && ( cd letsencrypt && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/letsencrypt-formula.git ${F_DIR}/letsencrypt +( cd letsencrypt && git checkout --quiet tags/"${LETSENCRYPT_TAG}" ) + +echo "...logrotate" +test -d logrotate && ( cd logrotate && git fetch ) \ + || git clone --quiet https://github.com/saltstack-formulas/logrotate-formula.git ${F_DIR}/logrotate +( cd logrotate && git checkout --quiet tags/"${LOGROTATE_TAG}" ) echo "...arvados" -git clone --quiet https://git.arvados.org/arvados-formula.git ${F_DIR}/arvados +test -d arvados || git clone --quiet https://git.arvados.org/arvados-formula.git ${F_DIR}/arvados # If we want to try a specific branch of the formula if [ "x${BRANCH}" != "x" ]; then ( cd ${F_DIR}/arvados && git checkout --quiet -t origin/"${BRANCH}" -b "${BRANCH}" ) elif [ "x${ARVADOS_TAG}" != "x" ]; then -( cd ${F_DIR}/arvados && git checkout --quiet tags/"${ARVADOS_TAG}" -b "${ARVADOS_TAG}" ) + ( cd ${F_DIR}/arvados && git checkout --quiet tags/"${ARVADOS_TAG}" -b "${ARVADOS_TAG}" ) fi if [ "x${VAGRANT}" = "xyes" ]; then @@ -417,30 +436,34 @@ for f in $(ls "${SOURCE_PILLARS_DIR}"/*); do "${f}" > "${P_DIR}"/$(basename "${f}") done -if [ "x${TEST}" = "xyes" ] && [ ! -d "${SOURCE_TESTS_DIR}" ]; then - echo "You requested to run tests, but ${SOURCE_TESTS_DIR} does not exist or is not a directory. Exiting." - exit 1 -fi -mkdir -p ${T_DIR} -# Replace cluster and domain name in the test files -for f in $(ls "${SOURCE_TESTS_DIR}"/*); do - FILTERS="s#__CLUSTER__#${CLUSTER}#g; - s#__CONTROLLER_EXT_SSL_PORT__#${CONTROLLER_EXT_SSL_PORT}#g; - s#__DOMAIN__#${DOMAIN}#g; - s#__IP_INT__#${IP_INT}#g; - s#__INITIAL_USER_EMAIL__#${INITIAL_USER_EMAIL}#g; - s#__INITIAL_USER_PASSWORD__#${INITIAL_USER_PASSWORD}#g - s#__INITIAL_USER__#${INITIAL_USER}#g; - s#__DATABASE_PASSWORD__#${DATABASE_PASSWORD}#g; - s#__SYSTEM_ROOT_TOKEN__#${SYSTEM_ROOT_TOKEN}#g" - if [ "$USE_SINGLE_HOSTNAME" = "yes" ]; then - FILTERS="s#__CLUSTER__.__DOMAIN__#${HOSTNAME_EXT}#g; - $FILTERS" +if [ ! -d "${SOURCE_TESTS_DIR}" ]; then + echo "WARNING: The tests directory was not copied to \"${SOURCE_TESTS_DIR}\"." + if [ "x${TEST}" = "xyes" ]; then + echo "WARNING: Disabling tests for this installation." fi - sed "$FILTERS" \ - "${f}" > ${T_DIR}/$(basename "${f}") -done -chmod 755 ${T_DIR}/run-test.sh + TEST="no" +else + mkdir -p ${T_DIR} + # Replace cluster and domain name in the test files + for f in $(ls "${SOURCE_TESTS_DIR}"/*); do + FILTERS="s#__CLUSTER__#${CLUSTER}#g; + s#__CONTROLLER_EXT_SSL_PORT__#${CONTROLLER_EXT_SSL_PORT}#g; + s#__DOMAIN__#${DOMAIN}#g; + s#__IP_INT__#${IP_INT}#g; + s#__INITIAL_USER_EMAIL__#${INITIAL_USER_EMAIL}#g; + s#__INITIAL_USER_PASSWORD__#${INITIAL_USER_PASSWORD}#g + s#__INITIAL_USER__#${INITIAL_USER}#g; + s#__DATABASE_PASSWORD__#${DATABASE_PASSWORD}#g; + s#__SYSTEM_ROOT_TOKEN__#${SYSTEM_ROOT_TOKEN}#g" + if [ "$USE_SINGLE_HOSTNAME" = "yes" ]; then + FILTERS="s#__CLUSTER__.__DOMAIN__#${HOSTNAME_EXT}#g; + $FILTERS" + fi + sed "$FILTERS" \ + "${f}" > ${T_DIR}/$(basename "${f}") + done + chmod 755 ${T_DIR}/run-test.sh +fi # Replace helper state files that differ from the formula's examples if [ -d "${SOURCE_STATES_DIR}" ]; then @@ -534,25 +557,29 @@ if [ -z "${ROLES}" ]; then fi grep -q "letsencrypt" ${S_DIR}/top.sls || echo " - letsencrypt" >> ${S_DIR}/top.sls else - # Use custom certs, as both bring-your-own and self-signed are copied using this state - # Copy certs to formula extra/files - # In dev mode, the files will be created and put in the destination directory by the - # snakeoil_certs.sls state file mkdir -p /srv/salt/certs - cp -rv ${CUSTOM_CERTS_DIR}/* /srv/salt/certs/ - # We add the custom_certs state - grep -q "custom_certs" ${S_DIR}/top.sls || echo " - extra.custom_certs" >> ${S_DIR}/top.sls + if [ "${SSL_MODE}" = "bring-your-own" ]; then + # Copy certs to formula extra/files + cp -rv ${CUSTOM_CERTS_DIR}/* /srv/salt/certs/ + # We add the custom_certs state + grep -q "custom_certs" ${S_DIR}/top.sls || echo " - extra.custom_certs" >> ${S_DIR}/top.sls + fi + # In self-signed mode, the certificate files will be created and put in the + # destination directory by the snakeoil_certs.sls state file fi echo " - postgres" >> ${S_DIR}/top.sls + echo " - logrotate" >> ${S_DIR}/top.sls echo " - docker.software" >> ${S_DIR}/top.sls echo " - arvados" >> ${S_DIR}/top.sls echo " - extra.shell_sudo_passwordless" >> ${S_DIR}/top.sls echo " - extra.shell_cron_add_login_sync" >> ${S_DIR}/top.sls + echo " - extra.passenger_rvm" >> ${S_DIR}/top.sls # Pillars echo " - docker" >> ${P_DIR}/top.sls echo " - nginx_api_configuration" >> ${P_DIR}/top.sls + echo " - logrotate_api" >> ${P_DIR}/top.sls echo " - nginx_controller_configuration" >> ${P_DIR}/top.sls echo " - nginx_keepproxy_configuration" >> ${P_DIR}/top.sls echo " - nginx_keepweb_configuration" >> ${P_DIR}/top.sls @@ -561,6 +588,7 @@ if [ -z "${ROLES}" ]; then echo " - nginx_webshell_configuration" >> ${P_DIR}/top.sls echo " - nginx_workbench2_configuration" >> ${P_DIR}/top.sls echo " - nginx_workbench_configuration" >> ${P_DIR}/top.sls + echo " - logrotate_wb1" >> ${P_DIR}/top.sls echo " - postgresql" >> ${P_DIR}/top.sls # We need to tweak the Nginx's pillar depending whether we want plan nginx or nginx+passenger @@ -573,11 +601,27 @@ if [ -z "${ROLES}" ]; then fi grep -q "letsencrypt" ${P_DIR}/top.sls || echo " - letsencrypt" >> ${P_DIR}/top.sls - # As the pillar differ whether we use LE or custom certs, we need to do a final edition on them - for c in controller websocket workbench workbench2 webshell download collections keepproxy; do - sed -i "s/__CERT_REQUIRES__/cmd: create-initial-cert-${c}.${CLUSTER}.${DOMAIN}*/g; - s#__CERT_PEM__#/etc/letsencrypt/live/${c}.${CLUSTER}.${DOMAIN}/fullchain.pem#g; - s#__CERT_KEY__#/etc/letsencrypt/live/${c}.${CLUSTER}.${DOMAIN}/privkey.pem#g" \ + hosts=("controller" "websocket" "workbench" "workbench2" "webshell" "keepproxy") + if [ ${USE_SINGLE_HOSTNAME} = "no" ]; then + hosts+=("download" "collections") + else + hosts+=("keepweb") + fi + + for c in "${hosts[@]}"; do + # Are we in a single-host-single-hostname env? + if [ "${USE_SINGLE_HOSTNAME}" = "yes" ]; then + # Are we in a single-host-single-hostname env? + CERT_NAME=${HOSTNAME_EXT} + else + # We are in a multiple-hostnames env + CERT_NAME=${c}.${CLUSTER}.${DOMAIN} + fi + + # As the pillar differs whether we use LE or custom certs, we need to do a final edition on them + sed -i "s/__CERT_REQUIRES__/cmd: create-initial-cert-${CERT_NAME}*/g; + s#__CERT_PEM__#/etc/letsencrypt/live/${CERT_NAME}/fullchain.pem#g; + s#__CERT_KEY__#/etc/letsencrypt/live/${CERT_NAME}/privkey.pem#g" \ ${P_DIR}/nginx_${c}_configuration.sls done else @@ -587,7 +631,7 @@ if [ -z "${ROLES}" ]; then echo "extra_custom_certs_dir: /srv/salt/certs" > ${P_DIR}/extra_custom_certs.sls echo "extra_custom_certs:" >> ${P_DIR}/extra_custom_certs.sls - for c in controller websocket workbench workbench2 webshell keepweb keepproxy; do + for c in controller websocket workbench workbench2 webshell keepweb keepproxy shell; do # Are we in a single-host-single-hostname env? if [ "${USE_SINGLE_HOSTNAME}" = "yes" ]; then # Are we in a single-host-single-hostname env? @@ -634,13 +678,13 @@ else ;; "api") # States - # FIXME: https://dev.arvados.org/issues/17352 - grep -q "postgres.client" ${S_DIR}/top.sls || echo " - postgres.client" >> ${S_DIR}/top.sls + grep -q " - logrotate" ${S_DIR}/top.sls || echo " - logrotate" >> ${S_DIR}/top.sls if grep -q " - nginx.*$" ${S_DIR}/top.sls; then sed -i s/"^ - nginx.*$"/" - nginx.passenger"/g ${S_DIR}/top.sls else echo " - nginx.passenger" >> ${S_DIR}/top.sls fi + echo " - extra.passenger_rvm" >> ${S_DIR}/top.sls ### If we don't install and run LE before arvados-api-server, it fails and breaks everything ### after it. So we add this here as we are, after all, sharing the host for api and controller if [ "${SSL_MODE}" = "lets-encrypt" ]; then @@ -657,6 +701,7 @@ else fi grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls # Pillars + grep -q "logrotate_api" ${P_DIR}/top.sls || echo " - logrotate_api" >> ${P_DIR}/top.sls grep -q "aws_credentials" ${P_DIR}/top.sls || echo " - aws_credentials" >> ${P_DIR}/top.sls grep -q "postgresql" ${P_DIR}/top.sls || echo " - postgresql" >> ${P_DIR}/top.sls grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls @@ -669,6 +714,7 @@ else "controller" | "websocket" | "workbench" | "workbench2" | "webshell" | "keepweb" | "keepproxy") # States if [ "${R}" = "workbench" ]; then + grep -q " - logrotate" ${S_DIR}/top.sls || echo " - logrotate" >> ${S_DIR}/top.sls NGINX_INSTALL_SOURCE="install_from_phusionpassenger" if grep -q " - nginx$" ${S_DIR}/top.sls; then sed -i s/"^ - nginx.*$"/" - nginx.passenger"/g ${S_DIR}/top.sls @@ -701,6 +747,9 @@ else grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls fi # Pillars + if [ "${R}" = "workbench" ]; then + grep -q "logrotate_wb1" ${P_DIR}/top.sls || echo " - logrotate_wb1" >> ${P_DIR}/top.sls + fi grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo " - nginx_${R}_configuration" >> ${P_DIR}/top.sls # Special case for keepweb