-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstart
executable file
·358 lines (317 loc) · 9.59 KB
/
start
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
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#!/bin/bash
set -e
source scripts/common.sh
source scripts/common-kubectl.sh
function display_usage_and_exit {
bold "Welcome to the all in one GCP Kubernetes GoCD deployment script."
echo ""
echo "Usage: $(basename "$0") <command> [options]"
echo ""
bold "Terraform commands:"
echo " - plan [module] Perform a terraform plan"
echo " - apply-plan [module] Apply a terraform plan"
echo " - destroy [module] [terraform options] Destroy one of these, (please be aware of dependencies)"
echo ""
echo " Available modules: $(ls terraform | tr -s "\n" " ")"
echo ""
bold "Application commands:"
echo " - configure [preprod | prod] Configure an empty kubernetes cluster with basic config"
echo " - deploy [gocd-master | gocd-agents] Deploy either the go master or agents"
echo ""
bold "Utility commands:"
echo " - bootstrap Does all of the above, on a new GCP project"
echo " - nuke Destroy everything in one devastating blow"
echo " - clean Cleans up orphaned firewall rules, disks etc"
echo ""
exit 1
}
function ensure_linux {
OS=$(uname -a | awk '{print $1}')
if [ ! "$OS" = "Linux" ]; then
bold "Sorry, you're not supported!"
echo ""
echo "This script was designed to be run on Linux, not $OS"
echo "There will be differences in the tools which have no been accounted for"
echo ""
echo "Please try using the docker version instead!"
echo "docker run --rm -it stono/ciinabox"
echo ""
echo "Thanks!"
exit 1
fi
}
function ensure_tools {
bold "Checking tool dependencies..."
command_check "kubectl"
command_check "terraform"
command_check "gcloud"
command_check "gsutil"
command_check "gpg2"
command_check "curl"
command_check "pdata" "You can install it with 'npm install -g peopledata-cli'"
EXPECTED_TERRAFORM=0.8.7
EXPECTED_KUBECTL=1.5.3
echo ""
bold "Checking tool versions..."
ACTUAL_TERRAFORM=$(terraform --version | head -n 1 | awk '{print $2}' | cut -c2-)
ACTUAL_KUBECTL=$(kubectl version --client --short | awk '{print $3}' | cut -c2-)
version_check "$ACTUAL_KUBECTL" "$EXPECTED_KUBECTL" "kubectl"
version_check "$ACTUAL_TERRAFORM" "$EXPECTED_TERRAFORM" "terraform"
echo ""
}
function ensure_environment_variables {
bold "Checking environment configuration..."
enforce_arg "LETSENCRYPT_EMAIL" "Lets Encrypt email address"
enforce_arg "STACK_NAME" "This application stack name"
enforce_arg "STATE_BUCKET" "GCS Bucket to store state in"
enforce_arg "NETWORK_NAME" "GCP Private Network Name"
enforce_arg "GCP_PROJECT_NAME" "GCP Project Name"
enforce_arg "PREPROD_CLUSTER_PASSWORD" "The Kubernetes preprod cluster password"
enforce_arg "PROD_CLUSTER_PASSWORD" "The Kubernetes prod cluster password"
enforce_arg "TARGET_REGION" "The primary region"
enforce_arg "TARGET_ZONE_A" "HA Zone 1"
enforce_arg "TARGET_ZONE_B" "HA Zone 2"
enforce_arg "GOCD_USERNAME" "Username to login to GOCD with"
enforce_arg "GOCD_PASSWORD" "Password to login to GOCD with"
enforce_arg "GOCD_AGENT_KEY" "Secure key that agents connect with"
echo ""
}
function ensure_cluster_doesnt_exist {
bold "Checking for cluster..."
if gcloud compute instances list | grep "-$env-" &>/dev/null; then
echo "Error! There appears to be machines associated with $env."
echo "This means you're trying to build a cluster when one is already built"
echo "You're a silly monkey. Destroy it first"
exit 1
else
echo " + Cluster does not exist."
fi
echo ""
}
function ensure_gpg_key {
export GNUPGHOME="$PWD/.tmp/.gnupg"
if [ -f "$GNUPGHOME/agent.asc" ]; then
echo "agent.asc already exists"
return;
else
bold "Generating GPG key..."
mkdir -p "$GNUPGHOME"
chmod 0700 "$GNUPGHOME"
fi
cat > "$GNUPGHOME/agent" <<EOF
%echo Generating a basic OpenPGP key
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: GoCCD
Name-Comment: GoCD Agent GPG Key
Name-Email: [email protected]
Expire-Date: 0
%no-protection
%no-ask-passphrase
%commit
%echo done
EOF
gpg2 --batch --gen-key "$GNUPGHOME/agent"
gpg2 -a --export > "$GNUPGHOME/agent.asc"
gpg2 -a --export-secret-keys >> "$GNUPGHOME/agent.asc"
}
function ensure_ssh_key {
if [ ! -d "./.tmp/.ssh" ]; then
bold "Generating SSH key pair..."
mkdir -p ./.tmp/.ssh
ssh-keygen -b 2048 -t rsa -f "$PWD/.tmp/.ssh/id_rsa" -q -N ""
fi
}
function ensure_in_docker {
if [ ! -f "/.dockerenv" ]; then
bold "You are not running inside docker! I really think you should."
confirm
fi
echo ""
}
function deploy_gocd_master {
bold "Deploying gocd secrets..."
echo -n $(htpasswd -nb -s $GOCD_USERNAME $GOCD_PASSWORD | xargs) > ./.tmp/users
ensure_secret_file "gocd.users" "users" "./.tmp/users"
ensure_secret_literal "gocd.goagent-key" "key" "$GOCD_AGENT_KEY"
ensure_ssh_key
delete_secret "gocd.ssh"
kube create secret generic "gocd.ssh" --from-file=ssh-privatekey=.tmp/.ssh/id_rsa --from-file=ssh-publickey=.tmp/.ssh/id_rsa.pub
echo ""
bold "Deploying gocd master..."
pdata app deploy "$ROOT/kubernetes/master.pod.yml"
echo ""
bold "Deploying gocd master service..."
pdata app deploy "$ROOT/kubernetes/master.service.yml"
echo ""
bold "Deploying gocd NGINX..."
pdata app deploy "$ROOT/kubernetes/nginx.pod.yml"
echo ""
export GOCD_MASTER_IP=$(gcloud compute addresses describe $STACK_NAME-gocd | grep "address:" | awk '{print $2}' | xargs)
bold "Deploying gocd NGINX service with static ip: $GOCD_MASTER_IP..."
pdata app deploy "$ROOT/kubernetes/nginx.service.yml"
echo ""
GOCD_URL="https://$GOCD_MASTER_IP/go"
wait_for_url "$GOCD_URL"
bold "GoCD is online at: $GOCD_URL!"
}
function deploy_gocd_agent {
echo "Ensuring GPG key..."
ensure_gpg_key
ensure_secret_file "goagent.gpg-key" "agent.asc" "./.tmp/.gnupg/agent.asc"
echo ""
bold "Deploying gocd preprod agents..."
export GOCD_AGENT_ENV=preprod
export AGENT_ADDITIONAL_ENV=",integration,infrastructure"
pdata app deploy "$ROOT/kubernetes/agent.pod.yml"
echo ""
bold "Deploying gocd prod agents..."
export GOCD_AGENT_ENV=prod
export AGENT_ADDITIONAL_ENV=",infrastructure"
pdata app deploy "$ROOT/kubernetes/agent.pod.yml"
echo ""
bold "GoCD agents deployed!"
}
function plan_build {
bold "Planning the build..."
$ROOT/scripts/infra plan "$1"
}
function plan_destroy {
bold "Planning the destruction..."
$ROOT/scripts/infra plan_destroy $*
}
function terraform_apply {
bold "Applying terraform plan..."
$ROOT/scripts/infra apply "$1"
}
function do_kube_environment {
check_presence "$env"
bold Configuring env...
$ROOT/scripts/configure-env "$*"
}
function do_infra {
env=$1
check_presence "$env"
plan_build "$env"
confirm
terraform_apply "$env"
if [ "$env" = "preprod" ] || [ "$env" = "prod" ]; then
do_kube_environment "$env"
fi
}
function do_deploy {
app=$1
check_presence "$app"
acquire_credentials_for_cluster "${STACK_NAME}-preprod"
if [ "$app" = "gocd-master" ]; then
deploy_gocd_master
elif [ "$app" = "gocd-agents" ]; then
deploy_gocd_agent
else
display_usage_and_exit
fi
}
function do_kube_destroy {
env=$1
check_presence "$env"
set +e
acquire_credentials_for_cluster "${STACK_NAME}-${env}"
if [ ! "$?" = "0" ]; then
echo " - Unable to get cluster credentials"
else
set -e
echo "Deleting all namespaces and resources in ${STACK_NAME}-${env}"
for ns in $(kubectl get namespaces --no-headers | awk '{print $1}'); do
if [ ! "$ns" = "kube-system" ]; then
kube --namespace="$ns" delete ingress --all --cascade=true --now
kube --namespace="$ns" delete services --all --cascade=true --now
kube --namespace="$ns" delete statefulsets --all --cascade=true --now
kube --namespace="$ns" delete deployments --all --cascade=true --now
fi
done
fi
}
function do_infra_destroy {
env=$1
check_presence $env
plan_destroy $*
confirm
terraform_apply "$env"
}
function do_infra_cleanup {
./scripts/cleanup-networking
./scripts/cleanup-disks
}
command="${1:-}"
env="${2:-}"
args="${@:3}"
export KUBECTL_NAMESPACE=default
mkdir -p .tmp
ensure_linux
ensure_in_docker
ensure_tools
ensure_environment_variables
ensure_gcloud_configuration
case "$command" in
plan)
plan_build "$env"
exit 0
;;
apply-plan)
terraform_apply "$env"
;;
deploy)
do_deploy "$env"
exit 0
;;
destroy)
if [ "$env" = "preprod" ] || [ "$env" = "prod" ]; then
do_kube_destroy "$env"
fi
do_infra_destroy "$env" "$args"
do_infra_cleanup
exit 0
;;
clean)
do_infra_cleanup
exit 0
;;
configure)
if [ "$env" = "preprod" ] || [ "$env" = "prod" ]; then
do_kube_environment "$env"
fi
exit 0
;;
bootstrap)
ensure_cluster_doesnt_exist
do_infra "gocd"
do_infra "networking"
do_infra "preprod"
do_infra "prod"
do_deploy "gocd-master"
do_deploy "gocd-agents"
echo ""
bold "Bootstrap complete, have fun on GoCD at $GOCD_URL"
exit 0
;;
nuke)
do_kube_destroy "prod"
do_kube_destroy "preprod"
do_infra_destroy "prod"
do_infra_destroy "preprod"
do_infra_cleanup
do_infra_destroy "networking"
# do_infra_destroy "gocd"
echo "[gocd] has been excluded, as this contains your gocd config"
echo "in order to delete that, manually run destroy gocd"
echo ""
bold "Nuke complete."
exit 0
;;
*)
display_usage_and_exit
;;
esac
exit 0