Skript prod_deploy.sh
Automaticky generovaná dokumentace skriptu scripts/prod_deploy.sh.
1#!/bin/bash
2###########
3#### SCRIPT: DEPLOYMENT from DOCKERHUB into SWARM
4#### PARAMS: see -h
5###########
6#USAGE: deployment based on release on GITHUB, i.e. GitHub actions published docker images on Docker Hub
7
8# ------ !!!! ----------
9SKIP_ALL_CHECKS=1 #IF CHANGED TO 1 then all MANUAL CHECKS, ie questions during script runtime are disabled!
10# ------ !!!! ----------
11
12ask_continue () {
13 while true; do
14
15 read -p "$1 (y or n): " input
16 case $input in
17 [yY]*)
18 echo '---Continuing!'
19 break
20 ;;
21 [nN]*)
22 echo '***So do THAT, exiting!'
23 exit 1
24 ;;
25 *)
26 echo '***Invalid input' >&2
27 esac
28 done
29}
30
31echo_dec ()
32{
33 echo "---------------------------------------"
34 echo "--> $1"
35 echo "---------------------------------------"
36}
37
38er () {
39 echo_dec "${1}"
40 eval "${1}"
41 ret_val=$?
42 echo "....................."
43 echo ">> DONE: ${1} with status: ${ret_val}"
44 return $ret_val
45}
46
47check_create_network () {
48
49 docker network inspect ${network_name} > /dev/null 2>&1
50 network_status=$?
51 if [ ${network_status} -eq 1 ]; then
52 er "docker network create -d overlay --attachable ${network_name}"
53 echo_dec "Network ${network_name} created"
54 else
55 echo_dec "Network ${network_name} already exists"
56 fi
57}
58
59check_stack_exists ()
60{
61 docker stack ps ${stack_name} > /dev/null 2>&1
62 stack_status=$?
63 return ${stack_status}
64}
65
66run_default ()
67{
68 echo_dec "# DEPLOYMENT in SWARM MODE (i.e. host has to be joined or initiated as SWARM NODE) @${start_time}"
69
70 #CHECK SWARM ACTIVATED
71 docker node ls
72 status_swarm=$?
73
74 if [ $status_swarm -ne 0 ]; then
75 echo_dec "SWARM not initiated or joined at this HOST. Exiting"
76 exit 1
77 fi
78 in_args="${1}"
79
80 #DISCLAIMER about DEFAULT CASE triggering
81 if [ ${SKIP_ALL_CHECKS} -eq 0 ] && [ "${in_args}" == "" ]; then
82 ask_continue "Do you want to continue with DEFAULT CASE? "
83 fi
84 echo_dec "DEPLOY all services."
85
86 #RAISE questions about conditions for deployemnt
87 do_manual_checks
88
89 # Check network exists
90 check_create_network
91
92 #Update images
93 er "${cmd_pull_images}"
94 if [ $? -gt 0 ]; then
95 echo_dec "${msg_pull_fail} with TAG: ${IMAGE_TAG} => EXITING"
96 exit
97 fi
98
99 er "${cmd_deploy_base} ${compose_proxy} ${stack_name} && \
100 ${cmd_deploy_base} ${compose_prod} ${stack_name}" && \
101 echo_dec "$msg_success" || echo_dec "${msg_fail_build}"
102}
103
104Help ()
105{
106 cat <<EOF
107 !!!MUST BE RUN from REPOSIOTRY root like =>
108 usage: ./scrips/${script_name} [-x|-u <tag_name>|-t <tag_name>|-i],
109 ---
110 PURPOSE: manage deployment/run of production docker images build from GIT repository for AIS CR project in SWARM mode
111 ----
112
113 Examples on options:
114 1) Remove complete docker stack, i.e all services
115
116 $./scripts/${script_name} -x
117
118 2) Update all services with new images
119
120 $./scripts/${script_name} -u <tag_name>
121
122 3) Deploy or redeploy all services in swarm mode with image tag (version number or "latest")
123
124 $./scripts/${script_name} -t <tag_name>
125
126 4) Get information about available versions.
127
128 $./scripts/${script_name} -i
129
130 -----
131 Summnary:
132 -h help
133 -x remove docker stack (all services)
134 -u update all services using rolling approach with tag name <tag_name>
135 -t deploy all services in swarm mode with tag name <tag_name>
136 -i information about available versions
137
138EOF
139}
140
141do_manual_checks ()
142{
143 # DO SOME MANUAL CHECKS of deployment steps by ASKING questions (can be skipped by providing arbitrary command-line argument to the script)
144 if [ ${SKIP_ALL_CHECKS} -eq 1 ]; then
145 echo_dec "DEPLOYMENT QUESTIONS SKIPPED due to CONSTANT SKIP_ALL_CHECKS set ${SKIP_ALL_CHECKS}"
146 else
147 # DO SOME MANUAL CHECKS of deployment steps by ASKING questions (can be skipped)
148 ask_continue "1.Did you APPLY MANUAL migrations to DB (if relevant)?"
149 ask_continue "2.Did you MAKE release on GitHUB and waited to for end Github Action for publishing Docker images ?"
150 ask_continue "3.Did you CONFIGURE secrets to point to desired DB location (using docker secrets db_conf, i.e swarm secrets MUST be already existing) ?"
151 fi
152}
153
154script_name=$(basename ${0})
155passed_args="$@"
156
157# Read first positional argument if exists (before any flags like -t or -u)
158if [[ "$1" != -* ]] && [[ -n "$1" ]]; then
159 IMAGE_SOURCE=$(echo "$1" | tr '[:upper:]' '[:lower:]')
160 if [[ "$IMAGE_SOURCE" != "dockerhub" && "$IMAGE_SOURCE" != "github" ]]; then
161 echo "ERROR: Invalid source type '$IMAGE_SOURCE'. Use 'dockerhub' or 'github'."
162 exit 1
163 fi
164 echo ">>> IMAGE SOURCE: ${IMAGE_SOURCE}"
165 shift # Shift to process remaining args with getopts
166fi
167
168IMAGE_SOURCE="${IMAGE_SOURCE:-github}" # Default to github if not specified
169
170while getopts ":t:u:" option; do
171
172 case ${option} in
173 t|u|d) #Overriding of default latest image by providing specific tag
174 if [ "$OPTARG" == "latest" ]; then
175 echo "Warning: IMAGE TAG must not be 'latest'"
176 exit 1
177 fi
178 export IMAGE_TAG="${OPTARG}"
179 tag_passed="yes"
180 echo "IMAGE TAG FOR DOCKER IMAGES IS >>>> ${IMAGE_TAG}"
181 ;;
182 *)
183 ;;
184 esac
185done
186
187#INPUTS
188
189# Override image source path based on the chosen source
190# Compose image tags (must match how GitHub Actions publish images)
191case $IMAGE_SOURCE in
192 dockerhub)
193 export amcr_image="aiscr/webamcr:${IMAGE_TAG}"
194 export proxy_image="aiscr/webamcr-proxy:${IMAGE_TAG}"
195 export redis_image="aiscr/webamcr-redis:${IMAGE_TAG}"
196 ;;
197 github)
198 export amcr_image="ghcr.io/arup-cas/aiscr-webamcr:${IMAGE_TAG}"
199 export proxy_image="ghcr.io/arup-cas/aiscr-webamcr-proxy:${IMAGE_TAG}"
200 export redis_image="ghcr.io/arup-cas/aiscr-webamcr-redis:${IMAGE_TAG}"
201 ;;
202esac
203
204stack_name="swarm_webamcr"
205network_name="prod-net" #MUST MATCH WITH COMPOSE FILES!!!
206
207compose_proxy="docker-compose-proxy.yml"
208compose_prod="docker-compose.yml"
209
210msg_fail_build="!! DEPLOYMENT not successfull"
211msg_pull_fail="!! PULL not successfull"
212msg_pull_success="PULL success"
213msg_success="DEPLOYED in SWARM MODE ---> APPLICATION ACCESSIBLE on: port 8080"
214
215#TRANSLATION backups path
216tr_path="$HOME/translations_backup"
217mkdir -p ${tr_path}
218
219#LOGGING
220log_dir="logs/prod_deploy"
221start_time=$(date +%Y%m%dT%H%M%S)
222log_file="${start_time}_prod-deployment_${passed_args}.log"
223mkdir -p ${log_dir}
224
225OPTIND=1
226
227#REDIRECT to log
228exec > >(tee "${log_dir}/${log_file}" )
229exec 2>&1
230
231#Build commands
232cmd_stack_rm="docker stack rm ${stack_name}"
233cmd_pull_images="docker pull ${proxy_image} && docker pull ${amcr_image}"
234cmd_deploy_base="docker stack deploy --compose-file"
235
236prune_images (){
237#Cleaning old images
238echo "Pruning unused Docker images..."
239docker image prune -f
240}
241
242option_passed=false
243
244while getopts "hxu:t:i" option; do
245 case ${option} in
246 h) # display Help
247 echo "OPTION: -h"
248 option_passed=true
249 Help
250 exit;;
251 x) echo "OPTION: -x"
252 option_passed=true
253 prune_images
254 echo_dec "Remove docker stack: ${stack_name}"
255 if check_stack_exists; then
256 er "${cmd_stack_rm}" && \
257 echo_dec "Stack ${stack_name} removal successful" || echo_dec "Stack ${stack_name} removal FAILED"
258 else
259 echo_dec "STACK ${stack_name} doesn't exist so can't be removed!!!"
260 fi
261 echo sleep 20 second to wait before network is really removed.
262 sleep 20 # Need to wait before network is really removed.
263 ;;
264 u) #update services
265 echo "OPTION: -u with ${IMAGE_TAG}"
266 option_passed=true
267 prune_images
268 echo_dec "Update services with new images!"
269 if check_stack_exists ; then
270 do_manual_checks
271 docker service update --force --image ${amcr_image} ${stack_name}_web && \
272 docker service update --force --image ${proxy_image} ${stack_name}_proxy && \
273 echo_dec "$msg_success" || echo_dec "$msg_fail_build"
274 else
275 echo_dec "SERVICE CANNOT BE UPDATED because stack doesn't exist !!!"
276 fi
277 ;;
278 t)
279 echo "OPTION: -t with ${IMAGE_TAG}"
280 option_passed=true
281 prune_images
282 run_default b
283 ;;
284 i)
285 option_passed=true
286 echo 10 last available versions
287 curl -s https://hub.docker.com/v2/repositories/aiscr/webamcr/tags/ | jq '."results"[0:10] | .[]["name"]'
288 ;;
289 \?) # Invalid option
290 echo_dec "OPTION: INVALID"
291 echo "Error: Invalid option ${option}"
292 exit;;
293 esac
294done
295
296if [ "$option_passed" = false ]; then
297 echo_dec "No option is passed as ARG, you have to specify a parameter, for help use -h."
298fi
299
300exit 0