-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathci
executable file
·189 lines (167 loc) · 5.5 KB
/
ci
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
#!/bin/bash
# Deploys a local Concourse CI cluster using Docker Compose.
#
# Enforce shell robustness
set -o errexit
set -o nounset
set -o pipefail
# Show line numbers when tracing execution.
readonly PS4='${LINENO}:+ '
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Allow functions that return a string to reach to stdout using FD #3.
exec 3>&1
# --- F U N C T I O N S --------------------------------------------------------
usage() {
cat <<EOF
$0 - Concourse CI in a box deployment tool
Usage: $0 deploy|destroy|restart|le-cert|ss-cert|add-dr-user
Commands:
up
Deploys a local docker Concourse cluster featuring Let's Encrypt site certificate.
down
Destroys the Concourse cluster and preserves runtime configuration and state.
rm
Destroys the Concourse cluster and removes configuration and state.
restart
Re-deploys the containers. Preserves deployment runtime state.
le-cert
Creates Let's Encrypt site certificate.
ss-cert
Create self-signed certificate.
add-dr-user <user>
Grant docker registry access for <user>. Requires running platform.
EOF
}
deploy() {
util.log "Deploy Concourse CI"
concourse.setup
# certificates.create_self_signed "${nginx_dir}/secrets" "${host_fqdn}"
certificates.setup_letsencrypt "${admin_email}" "${nginx_dir}/secrets" "${sites[@]}"
registry.setup
nginx.setup
docker_compose.setup
docker-compose up -d
util.log "Waiting for the Concourse CI cluster to take off"
local _version
while ! _version=$(util.get_concourse_api_version "${host_url}"); do
echo -n '.'; sleep 5
done
util.log "Concourse CI v${_version//\"/} is running"
# Create admin account record, if needed.
grep -q 'admin' "${registry_dir}/passwd" 2>/dev/null || \
registry.add_user 'admin'
local _password
_password="$(grep '^admin\s' "${registry_dir}/passwd" | cut -f 2)"
# shellcheck disable=SC2154
cat >"${deployments_dir}/docker_login" <<EOF
#!/bin/bash -euo pipefail
# Docker registry login script
docker login "${host_url}" -u "admin" -p "${_password}"
EOF
chmod +x "${deployments_dir}/docker_login"
util.run_preview 'Docker registry login:' "${deployments_dir}/docker_login"
# shellcheck disable=SC2154
cat >"${deployments_dir}/ci_login" <<EOF
#!/bin/bash -euo pipefail
# Concourse CI login script
fly -t "${ci_target}" login -u "${ci_username}" -p "${ci_password}" -c "${host_url}"
EOF
chmod +x "${deployments_dir}/ci_login"
util.run_preview 'Concourse login:' "${deployments_dir}/ci_login"
# Wait a bit so that Concourse can figure out if the workers it knows of
# are still around. Favor execution speed vs. accuracy.
for i in $(seq 1 3); do
workers=($(fly -t "${ci_target}" workers | grep stalled | cut -d\ -f1))
if [ -n "${workers[*]}" ]; then
util.log "Prune stalled Concourse workers"
for worker in "${workers[@]}"; do
fly -t "${ci_target}" prune-worker -w "${worker}"
done
break
fi
sleep 3
done
util.log "Concourse CI v${_version//\"/} is up and running at ${host_url}"
}
destroy() {
# Terminates the deployment.
# $1 Indicates if service setup data should be deleted too [Default: false].
local _delete=${1:-}
if [ -s "${script_dir}/docker-compose.yml" ]; then
util.log "Destroy Concourse CI deployment"
docker-compose -f "${script_dir}/docker-compose.yml" down || false
fi
if [ "${_delete}" = '--all' ]; then
util.log "Removing deployments files"
rm -rfv "${deployments_dir}" "${script_dir}/docker-compose.yml" | tail -2
fi
}
# --- M A I N ------------------------------------------------------------------
readonly deployments_dir="${script_dir}/deployments"
readonly db_dir="${deployments_dir}/db"
readonly ghost_dir="${deployments_dir}/ghost"
readonly nginx_dir="${deployments_dir}/nginx"
readonly registry_dir="${deployments_dir}/registry"
readonly web_dir="${deployments_dir}/web"
readonly worker_dir="${deployments_dir}/worker"
readonly admin_email='[email protected]'
readonly host_fqdn='carastan.com'
readonly host_url="https://${host_fqdn}"
readonly sites=("${host_fqdn}" "ci.${host_fqdn}" "git.${host_fqdn}")
readonly ci_target='.'
# Load library modules.
# shellcheck disable=SC1090
source "${script_dir}/lib/certificates.sh"
# shellcheck disable=SC1090
source "${script_dir}/lib/concourse.sh"
# shellcheck disable=SC1090
source "${script_dir}/lib/docker-compose.sh"
# shellcheck disable=SC1090
source "${script_dir}/lib/nginx.sh"
# shellcheck disable=SC1090
source "${script_dir}/lib/registry.sh"
# shellcheck disable=SC1090
source "${script_dir}/lib/util.sh"
case "${1:-}" in
destroy|rm)
destroy --all
;;
down)
destroy
;;
deploy|up)
# TODO: Add command line options for admin_email and host_fqdn.
deploy
;;
restart)
destroy
deploy
;;
le-cert)
util.log "Let's Encrypt certificate generation and renewal requires the" \
"HTTPS port be available. A sudo prompt will be presented to allow the" \
"lego tool bind to port 443."
# Free up the HTTPS port.
destroy
# Specify subject alternative names for each service running on this host.
certificates.create_letsencrypt "${admin_email}" "${sites[@]}"
;;
ss-cert)
certificates.create_self_signed "${HOME}/.certs" "${host_fqdn}"
;;
add-dr-user)
shift
registry.add_user "${1:?Missing value for --add-dr-user}"
;;
help|--help|-h)
usage
;;
*)
if [ -z "${1:-}" ]; then
usage
else
util.log_error "Unsuported command: '${1:-}'. See '$0 --help'."
fi
exit 1
esac