-
Notifications
You must be signed in to change notification settings - Fork 4
/
terra-app-local.sh
executable file
·284 lines (235 loc) · 8.16 KB
/
terra-app-local.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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#!/bin/bash
###
### Parameters
###
readonly progname="$(basename "${0}")"
readonly progdir="$(readlink "$(dirname "${0}")")"
readonly args=("$@")
# Set bash shell options
set -e
###
### Functions
###
usage() {
cat <<USAGEEOF
${progname} deploys an app on a local minikube cluster.
Find more information at: https://github.com/DataBiosphere/terra-app
Usage:
${progname} [command]
Available commands:
install installs an app
uninstall deletes an app
status displays stats about an app
list lists all apps
show-kubectl prints kubectl commands to interact with an app
Flags:
-h, --help display help
Use "${progname} [command] --help" for more information about a command.
USAGEEOF
}
install_usage() {
cat <<USAGEEOF
Install an app to a locally running minikube cluster.
For more information about configuring minikube, see: https://github.com/DataBiosphere/terra-app
Usage:
${progname} install -f [filename] -a [extra args] ...
Flags:
-a, --arg optional. extra args to the app launch command. can be repeated.
-f, --filename path to the app descriptor file
-h, --help display help
USAGEEOF
}
install() {
local _filename
local _args=()
if [ -z "$1" ]; then
install_usage
exit 0
fi
while [ "$1" != "" ]; do
case "$1" in
-a | --arg)
shift
_args+=($1)
;;
-f | --filename)
shift
_filename=$1
;;
-h | --help)
install_usage
exit 0
;;
*)
echo "Unrecognized argument '${1}'."
echo "Run '${progname} install --help' to see available arguments."
exit 1
;;
esac
shift
done
if [ -z "${_filename}" ]; then
echo "Error: -f needs an argument."
echo "Run '${progname} install --help' to see available arguments."
exit 1
fi
if ! test -f "${_filename}"; then
echo "Error: file '${_filename}' does not exist."
exit 1
fi
# get minikube ip
local _minikube_ip=$(minikube ip)
if [ -z "${_minikube_ip}" ]; then
echo "Unable to retrieve minikube public IP. Is minikube running?"
exit 1
fi
install_nginx
install_app "${_filename}" "${_args[@]}"
echo ""
echo "Congratulations! Your app has been installed on minikube."
echo ""
echo "To poll application startup, do one or more of the following:"
echo ""
echo " kubectl get pod -n ${_namespace}"
echo " kubectl describe pod -n ${_namespace} [pod-name]"
echo " kubectl logs -n ${_namespace} [pod-name]"
echo ""
echo "Once the pod is RUNNING, do the following to open the app:"
echo ""
echo "1. Run minikube service list to get service namespace and service name"
echo ""
echo "2. Run minikube service <service_name> -n <namespace>"
echo ""
}
install_nginx() {
echo "Setting up nginx ingress controller..."
# check if nginx namespace exists
if ! kubectl get ns | grep -q nginx; then
kubectl create namespace nginx
fi
# check if we need to add the nginx helm repo
if ! helm show chart ingress-nginx/ingress-nginx --version=3.23.0 >/dev/null 2>&1; then
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update > /dev/null
helm repo update >/dev/null
fi
# install nginx
helm upgrade --install nginx ingress-nginx/ingress-nginx \
-n nginx \
--version 3.23.0 \
--set controller.service.externalIPs[0]="${_minikube_ip}" >/dev/null 2>&1
}
# note only single-service apps are currently supported
install_app() {
# read args
local _filename="$1"
local _extraargs="$2"
# parse information out of the descriptor
_appname=$(yq e '.name' "${_filename}")
# Do not change this namespace convention without modifying the github action
_namespace="${_appname}-ns"
local _ksa="${_appname}-ksa"
local _baseurl=$(yq e '.services.*.baseUrl' "${_filename}")
if [ -z "${_baseurl}" ] | [ "${_baseurl}" == "null" ]; then
local _ingresspath="/${_appname}(/|$)(.*)"
else
local _ingresspath="${_baseurl}"
fi
_hostname=$(jq -r .hostname < ci-config.json)
if [ -z "${_appname}" ] | [ "${_appname}" == "null" ] ; then
echo "Error: could not parse app name from file '${_filename}'."
exit 1
fi
echo "Installing '${_appname}' from descriptor file '${_filename}'..."
# create the namespace if it doesn't already exist
if ! kubectl get ns | grep -q "${_namespace}"; then
kubectl create namespace "${_namespace}"
fi
echo "Namespace created."
# create KSA if it doesn't already exist
if ! kubectl get serviceaccount -n "${_namespace}" | grep -q "${_appname_ksa}"; then
kubectl create serviceaccount --namespace "${_namespace}" "${_appname_ksa}"
fi
echo "Service account created"
# build values yaml from app descriptor
# TODO note this supports at most 3 EVs; there is probably a nicer way but
# I couldn't figure out how to make yq map over keys.
local _tmp_values="$(date +%s)-temp.tmp"
touch "${_tmp_values}"
yq e \
".nameOverride=.name \
| .image.image=.services.*.image \
| .image.port=.services.*.port \
| .image.baseUrl=.services.*.baseUrl \
| .image.command=.services.*.command \
| .image.args=.services.*.args \
| .ingress.hosts[0].host=\"${_hostname}\" \
| .ingress.hosts[0].paths[0]=\"${_ingresspath}\" \
| .persistence.hostPath=\"/data\" \
| .extraEnv[0].name=(.services.*.environment | to_entries | .[0] | .key ) // \"unset0\"
| .extraEnv[0].value=(.services.*.environment | to_entries | .[0] | .value ) // \"unset0\"
| .extraEnv[1].name=(.services.*.environment | to_entries | .[1] | .key ) // \"unset1\"
| .extraEnv[1].value=(.services.*.environment | to_entries | .[1] | .value ) // \"unset1\"
| .extraEnv[2].name=(.services.*.environment | to_entries | .[2] | .key ) // \"unset2\"
| .extraEnv[2].value=(.services.*.environment | to_entries | .[2] | .value ) // \"unset2\"
| del(.name) \
| del(.services)" "${_filename}" > "${_tmp_values}"
# apply extra args, if any
for a in "${_extraargs[@]}"; do
yq e -i ".image.args += \"$a\"" "${_tmp_values}"
done
# apply proxy redirect rules if baseUrl is not specified by the app
if [ -z "${_baseurl}" ] | [ "${_baseurl}" == "null" ]; then
yq e -i \
".ingress.annotations.\"nginx.ingress.kubernetes.io/rewrite-target\"=\"/\$2\" \
| .ingress.annotations.\"nginx.ingress.kubernetes.io/proxy-redirect-from\"=\"http://${_hostname}/\" \
| .ingress.annotations.\"nginx.ingress.kubernetes.io/proxy-redirect-to\"=\"http://${_hostname}/${_appname}/\"" "${_tmp_values}"
fi
#echo "Installing chart with values:"
#cat "${_tmp_values}"
#echo ""
echo "Preparing for helm install..."
# install the app
helm upgrade --install -n "${_namespace}" \
"${_appname}" \
terra-app-chart/ \
-f "${_tmp_values}"
rm "${_tmp_values}"
}
main() {
local _subcmd
local _subcmd_args
if [ -z "$1" ]; then
usage
exit 0
fi
while [ "$1" != "" ]; do
case "$1" in
install | uninstall | status | list | show-kubectl)
_subcmd="$1"
shift
_subcmd_args=("$@")
break;;
-h | --help)
usage
exit 0;;
*)
echo "Unrecognized command '${1}'."
echo "Run '${progname} --help' to see available arguments."
exit 1;;
esac
shift
done
if [ "${_subcmd}" == "install" ]; then
install "${_subcmd_args[@]}"
else
echo "Unrecognized command '${_subcmd}'."
echo "Run '${progname} --help' to see available arguments."
exit 1
fi
}
###
### Main
###
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "${args[@]}"
fi