3 # Copyright (C) The Arvados Authors. All rights reserved.
5 # SPDX-License-Identifier: CC-BY-SA-3.0
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
15 # capture the directory that the script is running from
16 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
20 echo >&2 "Usage: ${0} [-h] [-h]"
22 echo >&2 "${0} options:"
23 echo >&2 " -d, --debug Run salt installation in debug mode"
24 echo >&2 " -p <N>, --ssl-port <N> SSL port to use for the web applications"
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:"
30 echo >&2 " controller"
34 echo >&2 " workbench2"
38 echo >&2 " dispatcher"
39 echo >&2 " Defaults to applying them all"
40 echo >&2 " -h, --help Display this help and exit"
41 echo >&2 " -v, --vagrant Run in vagrant and use the /vagrant shared dir"
46 # NOTE: This requires GNU getopt (part of the util-linux package on Debian-based distros).
47 TEMP=$(getopt -o c:dhp:r:tv \
48 --long config:,debug,help,ssl-port:,roles:,test,vagrant \
51 if [ ${?} != 0 ] ; then echo "GNU getopt missing? Use -h for help"; exit 1 ; fi
52 # Note the quotes around `$TEMP': they are essential!
55 while [ ${#} -ge 1 ]; do
66 CONTROLLER_EXT_SSL_PORT=${2}
72 # Verify the role exists
73 if [[ ! "database,api,controller,keepstore,websocket,keepweb,workbench2,keepproxy,shell,workbench,dispatcher" == *"$i"* ]]; then
74 echo "The role '${i}' is not a valid role"
102 CONFIG="${SCRIPT_DIR}/local.params"
103 CONFIG_DIR="config_examples/single_host/multiple_hostnames"
105 CONTROLLER_EXT_SSL_PORT=443
111 # Hostnames/IPs used for single-host deploys
113 HOSTNAME_INT="127.0.1.1"
117 INITIAL_USER_EMAIL=""
118 INITIAL_USER_PASSWORD=""
120 CONTROLLER_EXT_SSL_PORT=8000
121 KEEP_EXT_SSL_PORT=25101
122 # Both for collections and downloads
123 KEEPWEB_EXT_SSL_PORT=9002
124 WEBSHELL_EXT_SSL_PORT=4202
125 WEBSOCKET_EXT_SSL_PORT=8002
126 WORKBENCH1_EXT_SSL_PORT=443
127 WORKBENCH2_EXT_SSL_PORT=3001
132 POSTGRES_TAG="v0.41.3"
141 F_DIR="/srv/formulas"
147 if [ -s ${CONFIG_FILE} ]; then
148 source ${CONFIG_FILE}
150 echo >&2 "Please create a '${CONFIG_FILE}' file with initial values, as described in FIXME_URL_TO_DESCR"
154 if grep -q 'fixme_or_this_wont_work' ${CONFIG_FILE} ; then
155 echo >&2 "The config file ${CONFIG_FILE} has some parameters that need to be modified."
156 echo >&2 "Please, fix them and re-run the provision script."
160 if ! grep -E '^[[:alnum:]]{5}$' <<<${CLUSTER} ; then
161 echo >&2 "ERROR: <CLUSTER> must be exactly 5 alphanumeric characters long"
162 echo >&2 "Fix the cluster name in the 'local.params' file and re-run the provision script"
167 apt-get install -y curl git jq
169 if which salt-call; then
170 echo "Salt already installed"
172 curl -L https://bootstrap.saltstack.com -o /tmp/bootstrap_salt.sh
173 sh /tmp/bootstrap_salt.sh -XdfP -x python3
174 /bin/systemctl stop salt-minion.service
175 /bin/systemctl disable salt-minion.service
178 # Set salt to masterless mode
179 cat > /etc/salt/minion << EOFSM
191 mkdir -p ${S_DIR} ${F_DIR} ${P_DIR}
193 # Get the formula and dependencies
194 cd ${F_DIR} || exit 1
195 git clone --branch "${ARVADOS_TAG}" https://github.com/arvados/arvados-formula.git
196 git clone --branch "${DOCKER_TAG}" https://github.com/saltstack-formulas/docker-formula.git
197 git clone --branch "${LOCALE_TAG}" https://github.com/saltstack-formulas/locale-formula.git
198 git clone --branch "${NGINX_TAG}" https://github.com/saltstack-formulas/nginx-formula.git
199 git clone --branch "${POSTGRES_TAG}" https://github.com/saltstack-formulas/postgres-formula.git
201 # If we want to try a specific branch of the formula
202 if [ "x${BRANCH}" != "x" ]; then
203 cd ${F_DIR}/arvados-formula || exit 1
204 git checkout -t origin/"${BRANCH}" -b "${BRANCH}"
208 if [ "x${VAGRANT}" = "xyes" ]; then
209 SOURCE_PILLARS_DIR="/vagrant/${CONFIG_DIR}/pillars"
210 SOURCE_TESTS_DIR="/vagrant/${TESTS_DIR}"
212 SOURCE_PILLARS_DIR="${SCRIPT_DIR}/${CONFIG_DIR}/pillars"
213 SOURCE_TESTS_DIR="${SCRIPT_DIR}/${TESTS_DIR}"
216 SOURCE_STATES_DIR="${EXTRA_STATES_DIR}"
218 # Replace variables (cluster, domain, etc) in the pillars, states and tests
219 # to ease deployment for newcomers
220 for f in "${SOURCE_PILLARS_DIR}"/*; do
221 sed "s/__ANONYMOUS_USER_TOKEN__/${ANONYMOUS_USER_TOKEN}/g;
222 s/__BLOB_SIGNING_KEY__/${BLOB_SIGNING_KEY}/g;
223 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
224 s/__CLUSTER__/${CLUSTER}/g;
225 s/__DOMAIN__/${DOMAIN}/g;
226 s/__HOSTNAME_EXT__/${HOSTNAME_EXT}/g;
227 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
228 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
229 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g;
230 s/__INITIAL_USER__/${INITIAL_USER}/g;
231 s/__KEEPWEB_EXT_SSL_PORT__/${KEEPWEB_EXT_SSL_PORT}/g;
232 s/__KEEP_EXT_SSL_PORT__/${KEEP_EXT_SSL_PORT}/g;
233 s/__MANAGEMENT_TOKEN__/${MANAGEMENT_TOKEN}/g;
234 s/__RELEASE__/${RELEASE}/g;
235 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g;
236 s/__VERSION__/${VERSION}/g;
237 s/__WEBSHELL_EXT_SSL_PORT__/${WEBSHELL_EXT_SSL_PORT}/g;
238 s/__WEBSOCKET_EXT_SSL_PORT__/${WEBSOCKET_EXT_SSL_PORT}/g;
239 s/__WORKBENCH1_EXT_SSL_PORT__/${WORKBENCH1_EXT_SSL_PORT}/g;
240 s/__WORKBENCH2_EXT_SSL_PORT__/${WORKBENCH2_EXT_SSL_PORT}/g;
241 s/__WORKBENCH_SECRET_KEY__/${WORKBENCH_SECRET_KEY}/g" \
242 "${f}" > "${P_DIR}"/$(basename "${f}")
245 mkdir -p /tmp/cluster_tests
246 # Replace cluster and domain name in the test files
247 for f in "${SOURCE_TESTS_DIR}"/*; do
248 sed "s/__CLUSTER__/${CLUSTER}/g;
249 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
250 s/__DOMAIN__/${DOMAIN}/g;
251 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
252 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
253 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g
254 s/__INITIAL_USER__/${INITIAL_USER}/g;
255 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g" \
256 "${f}" > "/tmp/cluster_tests"/$(basename "${f}")
258 chmod 755 /tmp/cluster_tests/run-test.sh
260 # Replace helper state files that differ from the formula's examples
261 if [ -d "${SOURCE_STATES_DIR}" ]; then
262 mkdir -p "${F_DIR}"/extra/extra
264 for f in "${SOURCE_STATES_DIR}"/*; do
265 sed "s/__ANONYMOUS_USER_TOKEN__/${ANONYMOUS_USER_TOKEN}/g;
266 s/__CLUSTER__/${CLUSTER}/g;
267 s/__BLOB_SIGNING_KEY__/${BLOB_SIGNING_KEY}/g;
268 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
269 s/__DOMAIN__/${DOMAIN}/g;
270 s/__HOSTNAME_EXT__/${HOSTNAME_EXT}/g;
271 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
272 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
273 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g;
274 s/__INITIAL_USER__/${INITIAL_USER}/g;
275 s/__KEEPWEB_EXT_SSL_PORT__/${KEEPWEB_EXT_SSL_PORT}/g;
276 s/__KEEP_EXT_SSL_PORT__/${KEEP_EXT_SSL_PORT}/g;
277 s/__MANAGEMENT_TOKEN__/${MANAGEMENT_TOKEN}/g;
278 s/__RELEASE__/${RELEASE}/g;
279 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g;
280 s/__VERSION__/${VERSION}/g;
281 s/__WEBSHELL_EXT_SSL_PORT__/${WEBSHELL_EXT_SSL_PORT}/g;
282 s/__WEBSOCKET_EXT_SSL_PORT__/${WEBSOCKET_EXT_SSL_PORT}/g;
283 s/__WORKBENCH1_EXT_SSL_PORT__/${WORKBENCH1_EXT_SSL_PORT}/g;
284 s/__WORKBENCH2_EXT_SSL_PORT__/${WORKBENCH2_EXT_SSL_PORT}/g;
285 s/__WORKBENCH_SECRET_KEY__/${WORKBENCH_SECRET_KEY}/g" \
286 "${f}" > "${F_DIR}/extra/extra"/$(basename "${f}")
290 # Now, we build the SALT states/pillars trees
291 # As we need to separate both states and pillars in case we want specific
292 # roles, we iterate on both at the same time
295 cat > ${S_DIR}/top.sls << EOFTSLS
302 cat > ${P_DIR}/top.sls << EOFPSLS
309 # States, extra states
310 if [ -d "${F_DIR}"/extra/extra ]; then
311 for f in "${F_DIR}"/extra/extra/*.sls; do
312 echo " - extra.$(basename ${f} | sed 's/.sls$//g')" >> ${S_DIR}/top.sls
316 # If we want specific roles for a node, just add the desired states
317 # and its dependencies
318 if [ -z "${ROLES}" ]; then
320 echo " - nginx.passenger" >> ${S_DIR}/top.sls
321 echo " - postgres" >> ${S_DIR}/top.sls
322 echo " - docker" >> ${S_DIR}/top.sls
323 echo " - arvados" >> ${S_DIR}/top.sls
326 echo " - docker" >> ${P_DIR}/top.sls
327 echo " - nginx_api_configuration" >> ${P_DIR}/top.sls
328 echo " - nginx_controller_configuration" >> ${P_DIR}/top.sls
329 echo " - nginx_keepproxy_configuration" >> ${P_DIR}/top.sls
330 echo " - nginx_keepweb_configuration" >> ${P_DIR}/top.sls
331 echo " - nginx_passenger" >> ${P_DIR}/top.sls
332 echo " - nginx_websocket_configuration" >> ${P_DIR}/top.sls
333 echo " - nginx_webshell_configuration" >> ${P_DIR}/top.sls
334 echo " - nginx_workbench2_configuration" >> ${P_DIR}/top.sls
335 echo " - nginx_workbench_configuration" >> ${P_DIR}/top.sls
336 echo " - postgresql" >> ${P_DIR}/top.sls
338 # If we add individual roles, make sure we add the repo first
339 echo " - arvados.repo" >> ${S_DIR}/top.sls
340 for R in ${ROLES}; do
344 echo " - postgres" >> ${S_DIR}/top.sls
346 echo ' - postgresql' >> ${P_DIR}/top.sls
350 # FIXME: https://dev.arvados.org/issues/17352
351 grep -q "postgres.client" ${S_DIR}/top.sls || echo " - postgres.client" >> ${S_DIR}/top.sls
352 grep -q "nginx.passenger" ${S_DIR}/top.sls || echo " - nginx.passenger" >> ${S_DIR}/top.sls
353 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
355 grep -q "docker" ${P_DIR}/top.sls || echo " - docker" >> ${P_DIR}/top.sls
356 grep -q "postgresql" ${P_DIR}/top.sls || echo " - postgresql" >> ${P_DIR}/top.sls
357 grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls
358 grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo " - nginx_${R}_configuration" >> ${P_DIR}/top.sls
360 "controller" | "websocket" | "workbench" | "workbench2" | "keepweb" | "keepproxy")
362 grep -q "nginx.passenger" ${S_DIR}/top.sls || echo " - nginx.passenger" >> ${S_DIR}/top.sls
363 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
365 grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls
366 grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo " - nginx_${R}_configuration" >> ${P_DIR}/top.sls
370 grep -q "docker" ${S_DIR}/top.sls || echo " - docker" >> ${S_DIR}/top.sls
371 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
373 grep -q "" ${P_DIR}/top.sls || echo " - docker" >> ${P_DIR}/top.sls
374 grep -q "nginx_webshell_configuration" ${P_DIR}/top.sls || echo " - nginx_webshell_configuration" >> ${P_DIR}/top.sls
378 grep -q "docker" ${S_DIR}/top.sls || echo " - docker" >> ${S_DIR}/top.sls
379 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
381 # ATM, no specific pillar needed
385 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
387 # ATM, no specific pillar needed
390 echo "Unknown role ${R}"
397 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
398 if [ -e /root/.psqlrc ]; then
399 if ! ( grep 'pset pager off' /root/.psqlrc ); then
401 cp /root/.psqlrc /root/.psqlrc.provision.backup
407 echo '\pset pager off' >> /root/.psqlrc
408 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
410 # Now run the install
411 salt-call --local state.apply -l ${LOG_LEVEL}
413 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
414 if [ "x${DELETE_PSQL}" = "xyes" ]; then
415 echo "Removing .psql file"
419 if [ "x${RESTORE_PSQL}" = "xyes" ]; then
420 echo "Restoring .psql file"
421 mv -v /root/.psqlrc.provision.backup /root/.psqlrc
423 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
425 # Leave a copy of the Arvados CA so the user can copy it where it's required
426 echo "Copying the Arvados CA certificate to the installer dir, so you can import it"
427 # If running in a vagrant VM, also add default user to docker group
428 if [ "x${VAGRANT}" = "xyes" ]; then
429 cp /etc/ssl/certs/arvados-snakeoil-ca.pem /vagrant/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
431 echo "Adding the vagrant user to the docker group"
432 usermod -a -G docker vagrant
434 cp /etc/ssl/certs/arvados-snakeoil-ca.pem ${SCRIPT_DIR}/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
437 # Test that the installation finished correctly
438 if [ "x${TEST}" = "xyes" ]; then
439 cd /tmp/cluster_tests