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 HOSTNAME_INT="127.0.1.1"
113 INITIAL_USER_EMAIL=""
114 INITIAL_USER_PASSWORD=""
116 CONTROLLER_EXT_SSL_PORT=8000
117 KEEP_EXT_SSL_PORT=25101
118 # Both for collections and downloads
119 KEEPWEB_EXT_SSL_PORT=9002
120 WEBSHELL_EXT_SSL_PORT=4202
121 WEBSOCKET_EXT_SSL_PORT=8002
122 WORKBENCH1_EXT_SSL_PORT=443
123 WORKBENCH2_EXT_SSL_PORT=3001
128 POSTGRES_TAG="v0.41.3"
137 F_DIR="/srv/formulas"
143 if [ -s ${CONFIG_FILE} ]; then
144 source ${CONFIG_FILE}
146 echo >&2 "Please create a '${CONFIG_FILE}' file with initial values, as described in FIXME_URL_TO_DESCR"
150 if ! grep -E '^[[:alnum:]]{5}$' <<<${CLUSTER} ; then
151 echo >&2 "ERROR: <CLUSTER> must be exactly 5 alphanumeric characters long"
152 echo >&2 "Fix the cluster name in the 'local.params' file and re-run the provision script"
157 apt-get install -y curl git jq
159 if [ which salt-call ]; then
160 echo "Salt already installed"
162 curl -L https://bootstrap.saltstack.com -o /tmp/bootstrap_salt.sh
163 sh /tmp/bootstrap_salt.sh -XdfP -x python3
164 /bin/systemctl stop salt-minion.service
165 /bin/systemctl disable salt-minion.service
168 # Set salt to masterless mode
169 cat > /etc/salt/minion << EOFSM
181 mkdir -p ${S_DIR} ${F_DIR} ${P_DIR}
183 # Get the formula and dependencies
184 cd ${F_DIR} || exit 1
185 git clone --branch "${ARVADOS_TAG}" https://github.com/arvados/arvados-formula.git
186 git clone --branch "${DOCKER_TAG}" https://github.com/saltstack-formulas/docker-formula.git
187 git clone --branch "${LOCALE_TAG}" https://github.com/saltstack-formulas/locale-formula.git
188 git clone --branch "${NGINX_TAG}" https://github.com/saltstack-formulas/nginx-formula.git
189 git clone --branch "${POSTGRES_TAG}" https://github.com/saltstack-formulas/postgres-formula.git
191 if [ "x${BRANCH}" != "x" ]; then
192 cd ${F_DIR}/arvados-formula || exit 1
193 git checkout -t origin/"${BRANCH}"
197 if [ "x${VAGRANT}" = "xyes" ]; then
198 SOURCE_PILLARS_DIR="/vagrant/${CONFIG_DIR}/pillars"
199 TESTS_DIR="/vagrant/${TESTS_DIR}"
201 SOURCE_PILLARS_DIR="${SCRIPT_DIR}/${CONFIG_DIR}/pillars"
202 TESTS_DIR="${SCRIPT_DIR}/${TESTS_DIR}"
205 SOURCE_STATES_DIR="${EXTRA_STATES_DIR}"
207 # Replace variables (cluster, domain, etc) in the pillars, states and tests
208 # to ease deployment for newcomers
209 for f in "${SOURCE_PILLARS_DIR}"/*; do
210 sed "s/__ANONYMOUS_USER_TOKEN__/${ANONYMOUS_USER_TOKEN}/g;
211 s/__BLOB_SIGNING_KEY__/${BLOB_SIGNING_KEY}/g;
212 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
213 s/__CLUSTER__/${CLUSTER}/g;
214 s/__DOMAIN__/${DOMAIN}/g;
215 s/__HOSTNAME_EXT__/${HOSTNAME_EXT}/g;
216 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
217 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
218 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g;
219 s/__INITIAL_USER__/${INITIAL_USER}/g;
220 s/__KEEPWEB_EXT_SSL_PORT__/${KEEPWEB_EXT_SSL_PORT}/g;
221 s/__KEEP_EXT_SSL_PORT__/${KEEP_EXT_SSL_PORT}/g;
222 s/__MANAGEMENT_TOKEN__/${MANAGEMENT_TOKEN}/g;
223 s/__RELEASE__/${RELEASE}/g;
224 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g;
225 s/__VERSION__/${VERSION}/g;
226 s/__WEBSHELL_EXT_SSL_PORT__/${WEBSHELL_EXT_SSL_PORT}/g;
227 s/__WEBSOCKET_EXT_SSL_PORT__/${WEBSOCKET_EXT_SSL_PORT}/g;
228 s/__WORKBENCH1_EXT_SSL_PORT__/${WORKBENCH1_EXT_SSL_PORT}/g;
229 s/__WORKBENCH2_EXT_SSL_PORT__/${WORKBENCH2_EXT_SSL_PORT}/g;
230 s/__WORKBENCH_SECRET_KEY__/${WORKBENCH_SECRET_KEY}/g" \
231 "${f}" > "${P_DIR}"/$(basename "${f}")
234 mkdir -p /tmp/cluster_tests
235 # Replace cluster and domain name in the test files
236 for f in "${TESTS_DIR}"/*; do
237 sed "s/__CLUSTER__/${CLUSTER}/g;
238 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
239 s/__DOMAIN__/${DOMAIN}/g;
240 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
241 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
242 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g
243 s/__INITIAL_USER__/${INITIAL_USER}/g;
244 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g" \
245 "${f}" > "/tmp/cluster_tests"/$(basename "${f}")
247 chmod 755 /tmp/cluster_tests/run-test.sh
249 # Replace helper state files that differ from the formula's examples
250 if [ -d "${SOURCE_STATES_DIR}" ]; then
251 mkdir -p "${F_DIR}"/extra/extra
253 for f in "${SOURCE_STATES_DIR}"/*; do
254 sed "s/__ANONYMOUS_USER_TOKEN__/${ANONYMOUS_USER_TOKEN}/g;
255 s/__CLUSTER__/${CLUSTER}/g;
256 s/__BLOB_SIGNING_KEY__/${BLOB_SIGNING_KEY}/g;
257 s/__CONTROLLER_EXT_SSL_PORT__/${CONTROLLER_EXT_SSL_PORT}/g;
258 s/__DOMAIN__/${DOMAIN}/g;
259 s/__HOSTNAME_EXT__/${HOSTNAME_EXT}/g;
260 s/__HOSTNAME_INT__/${HOSTNAME_INT}/g;
261 s/__INITIAL_USER_EMAIL__/${INITIAL_USER_EMAIL}/g;
262 s/__INITIAL_USER_PASSWORD__/${INITIAL_USER_PASSWORD}/g;
263 s/__INITIAL_USER__/${INITIAL_USER}/g;
264 s/__KEEPWEB_EXT_SSL_PORT__/${KEEPWEB_EXT_SSL_PORT}/g;
265 s/__KEEP_EXT_SSL_PORT__/${KEEP_EXT_SSL_PORT}/g;
266 s/__MANAGEMENT_TOKEN__/${MANAGEMENT_TOKEN}/g;
267 s/__RELEASE__/${RELEASE}/g;
268 s/__SYSTEM_ROOT_TOKEN__/${SYSTEM_ROOT_TOKEN}/g;
269 s/__VERSION__/${VERSION}/g;
270 s/__WEBSHELL_EXT_SSL_PORT__/${WEBSHELL_EXT_SSL_PORT}/g;
271 s/__WEBSOCKET_EXT_SSL_PORT__/${WEBSOCKET_EXT_SSL_PORT}/g;
272 s/__WORKBENCH1_EXT_SSL_PORT__/${WORKBENCH1_EXT_SSL_PORT}/g;
273 s/__WORKBENCH2_EXT_SSL_PORT__/${WORKBENCH2_EXT_SSL_PORT}/g;
274 s/__WORKBENCH_SECRET_KEY__/${WORKBENCH_SECRET_KEY}/g" \
275 "${f}" > "${F_DIR}/extra/extra"/$(basename "${f}")
279 # Now, we build the SALT states/pillars trees
280 # As we need to separate both states and pillars in case we want specific
281 # roles, we iterate on both at the same time
284 cat > ${S_DIR}/top.sls << EOFTSLS
291 cat > ${P_DIR}/top.sls << EOFPSLS
298 # States, extra states
299 if [ -d "${F_DIR}"/extra/extra ]; then
300 for f in "${F_DIR}"/extra/extra/*.sls; do
301 echo " - extra.$(basename ${f} | sed 's/.sls$//g')" >> ${S_DIR}/top.sls
305 # If we want specific roles for a node, just add the desired states
306 # and its dependencies
307 if [ -z "${ROLES}" ]; then
309 echo " - nginx.passenger" >> ${S_DIR}/top.sls
310 echo " - postgres" >> ${S_DIR}/top.sls
311 echo " - docker" >> ${S_DIR}/top.sls
312 echo " - arvados" >> ${S_DIR}/top.sls
315 echo " - docker" >> ${P_DIR}/top.sls
316 echo " - nginx_api_configuration" >> ${P_DIR}/top.sls
317 echo " - nginx_controller_configuration" >> ${P_DIR}/top.sls
318 echo " - nginx_keepproxy_configuration" >> ${P_DIR}/top.sls
319 echo " - nginx_keepweb_configuration" >> ${P_DIR}/top.sls
320 echo " - nginx_passenger" >> ${P_DIR}/top.sls
321 echo " - nginx_websocket_configuration" >> ${P_DIR}/top.sls
322 echo " - nginx_webshell_configuration" >> ${P_DIR}/top.sls
323 echo " - nginx_workbench2_configuration" >> ${P_DIR}/top.sls
324 echo " - nginx_workbench_configuration" >> ${P_DIR}/top.sls
325 echo " - postgresql" >> ${P_DIR}/top.sls
327 # If we add individual roles, make sure we add the repo first
328 echo " - arvados.repo" >> ${S_DIR}/top.sls
329 for R in ${ROLES}; do
333 echo " - postgres" >> ${S_DIR}/top.sls
335 echo ' - postgresql' >> ${P_DIR}/top.sls
339 # FIXME: https://dev.arvados.org/issues/17352
340 grep -q "postgres.client" ${S_DIR}/top.sls || echo " - postgres.client" >> ${S_DIR}/top.sls
341 grep -q "nginx.passenger" ${S_DIR}/top.sls || echo " - nginx.passenger" >> ${S_DIR}/top.sls
342 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
344 grep -q "docker" ${P_DIR}/top.sls || echo " - docker" >> ${P_DIR}/top.sls
345 grep -q "postgresql" ${P_DIR}/top.sls || echo " - postgresql" >> ${P_DIR}/top.sls
346 grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls
347 grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo " - nginx_${R}_configuration" >> ${P_DIR}/top.sls
349 "workbench" | "workbench2" | "keepweb" | "keepproxy")
351 grep -q "nginx.passenger" ${S_DIR}/top.sls || echo " - nginx.passenger" >> ${S_DIR}/top.sls
352 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
354 grep -q "nginx_passenger" ${P_DIR}/top.sls || echo " - nginx_passenger" >> ${P_DIR}/top.sls
355 grep -q "nginx_${R}_configuration" ${P_DIR}/top.sls || echo " - nginx_${R}_configuration" >> ${P_DIR}/top.sls
359 grep -q "docker" ${S_DIR}/top.sls || echo " - docker" >> ${S_DIR}/top.sls
360 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
362 grep -q "" ${P_DIR}/top.sls || echo " - docker" >> ${P_DIR}/top.sls
363 grep -q "nginx_webshell_configuration" ${P_DIR}/top.sls || echo " - nginx_webshell_configuration" >> ${P_DIR}/top.sls
367 grep -q "docker" ${S_DIR}/top.sls || echo " - docker" >> ${S_DIR}/top.sls
368 grep -q "arvados.${R}" ${S_DIR}/top.sls || echo " - arvados.${R}" >> ${S_DIR}/top.sls
370 # ATM, no specific pillar needed
373 echo "Unknown role ${R}"
380 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
381 if [ -e /root/.psqlrc ]; then
382 if ! ( grep 'pset pager off' /root/.psqlrc ); then
384 cp /root/.psqlrc /root/.psqlrc.provision.backup
390 echo '\pset pager off' >> /root/.psqlrc
391 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
393 # Now run the install
394 salt-call --local state.apply -l ${LOG_LEVEL}
396 # FIXME! #16992 Temporary fix for psql call in arvados-api-server
397 if [ "x${DELETE_PSQL}" = "xyes" ]; then
398 echo "Removing .psql file"
402 if [ "x${RESTORE_PSQL}" = "xyes" ]; then
403 echo "Restoring .psql file"
404 mv -v /root/.psqlrc.provision.backup /root/.psqlrc
406 # END FIXME! #16992 Temporary fix for psql call in arvados-api-server
408 # Leave a copy of the Arvados CA so the user can copy it where it's required
409 echo "Copying the Arvados CA certificate to the installer dir, so you can import it"
410 # If running in a vagrant VM, also add default user to docker group
411 if [ "x${VAGRANT}" = "xyes" ]; then
412 cp /etc/ssl/certs/arvados-snakeoil-ca.pem /vagrant/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
414 echo "Adding the vagrant user to the docker group"
415 usermod -a -G docker vagrant
417 cp /etc/ssl/certs/arvados-snakeoil-ca.pem ${SCRIPT_DIR}/${CLUSTER}.${DOMAIN}-arvados-snakeoil-ca.pem
420 # Test that the installation finished correctly
421 if [ "x${TEST}" = "xyes" ]; then
422 cd /tmp/cluster_tests