Refactor code into separate functions

This commit is contained in:
Sergey Dudoladov 2018-01-29 16:59:25 +01:00
parent 08567e7be3
commit 9732ec6988
1 changed files with 188 additions and 111 deletions

View File

@ -1,156 +1,233 @@
#!/bin/bash
#!/usr/bin/env bash
#
# Deploy a Postgres operator to a minikube aka local Kubernetes cluster
# Optionally re-build the operator binary beforehand to test local changes
# unofficial bash strict mode w/o the -e option
# -e breaks "eval $cmd" in the retry function
set -uo pipefail
# enable unofficial bash strict mode
set -o errexit
set -o nounset
set -o pipefail
IFS=$'\n\t'
function retry(){ # timeouts after 1 minutes
cmd="$1"
retryMsg="$2"
readonly PATH_TO_LOCAL_OPERATOR_MANIFEST="/tmp/local-postgres-operator.yaml"
readonly PATH_TO_PORT_FORWARED_KUBECTL_PID="/tmp/kubectl-port-forward.pid"
readonly LOCAL_PORT="8080"
readonly OPERATOR_PORT="8080"
# minikube needs time to create resources,
# so the script retries actions until all the resources become available
function retry(){
# errexit may break "eval $cmd", so we disable it temporarily
set +o errexit
local cmd="$1"
local retry_msg="$2"
# times out after 1 minute
for i in {1..20}; do
if eval "$cmd"; then
set -o errexit # enable again
return 0
fi
echo "$retryMsg"
echo "$retry_msg"
sleep 3
done
>2& echo "The command $cmd timed out"
return 1
}
function build_operator_binary(){
make tools > /dev/null 2>&1 &&
make deps > /dev/null 2>&1 &&
make local > /dev/null 2>&1
function build_operator_binary(){
# redirecting stderr greatly reduces non-informative output during normal builds
echo "Build operator binary (stderr redirected to /dev/null)..."
make tools > /dev/null 2>&1
make deps > /dev/null 2>&1
make local > /dev/null 2>&1
}
# the fastest way to run your docker image locally is to reuse the docker from minikube.
function deploy_self_built_image() {
echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== "
echo "Build operator binary (stderr redirected to /dev/null)..."
build_operator_binary
# set docker env vars so that docker can talk to the Docker daemon inside the minikube VM
# the fastest way to run your docker image locally is to reuse the docker from minikube.
# set docker env vars so that docker can talk to the Docker daemon inside the minikube
eval $(minikube docker-env)
# image tag consists of a git tag or a unique commit prefix
# and the "-dev" suffix if there are uncommited changes in the working dir
export TAG=$(git describe --tags --always --dirty="-dev")
TAG=$(git describe --tags --always --dirty="-dev")
export TAG
# build the image
echo "Build the operator Docker image (stderr redirected to /dev/null)..."
make docker > /dev/null 2>&1
# update the tag in the postgres operator conf
# since the image with this tag is already present on the machine,
# since the image with this tag already exists on the machine,
# docker should not attempt to fetch it from the registry due to imagePullPolicy
file="/tmp/local-postgres-operator.yaml"
sed -e "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$file"
sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST"
retry "kubectl create -f \"$file\"" "attempt to create $file resource"
retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource"
}
function display_help(){
echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]"
}
# parse options
should_build_operator=false
while true
do
case "${1:-''}" in # if 1st is usnet, use the mety string as a default value
-h | --help)
display_help
exit 0
;;
-r | --rebuild-operator)
should_build_operator=true
shift 2
break
;;
--) shift
break;;
*) break
;;
esac
done
echo "==== CLEAN UP PREVIOUS RUN ==== "
status=$(minikube status --format "{{.MinikubeStatus}}")
if [ "$status" = "Running" ] || [ "$status" = "Stopped" ]; then
echo "Delete the existing local cluster so that we can cleanly apply resources from scratch..."
minikube delete
fi
# the kubectl process does the port-forwarding between operator and local ports
# we restart the process to bind to the same port again (see end of script)
if [ -e /tmp/kubectl-port-forward.pid ]; then
function clean_up(){
pid=$(cat /tmp/kubectl-port-forward.pid)
# the process will die if a minikube is stopped manually between two invocations of the script
if ps --pid "$pid" > /dev/null; then
echo "Kill the kubectl process responsible for port forwarding for minikube so that we can re-use the same ports for forwarding later..."
kill "$pid"
echo "==== CLEAN UP PREVIOUS RUN ==== "
local status
status=$(minikube status --format "{{.MinikubeStatus}}" || true)
if [[ "$status" = "Running" ]] || [[ "$status" = "Stopped" ]]; then
echo "Delete the existing local cluster so that we can cleanly apply resources from scratch..."
minikube delete
fi
rm /tmp/kubectl-port-forward.pid
fi
if [[ -e "$PATH_TO_LOCAL_OPERATOR_MANIFEST" ]]; then
rm --verbose "$PATH_TO_LOCAL_OPERATOR_MANIFEST"
fi
# the kubectl process does the port-forwarding between operator and local ports
# we restart the process to bind to the same port again (see end of script)
if [[ -e "$PATH_TO_PORT_FORWARED_KUBECTL_PID" ]]; then
local pid
pid=$(cat "$PATH_TO_PORT_FORWARED_KUBECTL_PID")
# the process dies if a minikube stops between two invocations of the script
if ps --pid "$pid" > /dev/null 2>&1; then
echo "Kill the kubectl process responsible for port forwarding for minikube so that we can re-use the same ports for forwarding later..."
kill "$pid"
fi
rm --verbose /tmp/kubectl-port-forward.pid
echo "==== START MINIKUBE ==== "
echo "May take a few minutes ..."
minikube start
kubectl config set-context minikube
fi
}
echo "==== MINIKUBE STATUS ==== "
minikube status
function start_minikube(){
echo "==== START MINIKUBE ==== "
echo "May take a few minutes ..."
minikube start
kubectl config set-context minikube
echo "==== START OPERATOR ==== "
# the order of files is significant
for file in "configmap.yaml" "serviceaccount.yaml"
do
retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource"
done
echo "==== MINIKUBE STATUS ==== "
minikube status
}
function start_operator(){
echo "==== START OPERATOR ==== "
echo "Certain operations may be retried multiple times..."
# the order of resource initialization is significant
local file
for file in "configmap.yaml" "serviceaccount.yaml"
do
retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource"
done
if [[ "$should_build_operator" = true ]]; then
deploy_self_built_image
else
retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource"
fi
local msg="Wait for the postgresql custom resource definition to register..."
local cmd="kubectl get crd | grep --quiet 'postgresqls.acid.zalan.do'"
retry "$cmd" "$msg "
kubectl create -f manifests/complete-postgres-manifest.yaml
}
function forward_ports(){
echo "==== FORWARD OPERATOR PORT $OPERATOR_PORT TO LOCAL PORT $LOCAL_PORT ===="
local operator_pod
operator_pod=$(kubectl get pod -l name=postgres-operator -o jsonpath={.items..metadata.name})
# runs in the background to keep current terminal responsive
# stdout redirect removes the info message about forwarded ports; the message sometimes garbles the cli prompt
kubectl port-forward "$operator_pod" "$LOCAL_PORT":"$OPERATOR_PORT" &> /dev/null &
pgrep --newest "kubectl" > "$PATH_TO_PORT_FORWARED_KUBECTL_PID"
}
function check_health(){
echo "==== RUN HEALTH CHECK ==== "
local check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null"
echo "Command for checking: $check_cmd"
local check_msg="Wait for port forwarding to take effect"
if retry "$check_cmd" "$check_msg"; then
echo "==== SUCCESS: OPERATOR IS RUNNING ==== "
echo "To stop it cleanly, run 'minikube delete'"
else
>2& echo "==== FAILURE: OPERATOR DID NOT START OR PORT FORWARDING DID NOT WORK"
>2& echo "This *might* have left the minikube VM image in inconsistent state."
exit 1
fi
}
function main(){
if ! [[ $(basename $PWD) == "postgres-operator" ]]; then
echo "Please execute the script only from the root directory of the Postgres opepator repo."
exit 1
fi
trap "echo 'If you observe issues with minikube VM not starting/not proceeding, consider deleting the .minikube dir and/or rebooting before re-running the script'" EXIT
local should_build_operator=false
while true
do
# if 1st param is unset, use the empty string as a default value
case "${1:-}" in
-h | --help)
display_help
exit 0
;;
-r | --rebuild-operator)
should_build_operator=true
shift 2 || true
break
;;
--) shift
break;;
*) break
;;
esac
done
clean_up
start_minikube
start_operator should_build_operator
forward_ports
check_health
exit 0
}
if [ "$should_build_operator" = true ]; then
deploy_self_built_image
else
retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource"
fi
msg="Wait for the postgresql custom resource definition to register..."
cmd="kubectl get crd | grep --quiet 'postgresqls.acid.zalan.do'"
retry "$cmd" "$msg "
kubectl create -f manifests/complete-postgres-manifest.yaml
localPort="8080"
operatorPort="8080"
echo "==== FORWARD OPERATOR PORT $operatorPort TO LOCAL PORT $localPort ===="
operatorPod=$(kubectl get pod -l name=postgres-operator -o jsonpath={.items..metadata.name})
# runs in the background to keep current terminal responsive
# stdout redirect removes the info message about forwarded ports; the message sometimes garbles the cli prompt
kubectl port-forward "$operatorPod" "$localPort":"$operatorPort" &> /dev/null &
pgrep --newest "kubectl" > /tmp/kubectl-port-forward.pid
echo "==== RUN HEALTH CHECK ==== "
checkCmd="curl --location --silent http://127.0.0.1:$localPort/clusters &> /dev/null"
echo "Command for checking: $checkCmd"
checkMsg="Wait for port forwarding to take effect"
if retry "$checkCmd" "$checkMsg" ; then
echo "==== SUCCESS: OPERATOR IS RUNNING ==== "
echo "To stop it cleanly, run 'minikube delete'"
else
echo "==== FAILURE: OPERATOR DID NOT START OR PORT FORWARDING DID NOT WORK"
echo "This *might* have left the minikube VM image in inconsistent state."
echo "If you observe strange issues, try deleting .minikube dir and re-running the script"
exit 1
fi
main "$@"