-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy path.env.sh.post
395 lines (337 loc) · 15.5 KB
/
.env.sh.post
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#!/bin/bash
# This needs to be added AFTERWARDS to your .env.sh.
# It contains non-customizeable addons which are needed by ALL your scripts
# in case you call skaffold dev it should then just work: https://skaffold.dev/docs/environment/image-registries/
export SKAFFOLD_DEFAULT_REPO="${REGION}-docker.pkg.dev/$PROJECT_ID/$ARTIFACT_REPONAME"
# This is the LONG path to your Artifact Registry, worth writing once for all:
export ARTIFACT_LONG_REPO_PATH="${REGION}-docker.pkg.dev/$PROJECT_ID/$ARTIFACT_REPONAME"
export DEVCONSOLE="https://console.cloud.google.com"
export BASH_VERSION="$(bash --version |head -1 | cut -d' ' -f 4)"
# calculate how much time it takes
function get_latest_successful_release_by_pipeline() {
PIPELINE="$1"
# BUG found: the LIMIT 1 limits BEFORE the filter, so if the first is broken it doesnt return anything!
gcloud deploy releases list --delivery-pipeline "$PIPELINE" --filter renderState=SUCCEEDED \
--format="value(name.split())" \
--region "$CLOUD_DEPLOY_REGION" \
--sort-by=~createTime --limit 100 |
cut -d';' -f 8 |
head -1
}
function red() {
echo -en "\033[1;31m$*\033[0m\n"
}
function green() {
echo -en "\033[1;32m$*\033[0m\n"
}
function white() {
echo -en "\033[1;37m$*\033[0m\n"
}
function yellow() {
echo -en "\033[1;33m$*\033[0m\n"
}
function _error() {
echo "[$(red ERROR)] $*"
}
# Executed by ALL scripts in the end.
function _allgood_post_script() {
set +x
echo "[$(green $0)] All good on $(date +%Y%m%d-%H%M%S)"
#touch .executed_ok."$(basename $0)".touch
# Also put the version which made that happen just for debug :)
green "==========================================="
green "== Script END (👍): '$(basename $0)'"
green "==========================================="
cat ./VERSION > .executed_ok."$(basename $0)".touch
}
function _echodo() {
(echo -en "[echodo] " ; echo "$@" )>&2
"$@"
}
function _fatal() {
echo "[FATAL] $*" >&2
exit 42
}
function _filter_k8s_errors() {
egrep -v 'WARNING: the gcp auth plugin is deprecated in v1.22|To learn more, consult https:' # W0816
}
function _colorize_kubectl_output() {
bin/rcg error RED |
bin/rcg Error RED |
bin/rcg created GREEN |
bin/rcg configured GREEN |
bin/rcg unchanged YELLOW
}
function _script_start_verbose() {
# only show header for proper ./ scripts.
if echo "$0"| grep -q "bin/" ; then
echo 'skip for bin/ ..' >&2
else
# proper scirpt
white "========================================"
#white "== Script START: '$(basename $0)' (on $(date))"
white "== Script START: '$0' (on $(date +%Y%m%d-%H%M%S))"
white "========================================"
# if DEBUG is enabled I'll write somethign more :)
if [ "true" = "$DEBUG" ]; then
PREPEND="[DEBUG] "
_deb "Hey! 'DEBUG' ENV var is set to true! => Please change to DEBUG=FALSE in your .env.sh to remove this. Some impotant fields:"
_deb "PROJECT_ID: '$PROJECT_ID'"
_deb "ACCOUNT: '$ACCOUNT'"
_deb "GITHUB_REPO_OWNER: '$GITHUB_REPO_OWNER'"
_deb "GCLOUD_REGION: '$GCLOUD_REGION'"
_deb "GKE_REGION: '$GKE_REGION' (defaults to the above but you can change it)"
_deb "ARTIFACT_LONG_REPO_PATH: '$ARTIFACT_LONG_REPO_PATH'"
#_deb "ENABLE_APP03: '$ENABLE_APP03'"
_deb "BASH_VERSION: '$BASH_VERSION'"
fi
fi
}
# TODO(ricc): iterate through all clusters. I dont want to be a hypocrite, these ENVs are not used as names are hardcoded everywhere :/
# Needed for the script 11 for GKE magic setup
export CLUSTER_DEV="cicd-dev"
# The two clusters you use for Traffiuc Splitting. Id unsure dont change.
export CLUSTER_1="cicd-canary"
export CLUSTER_2="cicd-prod"
export GKE_REGION="$REGION"
# GKE CONTEXTS
# GKE_DEV_CLUSTER_CONTEXT="gke_cicd-platinum-test001_europe-west6_cicd-dev"
# GKE_CANARY_CLUSTER_CONTEXT="gke_cicd-platinum-test001_europe-west6_cicd-canary"
# GKE_PROD_CLUSTER_CONTEXT="gke_cicd-platinum-test001_europe-west6_cicd-prod"
GKE_DEV_CLUSTER_CONTEXT="gke_${PROJECT_ID}_${GCLOUD_REGION}_cicd-dev"
GKE_CANARY_CLUSTER_CONTEXT="gke_${PROJECT_ID}_${GCLOUD_REGION}_cicd-canary"
GKE_PROD_CLUSTER_CONTEXT="gke_${PROJECT_ID}_${GCLOUD_REGION}_cicd-prod"
# if it works i do it on other 2 two :)
alias kubectl-on-dev="kubectl --context=$GKE_DEV_CLUSTER_CONTEXT"
alias kubectl-on-canary="kubectl --context=$GKE_CANARY_CLUSTER_CONTEXT"
alias kubectl-on-prod="kubectl --context=$GKE_PROD_CLUSTER_CONTEXT"
# ARGS:
# - MY_TARGET: %w{dev canary prod }
function _kubectl_on_target() {
MY_TARGET="$1" # dev, canary, prod
shift
kubectl --context="gke_${PROJECT_ID}_${GCLOUD_REGION}_cicd-${MY_TARGET}" "$@"
}
function _kubectl_on_canary() {
kubectl --context="$GKE_CANARY_CLUSTER_CONTEXT" "$@"
}
function _kubectl_on_prod() {
kubectl --context="$GKE_PROD_CLUSTER_CONTEXT" "$@"
}
function _kubectl_on_dev() {
echo "Note the namespace in DEV you have both DEV(cicd-dev) and STAGING(default)" >&2
kubectl --context="$GKE_DEV_CLUSTER_CONTEXT" "$@"
}
function _prepend() {
while read L ; do
echo "$*$L"
done
}
function _kubectl_on_both_canary_and_prod() {
kubectl --context=$GKE_CANARY_CLUSTER_CONTEXT "$@" | _prepend "[CANA] "
kubectl --context=$GKE_PROD_CLUSTER_CONTEXT "$@" | _prepend "[PROD] "
}
# Returns a MINI_REGION :) Must be lowercase unfortunately.
function _shorten_region() {
REGION="$1"
echo "$REGION" |
# abbreviating continents
sed -e 's/europe/eu/g' |
sed -e 's/asia/as/g' |
sed -e 's/southamerica/sa/g' |
# abbreviating cardinals
sed -e 's/north/n/g' |
sed -e 's/east/e/g' |
sed -e 's/south/s/g' |
sed -e 's/west/w/g' |
cat
}
#############################
# solutions 1-3
#############################
# MultiAppK8sRefactoring: second script (wrapper in .env.sh): `smart_apply_k8s_templates`
# This is a helper function which is a BASH version of kustomize to render/hydrate templates:
# TOSDO(ricc): refactoer with envsubst: https://hughesadam87.medium.com/dead-simple-include-env-variables-in-kubernetes-deployment-yaml-1c0e8f859fde
function smart_apply_k8s_templates() {
TEMPLATES_BASEDIR="$1"
COMMON_ENVFUNCTION_TEMPLATING_VER="2.0env"
mkdir -p "$TEMPLATES_BASEDIR/out/"
white "smart_apply_k8s_templates(): BEGIN on $TEMPLATES_BASEDIR/ and APP=$APP_NAME"
for TEMPLATE_FILE in "$TEMPLATES_BASEDIR/templates/"*.template.yaml ; do
DEST_FILE=$(echo "$TEMPLATE_FILE" | sed s:/templates/:/out/: | sed -e s/.template.yaml/.yaml/)
echo "Hydrating template '$TEMPLATE_FILE' [v.$COMMON_ENVFUNCTION_TEMPLATING_VER] into this tmp out/ file: $DEST_FILE:"
(
echo '###########################################################'
echo "# Created by $0 v$COMMON_ENVFUNCTION_TEMPLATING_VER "
echo "# on `date` on `hostname`"
echo "# TMPL DIR: $TEMPLATES_BASEDIR"
echo "# Edit at your own risk as it'll be soon overwritten. Maybe."
echo '###########################################################'
cat "$TEMPLATE_FILE" | egrep -v '^#' # remove comments
)|
sed -e "s/__MY_PROJECT_ID__/$PROJECT_ID/g" |
sed -e "s/__PREFIX__/$PREFIX/g" |
sed -e "s/__APP_NAME__/$APP_NAME/g" |
sed -e "s/__APPNAME__/$APP_NAME/g" | # I know what you thinking.. duplication is confusing.
sed -e "s/__APP_IMAGE__/$K8S_APP_IMAGE/g" |
sed -e "s/__K8S_APP_IMAGE__/$K8S_APP_IMAGE/g" | # I know...
sed -e "s/__K8S_APP_SELECTOR__/$K8S_APP_SELECTOR/g" | # I know what you thinking..
sed -e "s/__MY_REGION__/$REGION/g" |
sed -e "s/__MY_DOMAIN__/$MY_DOMAIN/g" |
#sed -e "s/__MY_VERSION_/$CLOUD_DEPLOY_TEMPLATING_VER/g" |
#egrep 'cluster|VER' |
tee "$DEST_FILE" >/dev/null
# Showing errors.
if cat "$DEST_FILE" | grep "__" ; then
red "Sorry, not all variables have been substituted in '$DEST_FILE'"
grep "__" $DEST_FILE
exit 142
fi
# Showing errors.
# r34moved: | egrep -- -v '---'
if cat "$DEST_FILE" | grep -- "--" ; then
red "Sorry, some variables seem empty (-- instead of -something-) in '$DEST_FILE'"
grep -- "--" "$DEST_FILE"
exit 143
fi
done
}
# this fixes also the multidir access which I need for ILB which has 2 different configs per cluster
function smart_apply_k8s_templates_with_envsubst() {
TEMPLATES_BASEDIR="$1"
MANIFESTS_OUTDIR="${2:-../out/}"
COMMON_ENVFUNCTION_TEMPLATING_VER="3.0envsubst"
mkdir -p "$MANIFESTS_OUTDIR"
for TEMPLATE_FILE in $TEMPLATES_BASEDIR/*.template.yaml ; do
DEST_FILE="$MANIFESTS_OUTDIR/$(basename "$TEMPLATE_FILE" | sed -e s/.template.yaml/.yaml/)"
echo -n "[$(basename $0)] " ; \
white "Hydrating template '$TEMPLATE_FILE' [v.$COMMON_ENVFUNCTION_TEMPLATING_VER] into this tmp out/ file: $DEST_FILE:"
(
echo '###########################################################'
echo "# Created by $(basename $0) v$COMMON_ENVFUNCTION_TEMPLATING_VER"
echo "# on `date` on `hostname`"
echo "# TMPL DIR: $TEMPLATES_BASEDIR"
echo '# TEST DOESNT_EXIST: ${DOESNT_EXIST}'
echo "# Edit at your own risk as it'll be soon overwritten. Maybe."
echo '###########################################################'
cat "$TEMPLATE_FILE" | egrep -v '^#' # remove comments
)|
envsubst | # Thanks Roberto
tee "$DEST_FILE" >/dev/null
# Showing errors.
if cat "$DEST_FILE" | fgrep '${' ; then
red "Sorry, not all variables have been substituted in '$DEST_FILE'"
fgrep '${' $DEST_FILE
exit 42
fi
done
}
function _gcloud_container_fleet_memberships_register_if_needed() {
CLUSTER="$1"
#echo Lets see if I need to do it:
gcloud container fleet memberships describe "$CLUSTER" >/dev/null &&
green "Fleet membership exists: '$CLUSTER'" ||
gcloud container fleet memberships register "$CLUSTER" \
--gke-cluster "$GCLOUD_REGION/$CLUSTER" \
--enable-workload-identity \
--project="$PROJECT_ID" --quiet
}
export DEFAULT_SHORT_REGION="$(_shorten_region "$REGION")" # you could shorten something else, that is :)
########################################
# SOLUTIONS
# solution 0/3 path (ILB)
export GKE_SOLUTION0_ILB_SETUP_DIR="k8s/solution3-multi-cluster-ilb-setup"
# Note: GKE_SOLUTION0_ILB_SETUP_DIR Solution0 == Solution3
############
# Solution 1
export GKE_SOLUTION1_XLB_PODSCALING_SETUP_DIR="k8s/solution1-GatewayAPI-pod-scaling-GXLB"
############
# Solution 2
#export FWD_RULE="${URLMAP_NAME_MTSUFFIX}-fwdrule-obsolete" # TODO(obsolete this)
export FWD_RULE_MTSUFFIX="${URLMAP_NAME_MTSUFFIX}-frmt" # FwdRule Multitenant, see https://github.com/palladius/clouddeploy-platinum-path/issues/14
export GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR="k8s/solution2-xlb-gfe3-traffic-split/"
export DFLT_SOL2_SERVICE_CANARY="sol2-svc-canary" # do NOT change this or it will break logic! (*)
export DFLT_SOL2_SERVICE_PROD="sol2-svc-prod" # do NOT change this or it will break logic! (*)
# In scripts 15/16 it implies it's "sol2-svc-${TypeOfTraffic}" and I dont want to refactor this even more in Bash :)
export PROD_PERCENTAGE="78" # 78
export CANARY_PERCENTAGE="$(( 100 - $PROD_PERCENTAGE ))" # 22
function solution2_kubectl_teardown() {
smart_apply_k8s_templates "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR"
# https://stackoverflow.com/questions/1835943/how-to-determine-function-name-from-inside-a-function eheheh
echo "${FUNCNAME[0]}(): 1 applying to Canary"
bin/kubectl-canary delete -f "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR/out/"
echo "${FUNCNAME[0]}(): 2 applying the same to Prod (which might be redundant)"
bin/kubectl-prod delete -f "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR/out/"
}
# Used both by script 15 and 16, sorry...
# Note you need to keep this script in sync with the above.
function solution2_kubectl_apply () { # was: solution2_tear_up_k8s
smart_apply_k8s_templates "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR"
# If you changed some name and you get IMMUTABLE error, try to destroy the same resource before:
# eg, bin/kubectl-prod delete deployments/app01-sol2-svc-canary
echo "${FUNCNAME[0]}(): 1 applying to Canary"
bin/kubectl-canary apply -f "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR/out/"
echo "${FUNCNAME[0]}(): 2 applying the same to Prod (which might be redundant)"
bin/kubectl-prod apply -f "$GKE_SOLUTION2_ENVOY_XLB_TRAFFICSPLITTING_SETUP_DIR/out/"
}
function _urlmap_name_by_app() {
APP_NAME="$1"
echo "${APP_NAME}-${URLMAP_NAME_MTSUFFIX}-sol2"
}
function _fwd_rule_by_app() {
APP_NAME="$1"
echo "${APP_NAME}-${FWD_RULE_MTSUFFIX}-sol2"
}
############
# solution 3 ==> see solution 0 above
# /solutions
#############################
# Adds local bin/ to PATH and takes precedence to make sure scripts like `proceed_if_error_matches` are locally sourced :)
export PATH=$(pwd)/bin/:$PATH
DEBUG_PREPEND="[DEBUG] "
function _deb() {
if [ "true" = "$DEBUG" ]; then
echo "$(white "$DEBUG_PREPEND")$*"
fi
}
#export GCLOUD_CONFIG='cicd-platinum' # changeme
#export GCLOUD_ZONE='europe-west6-c' # changeme and make sure ZONE belongs to REGION
# declaring Hash for the Two applications :)
# TODO bash version. On My mac, bad v (<5) is:
# $ bash --version
# GNU bash, version 3.2.57(1)-release (arm64-apple-darwin21)
# Bash 4 needed: https://stackoverflow.com/questions/1494178/how-to-define-hash-tables-in-bash
function _check_your_os_supports_bash_arrays() {
BASH_MAJOR_VERSION=$(echo "$BASH_VERSION" | cut -f 1 -d'.')
if [ $BASH_MAJOR_VERSION \> '3' ];
then
echo "BASH VERSION IS $BASH_MAJOR_VERSION: all good.";
else
_fatal "Sorry, bash v.$BASH_MAJOR_VERSION doesnt support natively Hashes (v$BASH_VERSION). We cant run the script. Use Linux or 'brew install bash' and call this script from brew bash (for Ricc its /opt/homebrew/opt/bash/bin/bash)";
fi
}
# requires BASH v4 or more.
declare -A AppsInterestingHash
AppsInterestingHash["app01-SELECTOR"]="app01-kupython"
AppsInterestingHash["app02-SELECTOR"]="app02-kuruby"
AppsInterestingHash["app03-SELECTOR"]="app02-kunode"
AppsInterestingHash["app01-IMAGE"]="skaf-app01-python-buildpacks" # BuildPacks
AppsInterestingHash["app02-IMAGE"]="ricc-app02-kuruby-skaffold" # dockerized
AppsInterestingHash["app03-IMAGE"]="aablsk-app03-kunode-skaffold" # dockerized
# 🔥 emojis for all apps.
AppsInterestingHash["app01-EMOJI"]="🐍" # python. Just perfect.
AppsInterestingHash["app02-EMOJI"]="💎" # a ruby gem, should be red but no ruby available.
AppsInterestingHash["app03-EMOJI"]="🧊" # a Node, should be a GREEN sube.
AppsInterestingHash["app01-SERVICE_PORT"]="8080"
AppsInterestingHash["app02-SERVICE_PORT"]="8080"
AppsInterestingHash["app03-SERVICE_PORT"]="80"
# # egrep string to find interesting stuff.. should be useless soon once every version has statusz, after 2.0ish versions..
# # This is now OBSOLETE :/
# AppsInterestingHash["app01-WEB_EGREP"]="tatusz" # TODO "App01 ("
# AppsInterestingHash["app02-WEB_EGREP"]="pp02|statusz" # dunno??
# AppsInterestingHash["app02-WEB_EGREP"]="pp03" # dunno??
# In case you SOURCE the .env.sh you get for free a yellow indicator of project id.
# Formidable when you're testing stuff in multiple projects :)
export PS1="\[\e]0;${PROJECT_ID:-MissingProject}\a\]\u@\h:\[\033[1;34m\]\w$([[ -n $PROJECT_ID ]] && printf " \[\033[1;33m\](%s)" "${PROJECT_ID}" )\[\033[00m\]$ "
#_check_your_os_supports_bash_arrays
_script_start_verbose