forked from openedx-unsupported/devstack
-
Notifications
You must be signed in to change notification settings - Fork 2
/
provision.sh
executable file
·178 lines (160 loc) · 5.25 KB
/
provision.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env bash
# This script will provision the services specified in the argument list,
# or all services if no arguments are provided.
#
# Non-existant services will be ignored.
# Specifying services more than once will cause them to be provisioned more
# than once.
#
# To allow services to be passed in through a Makefile target,
# services can be plus-sign-separated as well as space separated.
#
# Service(s) will generally be setup in the following manner
# (but refer to individual ./provision-{service} scripts to be sure):
# 1. Migrations run,
# 2. Tenants—as in multi-tenancy—setup,
# 3. Service users and OAuth clients setup in LMS,
# 4. Static assets compiled/collected.
#
# DEVSTACK DEVELOPERS -- To add a service to provisioning:
# * Create a provision-{service}.sh script for your new service.
# * Add the name of the service to ALL_SERVICES.
#
# Example usages:
# ./provision.sh # Provision all services.
# ./provision.sh lms ecommerce discovery # Provision these three services.
# ./provision.sh lms+ecommerce+discovery # Same as previous command.
set -e
set -o pipefail
set -u
set -x
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# All provisionable services.
# (Leading and trailing space are necessary for if-checks.)
# The order here is the order we will use when provisioning, even if only a subset
# of services are requested.
# Changing this order may break provisioning.
# For example, Discovery breaks if LMS is not provisioned first.
ALL_SERVICES_IN_ORDER=" \
lms \
ecommerce \
discovery \
credentials \
e2e \
forum \
notes \
registrar \
analyticspipeline \
marketing \
xqueue \
"
# What should we provision?
if [[ $# -eq 0 ]]; then
requested_services=$ALL_SERVICES_IN_ORDER
else
arg_string=" $* "
# Replace plus signs with spaces in order to allow plus-sign-separated
# services in addition to space-separated services.
requested_services="${arg_string//+/ }"
fi
# Returns whether first arg contains second arg as substring.
is_substring() {
local str="$1"
local substr="$2"
if [[ "$str" == *" ${substr} "* ]]; then
return 0 # Note that '0' means 'success' (i.e., true) in bash.
else
return 1
fi
}
# Returns whether we need to boot mongo,
# based on the space-separated list of services passed in the first argument.
needs_mongo() {
local services="$1"
if is_substring "$services" lms || is_substring "$services" forum; then
return 0
else
return 1
fi
}
# Validate user input, building up list of services to provision.
to_provision=" "
for serv in $requested_services; do
case "$serv" in
studio)
echo -e "${YELLOW}Studio is provisioned alongside LMS.\nPass 'lms' as an argument to ensure that Studio is provisioned.${NC}"
continue
;;
edx_notes_api)
# Treat 'edx_notes_api' as an alias for 'notes'.
service="notes"
;;
*)
service="$serv"
esac
if is_substring "$ALL_SERVICES_IN_ORDER" "$service"; then
if ! is_substring "$to_provision" "$service"; then
to_provision="${to_provision}${service} "
fi
else
echo -e "${YELLOW}Service '${service}' either doesn't exist or isn't provisionable.${NC}"
fi
done
# Order the services based on $ALL_SERVICES_IN_ORDER.
to_provision_ordered=" "
for ordered_service in $ALL_SERVICES_IN_ORDER; do
if is_substring "$to_provision" "$ordered_service"; then
to_provision_ordered="${to_provision_ordered}${ordered_service} "
fi
done
if [[ "$to_provision_ordered" = " " ]]; then
echo -e "${YELLOW}Nothing to provision; will exit.${NC}"
exit 0
fi
echo -e "${GREEN}Will provision the following:\n ${to_provision_ordered}${NC}"
# Bring the databases online.
docker-compose up -d mysql
if needs_mongo "$to_provision_ordered"; then
docker-compose up -d mongo
fi
# Ensure the MySQL server is online and usable
echo "${GREEN}Waiting for MySQL.${NC}"
until docker-compose exec -T mysql bash -c "mysql -uroot -se \"SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')\"" &> /dev/null
do
printf "."
sleep 1
done
# In the event of a fresh MySQL container, wait a few seconds for the server to restart
# See https://github.com/docker-library/mysql/issues/245 for why this is necessary.
sleep 20
echo -e "${GREEN}MySQL ready.${NC}"
# Ensure that the MySQL databases and users are created for all IDAs.
# (A no-op for databases and users that already exist).
echo -e "${GREEN}Ensuring MySQL databases and users exist...${NC}"
docker-compose exec -T mysql bash -c "mysql -uroot mysql" < provision.sql
# If necessary, ensure the MongoDB server is online and usable
# and create its users.
if needs_mongo "$to_provision_ordered"; then
echo -e "${GREEN}Waiting for MongoDB...${NC}"
until docker-compose exec -T mongo bash -c 'mongo --eval "printjson(db.serverStatus())"' &> /dev/null
do
printf "."
sleep 1
done
echo -e "${GREEN}MongoDB ready.${NC}"
echo -e "${GREEN}Creating MongoDB users...${NC}"
docker-compose exec -T mongo bash -c "mongo" < mongo-provision.js
else
echo -e "${GREEN}MongoDB preparation not required; skipping.${NC}"
fi
# Run the service-specific provisioning script(s)
for service in $to_provision_ordered; do
echo -e "${GREEN} Provisioning ${service}...${NC}"
./provision-"$service".sh
echo -e "${GREEN} Provisioned ${service}.${NC}"
done
docker image prune -f
echo -e "${GREEN}Provisioning complete!${NC}"