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