Merge branch '17535-test-provision-jenkins'
[arvados.git] / tools / salt-install / provision.sh
1 #!/bin/bash
2
3 # Copyright (C) The Arvados Authors. All rights reserved.
4 #
5 # SPDX-License-Identifier: CC-BY-SA-3.0
6
7 # If you want to test arvados in a single host, you can run this script, which
8 # will install it using salt masterless
9 # This script is run by the Vagrant file when you run it with
10 #
11 # vagrant up
12
13 set -o pipefail
14 set -x
15
16 # capture the directory that the script is running from
17 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
18
19 usage() {
20   echo >&2
21   echo >&2 "Usage: ${0} [-h] [-h]"
22   echo >&2
23   echo >&2 "${0} options:"
24   echo >&2 "  -d, --debug                                 Run salt installation in debug mode"
25   echo >&2 "  -c <local.params>, --config <local.params>  Path to the local.params config file"
26   echo >&2 "  -t, --test                                  Test installation running a CWL workflow"
27   echo >&2 "  -r, --roles                                 List of Arvados roles to apply to the host, comma separated"
28   echo >&2 "                                              Possible values are:"
29   echo >&2 "                                                api"
30   echo >&2 "                                                controller"
31   echo >&2 "                                                dispatcher"
32   echo >&2 "                                                keepproxy"
33   echo >&2 "                                                keepstore"
34   echo >&2 "                                                keepweb"
35   echo >&2 "                                                shell"
36   echo >&2 "                                                webshell"
37   echo >&2 "                                                websocket"
38   echo >&2 "                                                workbench"
39   echo >&2 "                                                workbench2"
40   echo >&2 "                                              Defaults to applying them all"
41   echo >&2 "  -h, --help                                  Display this help and exit"
42   echo >&2 "  --dump-config <dest_dir>                    Dumps the pillars and states to a directory"
43   echo >&2 "                                              This parameter does not perform any installation at all. It's"
44   echo >&2 "                                              intended to give you a parsed sot of configuration files so"
45   echo >&2 "                                              you can inspect them or use them in you Saltstack infrastructure."
46   echo >&2 "                                              It"
47   echo >&2 "                                                - parses the pillar and states templates,"
48   echo >&2 "                                                - downloads the helper formulas with their desired versions,"
49   echo >&2 "                                                - prepares the 'top.sls' files both for pillars and states"
50   echo >&2 "                                                  for the selected role/s"
51   echo >&2 "                                                - writes the resulting files into <dest_dir>"
52   echo >&2 "  -v, --vagrant                               Run in vagrant and use the /vagrant shared dir"
53   echo >&2
54 }
55
56 arguments() {
57   # NOTE: This requires GNU getopt (part of the util-linux package on Debian-based distros).
58   if ! which getopt > /dev/null; then
59     echo >&2 "GNU getopt is required to run this script. Please install it and re-reun it"
60     exit 1
61   fi
62
63   TEMP=$(getopt -o c:dhp:r:tv \
64     --long config:,debug,dump-config:,help,roles:,test,vagrant \
65     -n "${0}" -- "${@}")
66
67   if [ ${?} != 0 ];
68     then echo "Please check the parameters you entered and re-run again"
69     exit 1
70   fi
71   # Note the quotes around `$TEMP': they are essential!
72   eval set -- "$TEMP"
73
74   while [ ${#} -ge 1 ]; do
75     case ${1} in
76       -c | --config)
77         CONFIG_FILE=${2}
78         shift 2
79         ;;
80       -d | --debug)
81         LOG_LEVEL="debug"
82         shift
83         set -x
84         ;;
85       --dump-config)
86         if [[ ${2} = /* ]]; then
87           DUMP_SALT_CONFIG_DIR=${2}
88         else
89           DUMP_SALT_CONFIG_DIR=${PWD}/${2}
90         fi
91         ## states
92         S_DIR="${DUMP_SALT_CONFIG_DIR}/salt"
93         ## formulas
94         F_DIR="${DUMP_SALT_CONFIG_DIR}/formulas"
95         ## pillars
96         P_DIR="${DUMP_SALT_CONFIG_DIR}/pillars"
97         ## tests
98         T_DIR="${DUMP_SALT_CONFIG_DIR}/tests"
99         DUMP_CONFIG="yes"
100         shift 2
101         ;;
102       -r | --roles)
103         for i in ${2//,/ }
104           do
105             # Verify the role exists
106             if [[ ! "database,api,controller,keepstore,websocket,keepweb,workbench2,webshell,keepproxy,shell,workbench,dispatcher" == *"$i"* ]]; then
107               echo "The role '${i}' is not a valid role"
108               usage
109               exit 1
110             fi
111             ROLES="${ROLES} ${i}"
112           done
113           shift 2
114         ;;
115       -t | --test)
116         TEST="yes"
117         shift
118         ;;
119       -v | --vagrant)
120         VAGRANT="yes"
121         shift
122         ;;
123       --)
124         shift
125         break
126         ;;
127       *)
128         usage
129         exit 1
130         ;;
131     esac
132   done
133 }
134
135 CONFIG_FILE="${SCRIPT_DIR}/local.params"
136 CONFIG_DIR="local_config_dir"
137 DUMP_CONFIG="no"
138 LOG_LEVEL="info"
139 CONTROLLER_EXT_SSL_PORT=443
140 TESTS_DIR="tests"
141
142 CLUSTER=""
143 DOMAIN=""
144
145 # Hostnames/IPs used for single-host deploys
146 HOSTNAME_EXT=""
147 HOSTNAME_INT="127.0.1.1"
148
149 # Initial user setup
150 INITIAL_USER=""
151 INITIAL_USER_EMAIL=""
152 INITIAL_USER_PASSWORD=""
153
154 CONTROLLER_EXT_SSL_PORT=8000
155 KEEP_EXT_SSL_PORT=25101
156 # Both for collections and downloads
157 KEEPWEB_EXT_SSL_PORT=9002
158 WEBSHELL_EXT_SSL_PORT=4202
159 WEBSOCKET_EXT_SSL_PORT=8002
160 WORKBENCH1_EXT_SSL_PORT=443
161 WORKBENCH2_EXT_SSL_PORT=3001
162
163 ## These are ARVADOS-related parameters
164 # For a stable release, change RELEASE "production" and VERSION to the
165 # package version (including the iteration, e.g. X.Y.Z-1) of the
166 # release.
167 # The "local.params.example.*" files already set "RELEASE=production"
168 # to deploy  production-ready packages
169 RELEASE="development"
170 VERSION="latest"
171
172 # These are arvados-formula-related parameters
173 # An arvados-formula tag. For a stable release, this should be a
174 # branch name (e.g. X.Y-dev) or tag for the release.
175 # ARVADOS_TAG="2.2.0"
176 # BRANCH="main"
177
178 # Other formula versions we depend on
179 POSTGRES_TAG="v0.41.6"
180 NGINX_TAG="temp-fix-missing-statements-in-pillar"
181 DOCKER_TAG="v2.0.7"
182 LOCALE_TAG="v0.3.4"
183 LETSENCRYPT_TAG="v2.1.0"
184
185 # Salt's dir
186 DUMP_SALT_CONFIG_DIR=""
187 ## states
188 S_DIR="/srv/salt"
189 ## formulas
190 F_DIR="/srv/formulas"
191 ## pillars
192 P_DIR="/srv/pillars"
193 ## tests
194 T_DIR="/tmp/cluster_tests"
195
196 arguments ${@}
197
198 if [ -s ${CONFIG_FILE} ]; then
199   source ${CONFIG_FILE}
200 else
201   echo >&2 "You don't seem to have a config file with initial values."
202   echo >&2 "Please create a '${CONFIG_FILE}' file as described in"
203   echo >&2 "  * https://doc.arvados.org/install/salt-single-host.html#single_host, or"
204   echo >&2 "  * https://doc.arvados.org/install/salt-multi-host.html#multi_host_multi_hostnames"
205   exit 1
206 fi
207
208 if [ ! -d ${CONFIG_DIR} ]; then
209   echo >&2 "You don't seem to have a config directory with pillars and states."
210   echo >&2 "Please create a '${CONFIG_DIR}' directory (as configured in your '${CONFIG_FILE}'). Please see"
211   echo >&2 "  * https://doc.arvados.org/install/salt-single-host.html#single_host, or"
212   echo >&2 "  * https://doc.arvados.org/install/salt-multi-host.html#multi_host_multi_hostnames"
213   exit 1
214 fi
215
216 if grep -q 'fixme_or_this_wont_work' ${CONFIG_FILE} ; then
217   echo >&2 "The config file ${CONFIG_FILE} has some parameters that need to be modified."
218   echo >&2 "Please, fix them and re-run the provision script."
219   exit 1
220 fi
221
222 if ! grep -qE '^[[:alnum:]]{5}$' <<<${CLUSTER} ; then
223   echo >&2 "ERROR: <CLUSTER> must be exactly 5 alphanumeric characters long"
224   echo >&2 "Fix the cluster name in the 'local.params' file and re-run the provision script"
225   exit 1
226 fi
227
228 # Only used in single_host/single_name deploys
229 if [ "x${HOSTNAME_EXT}" = "x" ] ; then
230   HOSTNAME_EXT="${CLUSTER}.${DOMAIN}"
231 fi
232
233 if [ "${DUMP_CONFIG}" = "yes" ]; then
234   echo "The provision installer will just dump a config under ${DUMP_SALT_CONFIG_DIR} and exit"
235 else
236   # Install a few dependency packages
237   # First, let's figure out the OS we're working on
238   OS_ID=$(grep ^ID= /etc/os-release |cut -f 2 -d=  |cut -f 2 -d \")
239   echo "Detected distro: ${OS_ID}"
240
241   case ${OS_ID} in
242     "centos")
243       echo "WARNING! Disabling SELinux, see https://dev.arvados.org/issues/18019"
244       sed -i 's/SELINUX=enforcing/SELINUX=permissive' /etc/sysconfig/selinux
245       setenforce permissive
246       yum install -y  curl git jq
247       ;;
248     "debian"|"ubuntu")
249       DEBIAN_FRONTEND=noninteractive apt update
250       DEBIAN_FRONTEND=noninteractive apt install -y curl git jq
251       ;;
252   esac
253
254   if which salt-call; then
255     echo "Salt already installed"
256   else
257     curl -L https://bootstrap.saltstack.com -o /tmp/bootstrap_salt.sh
258     sh /tmp/bootstrap_salt.sh -XdfP -x python3
259     /bin/systemctl stop salt-minion.service
260     /bin/systemctl disable salt-minion.service
261   fi
262
263   # Set salt to masterless mode
264   cat > /etc/salt/minion << EOFSM
265 failhard: "True"
266
267 file_client: local
268 file_roots:
269   base:
270     - ${S_DIR}
271     - ${F_DIR}/*
272
273 pillar_roots:
274   base:
275     - ${P_DIR}
276 EOFSM
277 fi
278
279 mkdir -p ${S_DIR} ${F_DIR} ${P_DIR} ${T_DIR}
280
281 # Get the formula and dependencies
282 cd ${F_DIR} || exit 1
283 echo "Cloning formulas"
284 rm -rf ${F_DIR}/* || exit 1
285 git clone --quiet https://github.com/saltstack-formulas/docker-formula.git ${F_DIR}/docker
286 ( cd docker && git checkout --quiet tags/"${DOCKER_TAG}" -b "${DOCKER_TAG}" )
287
288 git clone --quiet https://github.com/saltstack-formulas/locale-formula.git ${F_DIR}/locale
289 ( cd locale && git checkout --quiet tags/"${LOCALE_TAG}" -b "${LOCALE_TAG}" )
290
291 git clone --quiet https://github.com/netmanagers/nginx-formula.git ${F_DIR}/nginx
292 ( cd nginx && git checkout --quiet tags/"${NGINX_TAG}" -b "${NGINX_TAG}" )
293
294 git clone --quiet https://github.com/saltstack-formulas/postgres-formula.git ${F_DIR}/postgres
295 ( cd postgres && git checkout --quiet tags/"${POSTGRES_TAG}" -b "${POSTGRES_TAG}" )
296
297 git clone --quiet https://github.com/saltstack-formulas/letsencrypt-formula.git ${F_DIR}/letsencrypt
298 ( cd letsencrypt && git checkout --quiet tags/"${LETSENCRYPT_TAG}" -b "${LETSENCRYPT_TAG}" )
299
300 git clone --quiet https://git.arvados.org/arvados-formula.git ${F_DIR}/arvados
301
302 # If we want to try a specific branch of the formula
303 if [ "x${BRANCH}" != "x" ]; then
304   ( cd ${F_DIR}/arvados && git checkout --quiet -t origin/"${BRANCH}" -b "${BRANCH}" )
305 elif [ "x${ARVADOS_TAG}" != "x" ]; then
306 ( cd ${F_DIR}/arvados && git checkout --quiet tags/"${ARVADOS_TAG}" -b "${ARVADOS_TAG}" )
307 fi
308
309 if [ "x${VAGRANT}" = "xyes" ]; then
310   EXTRA_STATES_DIR="/home/vagrant/${CONFIG_DIR}/states"
311   SOURCE_PILLARS_DIR="/home/vagrant/${CONFIG_DIR}/pillars"
312   SOURCE_TESTS_DIR="/home/vagrant/${TESTS_DIR}"
313 else
314   EXTRA_STATES_DIR="${SCRIPT_DIR}/${CONFIG_DIR}/states"
315   SOURCE_PILLARS_DIR="${SCRIPT_DIR}/${CONFIG_DIR}/pillars"
316   SOURCE_TESTS_DIR="${SCRIPT_DIR}/${TESTS_DIR}"
317 fi
318
319 SOURCE_STATES_DIR="${EXTRA_STATES_DIR}"
320
321 echo "Writing pillars and states"
322
323 # Replace variables (cluster,  domain, etc) in the pillars, states and tests
324 # to ease deployment for newcomers
325 if [ ! -d "${SOURCE_PILLARS_DIR}" ]; then
326   echo "${SOURCE_PILLARS_DIR} does not exist or is not a directory. Exiting."
327   exit 1
328 fi
329 for f in $(ls "${SOURCE_PILLARS_DIR}"/*); do
330   sed "s#__ANONYMOUS_USER_TOKEN__#${ANONYMOUS_USER_TOKEN}#g;
331        s#__BLOB_SIGNING_KEY__#${BLOB_SIGNING_KEY}#g;
332        s#__CONTROLLER_EXT_SSL_PORT__#${CONTROLLER_EXT_SSL_PORT}#g;
333        s#__CLUSTER__#${CLUSTER}#g;
334        s#__DOMAIN__#${DOMAIN}#g;
335        s#__HOSTNAME_EXT__#${HOSTNAME_EXT}#g;
336        s#__HOSTNAME_INT__#${HOSTNAME_INT}#g;
337        s#__INITIAL_USER_EMAIL__#${INITIAL_USER_EMAIL}#g;
338        s#__INITIAL_USER_PASSWORD__#${INITIAL_USER_PASSWORD}#g;
339        s#__INITIAL_USER__#${INITIAL_USER}#g;
340        s#__LE_AWS_REGION__#${LE_AWS_REGION}#g;
341        s#__LE_AWS_SECRET_ACCESS_KEY__#${LE_AWS_SECRET_ACCESS_KEY}#g;
342        s#__LE_AWS_ACCESS_KEY_ID__#${LE_AWS_ACCESS_KEY_ID}#g;
343        s#__DATABASE_PASSWORD__#${DATABASE_PASSWORD}#g;
344        s#__KEEPWEB_EXT_SSL_PORT__#${KEEPWEB_EXT_SSL_PORT}#g;
345        s#__KEEP_EXT_SSL_PORT__#${KEEP_EXT_SSL_PORT}#g;
346        s#__MANAGEMENT_TOKEN__#${MANAGEMENT_TOKEN}#g;
347        s#__RELEASE__#${RELEASE}#g;
348        s#__SYSTEM_ROOT_TOKEN__#${SYSTEM_ROOT_TOKEN}#g;
349        s#__VERSION__#${VERSION}#g;
350        s#__WEBSHELL_EXT_SSL_PORT__#${WEBSHELL_EXT_SSL_PORT}#g;
351        s#__WEBSOCKET_EXT_SSL_PORT__#${WEBSOCKET_EXT_SSL_PORT}#g;
352        s#__WORKBENCH1_EXT_SSL_PORT__#${WORKBENCH1_EXT_SSL_PORT}#g;
353        s#__WORKBENCH2_EXT_SSL_PORT__#${WORKBENCH2_EXT_SSL_PORT}#g;
354        s#__CLUSTER_INT_CIDR__#${CLUSTER_INT_CIDR}#g;
355        s#__CONTROLLER_INT_IP__#${CONTROLLER_INT_IP}#g;
356        s#__WEBSOCKET_INT_IP__#${WEBSOCKET_INT_IP}#g;
357        s#__KEEP_INT_IP__#${KEEP_INT_IP}#g;
358        s#__KEEPSTORE0_INT_IP__#${KEEPSTORE0_INT_IP}#g;
359        s#__KEEPSTORE1_INT_IP__#${KEEPSTORE1_INT_IP}#g;
360        s#__KEEPWEB_INT_IP__#${KEEPWEB_INT_IP}#g;
361        s#__WEBSHELL_INT_IP__#${WEBSHELL_INT_IP}#g;
362        s#__SHELL_INT_IP__#${SHELL_INT_IP}#g;
363        s#__WORKBENCH1_INT_IP__#${WORKBENCH1_INT_IP}#g;
364        s#__WORKBENCH2_INT_IP__#${WORKBENCH2_INT_IP}#g;
365        s#__DATABASE_INT_IP__#${DATABASE_INT_IP}#g;
366        s#__WORKBENCH_SECRET_KEY__#${WORKBENCH_SECRET_KEY}#g" \
367   "${f}" > "${P_DIR}"/$(basename "${f}")
368 done
369
370 if [ "x${TEST}" = "xyes" ] && [ ! -d "${SOURCE_TESTS_DIR}" ]; then
371   echo "You requested to run tests, but ${SOURCE_TESTS_DIR} does not exist or is not a directory. Exiting."
372   exit 1
373 fi
374 mkdir -p ${T_DIR}
375 # Replace cluster and domain name in the test files
376 for f in $(ls "${SOURCE_TESTS_DIR}"/*); do
377   sed "s#__CLUSTER__#${CLUSTER}#g;
378        s#__CONTROLLER_EXT_SSL_PORT__#${CONTROLLER_EXT_SSL_PORT}#g;
379        s#__DOMAIN__#${DOMAIN}#g;
380        s#__HOSTNAME_INT__#${HOSTNAME_INT}#g;
381        s#__INITIAL_USER_EMAIL__#${INITIAL_USER_EMAIL}#g;
382        s#__INITIAL_USER_PASSWORD__#${INITIAL_USER_PASSWORD}#g
383        s#__INITIAL_USER__#${INITIAL_USER}#g;
384        s#__DATABASE_PASSWORD__#${DATABASE_PASSWORD}#g;
385        s#__SYSTEM_ROOT_TOKEN__#${SYSTEM_ROOT_TOKEN}#g" \
386   "${f}" > ${T_DIR}/$(basename "${f}")
387 done
388 chmod 755 ${T_DIR}/run-test.sh
389
390 # Replace helper state files that differ from the formula's examples
391 if [ -d "${SOURCE_STATES_DIR}" ]; then
392   mkdir -p "${F_DIR}"/extra/extra
393
394   for f in $(ls "${SOURCE_STATES_DIR}"/*); do
395     sed "s#__ANONYMOUS_USER_TOKEN__#${ANONYMOUS_USER_TOKEN}#g;
396          s#__CLUSTER__#${CLUSTER}#g;
397          s#__BLOB_SIGNING_KEY__#${BLOB_SIGNING_KEY}#g;
398          s#__CONTROLLER_EXT_SSL_PORT__#${CONTROLLER_EXT_SSL_PORT}#g;
399          s#__DOMAIN__#${DOMAIN}#g;
400          s#__HOSTNAME_EXT__#${HOSTNAME_EXT}#g;
401          s#__HOSTNAME_INT__#${HOSTNAME_INT}#g;
402          s#__INITIAL_USER_EMAIL__#${INITIAL_USER_EMAIL}#g;
403          s#__INITIAL_USER_PASSWORD__#${INITIAL_USER_PASSWORD}#g;
404          s#__INITIAL_USER__#${INITIAL_USER}#g;
405          s#__DATABASE_PASSWORD__#${DATABASE_PASSWORD}#g;
406          s#__KEEPWEB_EXT_SSL_PORT__#${KEEPWEB_EXT_SSL_PORT}#g;
407          s#__KEEP_EXT_SSL_PORT__#${KEEP_EXT_SSL_PORT}#g;
408          s#__MANAGEMENT_TOKEN__#${MANAGEMENT_TOKEN}#g;
409          s#__RELEASE__#${RELEASE}#g;
410          s#__SYSTEM_ROOT_TOKEN__#${SYSTEM_ROOT_TOKEN}#g;
411          s#__VERSION__#${VERSION}#g;
412          s#__CLUSTER_INT_CIDR__#${CLUSTER_INT_CIDR}#g;
413          s#__CONTROLLER_INT_IP__#${CONTROLLER_INT_IP}#g;
414          s#__WEBSOCKET_INT_IP__#${WEBSOCKET_INT_IP}#g;
415          s#__KEEP_INT_IP__#${KEEP_INT_IP}#g;
416          s#__KEEPSTORE0_INT_IP__#${KEEPSTORE0_INT_IP}#g;
417          s#__KEEPSTORE1_INT_IP__#${KEEPSTORE1_INT_IP}#g;
418          s#__KEEPWEB_INT_IP__#${KEEPWEB_INT_IP}#g;
419          s#__WEBSHELL_INT_IP__#${WEBSHELL_INT_IP}#g;
420          s#__WORKBENCH1_INT_IP__#${WORKBENCH1_INT_IP}#g;
421          s#__WORKBENCH2_INT_IP__#${WORKBENCH2_INT_IP}#g;
422          s#__DATABASE_INT_IP__#${DATABASE_INT_IP}#g;
423          s#__WEBSHELL_EXT_SSL_PORT__#${WEBSHELL_EXT_SSL_PORT}#g;
424          s#__WEBSOCKET_EXT_SSL_PORT__#${WEBSOCKET_EXT_SSL_PORT}#g;
425          s#__WORKBENCH1_EXT_SSL_PORT__#${WORKBENCH1_EXT_SSL_PORT}#g;
426          s#__WORKBENCH2_EXT_SSL_PORT__#${WORKBENCH2_EXT_SSL_PORT}#g;
427          s#__WORKBENCH_SECRET_KEY__#${WORKBENCH_SECRET_KEY}#g" \
428     "${f}" > "${F_DIR}/extra/extra"/$(basename "${f}")
429   done
430 fi
431
432 # Now, we build the SALT states/pillars trees
433 # As we need to separate both states and pillars in case we want specific
434 # roles, we iterate on both at the same time
435
436 # States
437 cat > ${S_DIR}/top.sls << EOFTSLS
438 base:
439   '*':
440     - locale
441 EOFTSLS
442
443 # Pillars
444 cat > ${P_DIR}/top.sls << EOFPSLS
445 base:
446   '*':
447     - locale
448     - arvados
449 EOFPSLS
450
451 # States, extra states
452 if [ -d "${F_DIR}"/extra/extra ]; then
453   for f in $(ls "${F_DIR}"/extra/extra/*.sls); do
454   echo "    - extra.$(basename ${f} | sed 's/.sls$//g')" >> ${S_DIR}/top.sls
455   done
456 fi
457
458 # If we want specific roles for a node, just add the desired states
459 # and its dependencies
460 if [ -z "${ROLES}" ]; then
461   # States
462   echo "    - nginx.passenger" >> ${S_DIR}/top.sls
463   # Currently, only available on config_examples/multi_host/aws
464   if [ "x${USE_LETSENCRYPT}" = "xyes" ]; then
465     if [ "x${USE_LETSENCRYPT_IAM_USER}" = "xyes" ]; then
466       grep -q "aws_credentials" ${S_DIR}/top.sls || echo "    - aws_credentials" >> ${S_DIR}/top.sls
467     fi
468     grep -q "letsencrypt"     ${S_DIR}/top.sls || echo "    - letsencrypt" >> ${S_DIR}/top.sls
469   fi
470   echo "    - postgres" >> ${S_DIR}/top.sls
471   echo "    - docker.software" >> ${S_DIR}/top.sls
472   echo "    - arvados" >> ${S_DIR}/top.sls
473
474   # Pillars
475   echo "    - docker" >> ${P_DIR}/top.sls
476   echo "    - nginx_api_configuration" >> ${P_DIR}/top.sls
477   echo "    - nginx_controller_configuration" >> ${P_DIR}/top.sls
478   echo "    - nginx_keepproxy_configuration" >> ${P_DIR}/top.sls
479   echo "    - nginx_keepweb_configuration" >> ${P_DIR}/top.sls
480   echo "    - nginx_passenger" >> ${P_DIR}/top.sls
481   echo "    - nginx_websocket_configuration" >> ${P_DIR}/top.sls
482   echo "    - nginx_webshell_configuration" >> ${P_DIR}/top.sls
483   echo "    - nginx_workbench2_configuration" >> ${P_DIR}/top.sls
484   echo "    - nginx_workbench_configuration" >> ${P_DIR}/top.sls
485   echo "    - postgresql" >> ${P_DIR}/top.sls
486   # Currently, only available on config_examples/multi_host/aws
487   if [ "x${USE_LETSENCRYPT}" = "xyes" ]; then
488     if [ "x${USE_LETSENCRYPT_IAM_USER}" = "xyes" ]; then
489       grep -q "aws_credentials" ${P_DIR}/top.sls || echo "    - aws_credentials" >> ${P_DIR}/top.sls
490     fi
491     grep -q "letsencrypt"     ${P_DIR}/top.sls || echo "    - letsencrypt" >> ${P_DIR}/top.sls
492   fi
493 else
494   # If we add individual roles, make sure we add the repo first
495   echo "    - arvados.repo" >> ${S_DIR}/top.sls
496   for R in ${ROLES}; do
497     case "${R}" in
498       "database")
499         # States
500         echo "    - postgres" >> ${S_DIR}/top.sls
501         # Pillars
502         echo '    - postgresql' >> ${P_DIR}/top.sls
503       ;;
504       "api")
505         # States
506         # FIXME: https://dev.arvados.org/issues/17352
507         grep -q "postgres.client" ${S_DIR}/top.sls || echo "    - postgres.client" >> ${S_DIR}/top.sls
508         grep -q "nginx.passenger" ${S_DIR}/top.sls || echo "    - nginx.passenger" >> ${S_DIR}/top.sls
509         ### If we don't install and run LE before arvados-api-server, it fails and breaks everything
510         ### after it so we add this here, as we are, after all, sharing the host for api and controller
511         # Currently, only available on config_examples/multi_host/aws
512         if [ "x${USE_LETSENCRYPT}" = "xyes" ]; then
513           if [ "x${USE_LETSENCRYPT_IAM_USER}" = "xyes" ]; then
514             grep -q "aws_credentials" ${S_DIR}/top.sls || echo "    - aws_credentials" >> ${S_DIR}/top.sls
515           fi
516           grep -q "letsencrypt"     ${S_DIR}/top.sls || echo "    - letsencrypt" >> ${S_DIR}/top.sls
517         fi
518         grep -q "arvados.${R}" ${S_DIR}/top.sls    || echo "    - arvados.${R}" >> ${S_DIR}/top.sls
519         # Pillars
520         grep -q "aws_credentials" ${P_DIR}/top.sls          || echo "    - aws_credentials" >> ${P_DIR}/top.sls
521         grep -q "docker" ${P_DIR}/top.sls                   || echo "    - docker" >> ${P_DIR}/top.sls
522         grep -q "postgresql" ${P_DIR}/top.sls               || echo "    - postgresql" >> ${P_DIR}/top.sls
523         grep -q "nginx_passenger" ${P_DIR}/top.sls          || echo "    - nginx_passenger" >> ${P_DIR}/top.sls
524         grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo "    - nginx_${R}_configuration" >> ${P_DIR}/top.sls
525       ;;
526       "controller" | "websocket" | "workbench" | "workbench2" | "webshell" | "keepweb" | "keepproxy")
527         # States
528         grep -q "nginx.passenger" ${S_DIR}/top.sls || echo "    - nginx.passenger" >> ${S_DIR}/top.sls
529         # Currently, only available on config_examples/multi_host/aws
530         if [ "x${USE_LETSENCRYPT}" = "xyes" ]; then
531           if [ "x${USE_LETSENCRYPT_IAM_USER}" = "xyes" ]; then
532             grep -q "aws_credentials" ${S_DIR}/top.sls || echo "    - aws_credentials" >> ${S_DIR}/top.sls
533           fi
534           grep -q "letsencrypt"     ${S_DIR}/top.sls || echo "    - letsencrypt" >> ${S_DIR}/top.sls
535         fi
536         # webshell role is just a nginx vhost, so it has no state
537         if [ "${R}" != "webshell" ]; then
538           grep -q "arvados.${R}" ${S_DIR}/top.sls    || echo "    - arvados.${R}" >> ${S_DIR}/top.sls
539         fi
540         # Pillars
541         grep -q "nginx_passenger" ${P_DIR}/top.sls          || echo "    - nginx_passenger" >> ${P_DIR}/top.sls
542         grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo "    - nginx_${R}_configuration" >> ${P_DIR}/top.sls
543         # Currently, only available on config_examples/multi_host/aws
544         if [ "x${USE_LETSENCRYPT}" = "xyes" ]; then
545           if [ "x${USE_LETSENCRYPT_IAM_USER}" = "xyes" ]; then
546             grep -q "aws_credentials" ${P_DIR}/top.sls || echo "    - aws_credentials" >> ${P_DIR}/top.sls
547           fi
548           grep -q "letsencrypt"     ${P_DIR}/top.sls || echo "    - letsencrypt" >> ${P_DIR}/top.sls
549           grep -q "letsencrypt_${R}_configuration" ${P_DIR}/top.sls || echo "    - letsencrypt_${R}_configuration" >> ${P_DIR}/top.sls
550         fi
551       ;;
552       "shell")
553         # States
554         grep -q "docker" ${S_DIR}/top.sls       || echo "    - docker.software" >> ${S_DIR}/top.sls
555         grep -q "arvados.${R}" ${S_DIR}/top.sls || echo "    - arvados.${R}" >> ${S_DIR}/top.sls
556         # Pillars
557         grep -q "" ${P_DIR}/top.sls                             || echo "    - docker" >> ${P_DIR}/top.sls
558       ;;
559       "dispatcher")
560         # States
561         grep -q "docker" ${S_DIR}/top.sls       || echo "    - docker.software" >> ${S_DIR}/top.sls
562         grep -q "arvados.${R}" ${S_DIR}/top.sls || echo "    - arvados.${R}" >> ${S_DIR}/top.sls
563         # Pillars
564         # ATM, no specific pillar needed
565       ;;
566       "keepstore")
567         # States
568         grep -q "arvados.${R}" ${S_DIR}/top.sls || echo "    - arvados.${R}" >> ${S_DIR}/top.sls
569         # Pillars
570         # ATM, no specific pillar needed
571       ;;
572       *)
573         echo "Unknown role ${R}"
574         exit 1
575       ;;
576     esac
577   done
578 fi
579
580 if [ "${DUMP_CONFIG}" = "yes" ]; then
581   # We won't run the rest of the script because we're just dumping the config
582   exit 0
583 fi
584
585 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
586 if [ -e /root/.psqlrc ]; then
587   if ! ( grep 'pset pager off' /root/.psqlrc ); then
588     RESTORE_PSQL="yes"
589     cp /root/.psqlrc /root/.psqlrc.provision.backup
590   fi
591 else
592   DELETE_PSQL="yes"
593 fi
594
595 echo '\pset pager off' >> /root/.psqlrc
596 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
597
598 # Now run the install
599 salt-call --local state.apply -l ${LOG_LEVEL}
600
601 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
602 if [ "x${DELETE_PSQL}" = "xyes" ]; then
603   echo "Removing .psql file"
604   rm /root/.psqlrc
605 fi
606
607 if [ "x${RESTORE_PSQL}" = "xyes" ]; then
608   echo "Restoring .psql file"
609   mv -v /root/.psqlrc.provision.backup /root/.psqlrc
610 fi
611 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
612
613 # Leave a copy of the Arvados CA so the user can copy it where it's required
614 echo "Copying the Arvados CA certificate to the installer dir, so you can import it"
615 # If running in a vagrant VM, also add default user to docker group
616 if [ "x${VAGRANT}" = "xyes" ]; then
617   cp /etc/ssl/certs/arvados-snakeoil-ca.pem /vagrant/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
618
619   echo "Adding the vagrant user to the docker group"
620   usermod -a -G docker vagrant
621 else
622   cp /etc/ssl/certs/arvados-snakeoil-ca.pem ${SCRIPT_DIR}/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
623 fi
624
625 # Test that the installation finished correctly
626 if [ "x${TEST}" = "xyes" ]; then
627   cd ${T_DIR}
628   # If we use RVM, we need to run this with it, or most ruby commands will fail
629   RVM_EXEC=""
630   if [ -x /usr/local/rvm/bin/rvm-exec ]; then
631     RVM_EXEC="/usr/local/rvm/bin/rvm-exec"
632   fi
633   ${RVM_EXEC} ./run-test.sh
634 fi