From d707bba2fbd8430f2a0e11c919bc279b0bc6cfcd Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 18 Jan 2018 13:48:38 +0100 Subject: [PATCH 01/10] Add a script to run operator locally --- run_locally.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 run_locally.sh diff --git a/run_locally.sh b/run_locally.sh new file mode 100755 index 000000000..03d6dee47 --- /dev/null +++ b/run_locally.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +set -uo pipefail +IFS=$'\n\t' + +# timeouts after 3 minutes +function retry(){ + cmd="$1" + retryMsg="$2" + for i in {1..90}; do + eval "$cmd" + if [ $? -eq 0 ]; then + return 0 + fi + echo "$retryMsg" + sleep 2 + done + + return 1 +} + + +echo "==== CLEAN UP PREVIOUS RUN ==== " + +status=$(minikube status --format "{{.MinikubeStatus}}") +if [ "$status" = "Running" ]; then + minikube delete +fi + +# the kubectl process does the port-forwarding between operator and local ports +# we restart the process to be able to bind to the same port again (see end of script) +echo "Kill kubectl process to re-init port-forwarding for minikube" +kubepid=$(pidof "kubectl") +if [ $? -eq 0 ]; then + kill "$kubepid" +fi + + +echo "==== START MINIKUBE ==== " +echo "May take a few minutes ..." +minikube start +kubectl config set-context minikube + +echo "==== MINIKUBE STATUS ==== " +minikube status + +echo "==== START OPERATOR ==== " +# the order of files is significant +for file in "configmap.yaml" "serviceaccount.yaml" "postgres-operator.yaml" +do + retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" +done + +msg="Wait for the postgresql custom resource definition to register." +cmd="kubectl get crd | grep 'postgresqls.acid.zalan.do' &> /dev/null" +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 +# 1> redirects stdout to remove the info message about forwarded ports; the message sometimes garbles the cli prompt +kubectl port-forward "$operatorPod" "$localPort":"$operatorPort" 1> /dev/null & + + +echo "==== RUN HEALTH CHECK ==== " +checkCmd="curl -L http://127.0.0.1:$localPort/clusters &> /dev/null" +checkMsg="Wait for port forwarding to take effect" +retry "$checkCmd" "$checkMsg" + +if [ $? -eq 0 ]; then + echo "==== SUCCESS: OPERATOR IS RUNNING ==== " +else + echo "Operator did not start or port forwarding did not work" + exit 1 +fi + + + + From 2cd6e9d9898c7c0fd2860c560625b6859fc925ff Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 25 Jan 2018 15:24:30 +0100 Subject: [PATCH 02/10] respond to code review --- run_locally.sh | 60 ++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/run_locally.sh b/run_locally.sh index 03d6dee47..f7c6973fe 100755 --- a/run_locally.sh +++ b/run_locally.sh @@ -1,44 +1,50 @@ #!/bin/bash -set -uo pipefail +# unofficial bash strict mode w/o the -e option +# -e breaks "eval $cmd" in the retry function +set -uo pipefail IFS=$'\n\t' -# timeouts after 3 minutes -function retry(){ +function retry(){ # timeouts after 1 minutes cmd="$1" retryMsg="$2" - for i in {1..90}; do + for i in {1..20}; do eval "$cmd" if [ $? -eq 0 ]; then - return 0 + return 0 fi echo "$retryMsg" - sleep 2 + sleep 3 done - + return 1 } - echo "==== CLEAN UP PREVIOUS RUN ==== " status=$(minikube status --format "{{.MinikubeStatus}}") -if [ "$status" = "Running" ]; then +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 be able to bind to the same port again (see end of script) -echo "Kill kubectl process to re-init port-forwarding for minikube" -kubepid=$(pidof "kubectl") -if [ $? -eq 0 ]; then - kill "$kubepid" +# we restart the process to bind to the same port again (see end of script) +if [ -e /tmp/kubectl-port-forward.pid ]; then + + 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" + fi + rm /tmp/kubectl-port-forward.pid fi echo "==== START MINIKUBE ==== " echo "May take a few minutes ..." -minikube start +minikube start kubectl config set-context minikube echo "==== MINIKUBE STATUS ==== " @@ -48,11 +54,11 @@ echo "==== START OPERATOR ==== " # the order of files is significant for file in "configmap.yaml" "serviceaccount.yaml" "postgres-operator.yaml" do - retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" + retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" done -msg="Wait for the postgresql custom resource definition to register." -cmd="kubectl get crd | grep 'postgresqls.acid.zalan.do' &> /dev/null" +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 @@ -62,22 +68,18 @@ 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 -# 1> redirects stdout to remove the info message about forwarded ports; the message sometimes garbles the cli prompt -kubectl port-forward "$operatorPod" "$localPort":"$operatorPort" 1> /dev/null & - +# 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 -L http://127.0.0.1:$localPort/clusters &> /dev/null" +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" -retry "$checkCmd" "$checkMsg" -if [ $? -eq 0 ]; then +if retry "$checkCmd" "$checkMsg" ; then echo "==== SUCCESS: OPERATOR IS RUNNING ==== " else - echo "Operator did not start or port forwarding did not work" + echo "==== FAILURE: OPERATOR DID NOT START OR PORT FORWARDING DID NOT WORK" exit 1 fi - - - - From 7ce36a3d5bc764079dfb92ec9351aa9dce0d5438 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 25 Jan 2018 15:36:45 +0100 Subject: [PATCH 03/10] Apply stashed changes that build operator --- run_locally.sh | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/run_locally.sh b/run_locally.sh index f7c6973fe..419bcf1fb 100755 --- a/run_locally.sh +++ b/run_locally.sh @@ -20,6 +20,37 @@ function retry(){ # timeouts after 1 minutes return 1 } +function build_operator_binary(){ + make tools && make deps && make local +} + +# 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 ==== " + + build_operator_binary + + # set docker env vars so that it can talk to the Docker daemon inside the minikube VM + 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") + + # build the image + make docker + + # update the tag in the postgres operator conf + # since the image with this tag is already present on the machine, + # docker should not attempt to fetch it from the registry due to imagePullPolicy + file="manifests/local-postgres-operator.yaml" + sed -e "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml >> "$file" + + retry "kubectl create -f \"$file\"" "attempt to create $file resource" + } + + echo "==== CLEAN UP PREVIOUS RUN ==== " status=$(minikube status --format "{{.MinikubeStatus}}") @@ -39,8 +70,8 @@ if [ -e /tmp/kubectl-port-forward.pid ]; then kill "$pid" fi rm /tmp/kubectl-port-forward.pid -fi +fi echo "==== START MINIKUBE ==== " echo "May take a few minutes ..." @@ -52,11 +83,18 @@ minikube status echo "==== START OPERATOR ==== " # the order of files is significant -for file in "configmap.yaml" "serviceaccount.yaml" "postgres-operator.yaml" +for file in "configmap.yaml" "serviceaccount.yaml" do retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" done +should_build_operator=true +if [ "$should_build_operator" = true ]; then + deploy_self_built_image +else + retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create $file 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 " From 08567e7be3c9332779a9e6a4e926e2a732e8a522 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 25 Jan 2018 18:13:53 +0100 Subject: [PATCH 04/10] Add code to build a custom operator image --- run_locally.sh | 59 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/run_locally.sh b/run_locally.sh index 419bcf1fb..66b23b71b 100755 --- a/run_locally.sh +++ b/run_locally.sh @@ -9,8 +9,7 @@ function retry(){ # timeouts after 1 minutes cmd="$1" retryMsg="$2" for i in {1..20}; do - eval "$cmd" - if [ $? -eq 0 ]; then + if eval "$cmd"; then return 0 fi echo "$retryMsg" @@ -21,17 +20,20 @@ function retry(){ # timeouts after 1 minutes } function build_operator_binary(){ - make tools && make deps && make local + 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 it can talk to the Docker daemon inside the minikube VM + # set docker env vars so that docker can talk to the Docker daemon inside the minikube VM eval $(minikube docker-env) # image tag consists of a git tag or a unique commit prefix @@ -39,16 +41,43 @@ function deploy_self_built_image() { export TAG=$(git describe --tags --always --dirty="-dev") # build the image - make docker + 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, # docker should not attempt to fetch it from the registry due to imagePullPolicy - file="manifests/local-postgres-operator.yaml" - sed -e "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml >> "$file" + file="/tmp/local-postgres-operator.yaml" + sed -e "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$file" - retry "kubectl create -f \"$file\"" "attempt to create $file resource" - } + retry "kubectl create -f \"$file\"" "attempt to create $file 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 ==== " @@ -88,11 +117,11 @@ do retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" done -should_build_operator=true + if [ "$should_build_operator" = true ]; then - deploy_self_built_image + deploy_self_built_image else - retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create $file resource" + 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..." @@ -117,7 +146,11 @@ 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 + From 9732ec6988d2d441588a46c2163eaa46ed63a3a0 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Mon, 29 Jan 2018 16:59:25 +0100 Subject: [PATCH 05/10] Refactor code into separate functions --- run_locally.sh | 299 +++++++++++++++++++++++++++++++------------------ 1 file changed, 188 insertions(+), 111 deletions(-) diff --git a/run_locally.sh b/run_locally.sh index 66b23b71b..f77b50287 100755 --- a/run_locally.sh +++ b/run_locally.sh @@ -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 "$@" From 258f4a848f0923f56aef14b21d54931b843ee3af Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 30 Jan 2018 11:04:38 +0100 Subject: [PATCH 06/10] misc readability improvements --- run_locally.sh | 93 ++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/run_locally.sh b/run_locally.sh index f77b50287..988382096 100755 --- a/run_locally.sh +++ b/run_locally.sh @@ -24,8 +24,8 @@ function retry(){ # errexit may break "eval $cmd", so we disable it temporarily set +o errexit - local cmd="$1" - local retry_msg="$2" + local -r cmd="$1" + local -r retry_msg="$2" # times out after 1 minute for i in {1..20}; do @@ -42,47 +42,11 @@ function retry(){ } -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 -} - - -function deploy_self_built_image() { - - echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " - - build_operator_binary - - # 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 - TAG=$(git describe --tags --always --dirty="-dev") - export TAG - - # build the image - make docker > /dev/null 2>&1 - - # update the tag in the postgres operator conf - # since the image with this tag already exists on the machine, - # docker should not attempt to fetch it from the registry due to imagePullPolicy - sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" - - 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 ]" } + function clean_up(){ echo "==== CLEAN UP PREVIOUS RUN ==== " @@ -116,6 +80,7 @@ function clean_up(){ fi } + function start_minikube(){ echo "==== START MINIKUBE ==== " @@ -129,6 +94,46 @@ function start_minikube(){ } + +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 +} + + +function deploy_self_built_image() { + + echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " + + build_operator_binary + + # the fastest way to run a 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 + local -x TAG + TAG=$(git describe --tags --always --dirty="-dev") + readonly TAG + + # build the image + make docker > /dev/null 2>&1 + + # update the tag in the postgres operator conf + # since the image with this tag already exists on the machine, + # docker should not attempt to fetch it from the registry due to imagePullPolicy + sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" + + retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource" +} + + function start_operator(){ echo "==== START OPERATOR ==== " @@ -147,13 +152,14 @@ function start_operator(){ 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'" + local -r msg="Wait for the postgresql custom resource definition to register..." + local -r 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 ====" @@ -172,9 +178,9 @@ function check_health(){ echo "==== RUN HEALTH CHECK ==== " - local check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" + local -r check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" + local -r check_msg="Wait for port forwarding to take effect" 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 ==== " @@ -196,7 +202,6 @@ function main(){ 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 From 153ebd335f5471a4cae195325ac9722e711203dd Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 30 Jan 2018 12:08:08 +0100 Subject: [PATCH 07/10] Fix formatting --- run_locally.sh | 162 ++++++++++++++------------- run_operator_locally.sh | 236 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+), 83 deletions(-) mode change 100755 => 100644 run_locally.sh create mode 100755 run_operator_locally.sh diff --git a/run_locally.sh b/run_locally.sh old mode 100755 new mode 100644 index 988382096..675ce2dea --- a/run_locally.sh +++ b/run_locally.sh @@ -19,73 +19,73 @@ readonly OPERATOR_PORT="8080" # minikube needs time to create resources, # so the script retries actions until all the resources become available -function retry(){ +function retry(){ - # errexit may break "eval $cmd", so we disable it temporarily - set +o errexit - - local -r cmd="$1" + local -r cmd_to_retry="$1" local -r retry_msg="$2" + # errexit may break "eval $cmd_to_retry", so we disable it temporarily + set +o errexit + # times out after 1 minute for i in {1..20}; do - if eval "$cmd"; then - set -o errexit # enable again + if eval "$cmd_to_retry"; then + set -o errexit # enable again return 0 fi - echo "$retry_msg" + echo "$retry_msg" sleep 3 done - >2& echo "The command $cmd timed out" + >2& echo "The command $cmd_to_retry timed out" return 1 } function display_help(){ - echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" + echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" } function clean_up(){ - + 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 + echo "Delete the existing local cluster so that we can cleanly apply resources from scratch..." + minikube delete fi if [[ -e "$PATH_TO_LOCAL_OPERATOR_MANIFEST" ]]; then - rm --verbose "$PATH_TO_LOCAL_OPERATOR_MANIFEST" + 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 + + 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 fi } function start_minikube(){ - + echo "==== START MINIKUBE ==== " echo "May take a few minutes ..." - + minikube start kubectl config set-context minikube @@ -99,8 +99,8 @@ 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 tools > /dev/null 2>&1 make deps > /dev/null 2>&1 make local > /dev/null 2>&1 } @@ -109,10 +109,10 @@ function build_operator_binary(){ function deploy_self_built_image() { echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " - + build_operator_binary - - # the fastest way to run a docker image locally is to reuse the docker from minikube + + # the fastest way to run a 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) @@ -121,35 +121,35 @@ function deploy_self_built_image() { local -x TAG TAG=$(git describe --tags --always --dirty="-dev") readonly TAG - + # build the image make docker > /dev/null 2>&1 - + # update the tag in the postgres operator conf # since the image with this tag already exists on the machine, # docker should not attempt to fetch it from the registry due to imagePullPolicy sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" - + retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource" } 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" + for file in "configmap.yaml" "serviceaccount.yaml" do - retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" + retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" done - if [[ "$should_build_operator" = true ]]; then - deploy_self_built_image + if [[ "$should_build_custom_operator" = true ]]; then # set in main() + deploy_self_built_image else - retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" + retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" fi local -r msg="Wait for the postgresql custom resource definition to register..." @@ -161,78 +161,74 @@ function start_operator(){ function forward_ports(){ - - echo "==== FORWARD OPERATOR PORT $OPERATOR_PORT TO LOCAL PORT $LOCAL_PORT ====" - + + 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 -r check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" + + local -r check_cmd="curl --location http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" local -r check_msg="Wait for port forwarding to take effect" echo "Command for checking: $check_cmd" if retry "$check_cmd" "$check_msg"; then - echo "==== SUCCESS: OPERATOR IS RUNNING ==== " - echo "To stop it cleanly, run 'minikube delete'" + 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 + >2& echo "==== FAILURE: OPERATOR DID NOT START OR PORT FORWARDING DID NOT WORK ==== " + 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 + 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 + local should_build_custom_operator=false # used in start_operator() 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 + # if the 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_custom_operator=true + break + ;; + *) break + ;; + esac done - - clean_up + + clean_up start_minikube - start_operator should_build_operator + start_operator forward_ports check_health - + exit 0 } main "$@" - diff --git a/run_operator_locally.sh b/run_operator_locally.sh new file mode 100755 index 000000000..0d88c6e9f --- /dev/null +++ b/run_operator_locally.sh @@ -0,0 +1,236 @@ +#!/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 + + +# enable unofficial bash strict mode +set -o errexit +set -o nounset +set -o pipefail +IFS=$'\n\t' + + +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 -r cmd="$1" + local -r 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 "$retry_msg" + sleep 3 + done + + >2& echo "The command $cmd timed out" + return 1 +} + + +function display_help(){ + echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" +} + + +function clean_up(){ + + 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 + + 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 + + fi +} + + +function start_minikube(){ + + echo "==== START MINIKUBE ==== " + echo "May take a few minutes ..." + + minikube start + kubectl config set-context minikube + + echo "==== MINIKUBE STATUS ==== " + minikube status + +} + + +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 +} + + +function deploy_self_built_image() { + + echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " + + build_operator_binary + + # the fastest way to run a 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 + local -x TAG + TAG=$(git describe --tags --always --dirty="-dev") + readonly TAG + + # build the image + make docker > /dev/null 2>&1 + + # update the tag in the postgres operator conf + # since the image with this tag already exists on the machine, + # docker should not attempt to fetch it from the registry due to imagePullPolicy + sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" + + retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource" +} + + +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_custom_operator" = true ]]; then # set in main() + deploy_self_built_image + else + retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" + fi + + local -r msg="Wait for the postgresql custom resource definition to register..." + local -r 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 -r check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" + local -r check_msg="Wait for port forwarding to take effect" + echo "Command for checking: $check_cmd" + + 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_custom_operator=false # used in start_operator() + while true + do + # if the 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_custom_operator=true + break + ;; + *) break + ;; + esac + done + + clean_up + start_minikube + start_operator + forward_ports + check_health + + exit 0 +} + + +main "$@" + From 105bbdb8e42d63bba97f402b542151d825ede96d Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 30 Jan 2018 12:09:32 +0100 Subject: [PATCH 08/10] delete script with the old name --- run_locally.sh | 234 ------------------------------------------------- 1 file changed, 234 deletions(-) delete mode 100644 run_locally.sh diff --git a/run_locally.sh b/run_locally.sh deleted file mode 100644 index 675ce2dea..000000000 --- a/run_locally.sh +++ /dev/null @@ -1,234 +0,0 @@ -#!/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 - - -# enable unofficial bash strict mode -set -o errexit -set -o nounset -set -o pipefail -IFS=$'\n\t' - - -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(){ - - local -r cmd_to_retry="$1" - local -r retry_msg="$2" - - # errexit may break "eval $cmd_to_retry", so we disable it temporarily - set +o errexit - - # times out after 1 minute - for i in {1..20}; do - if eval "$cmd_to_retry"; then - set -o errexit # enable again - return 0 - fi - echo "$retry_msg" - sleep 3 - done - - >2& echo "The command $cmd_to_retry timed out" - return 1 -} - - -function display_help(){ - echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" -} - - -function clean_up(){ - - 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 - - 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 - - fi -} - - -function start_minikube(){ - - echo "==== START MINIKUBE ==== " - echo "May take a few minutes ..." - - minikube start - kubectl config set-context minikube - - echo "==== MINIKUBE STATUS ==== " - minikube status - -} - - -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 -} - - -function deploy_self_built_image() { - - echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " - - build_operator_binary - - # the fastest way to run a 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 - local -x TAG - TAG=$(git describe --tags --always --dirty="-dev") - readonly TAG - - # build the image - make docker > /dev/null 2>&1 - - # update the tag in the postgres operator conf - # since the image with this tag already exists on the machine, - # docker should not attempt to fetch it from the registry due to imagePullPolicy - sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" - - retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource" -} - - -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_custom_operator" = true ]]; then # set in main() - deploy_self_built_image - else - retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" - fi - - local -r msg="Wait for the postgresql custom resource definition to register..." - local -r 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 -r check_cmd="curl --location http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" - local -r check_msg="Wait for port forwarding to take effect" - echo "Command for checking: $check_cmd" - - 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 ==== " - 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_custom_operator=false # used in start_operator() - while true - do - # if the 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_custom_operator=true - break - ;; - *) break - ;; - esac - done - - clean_up - start_minikube - start_operator - forward_ports - check_health - - exit 0 -} - - -main "$@" From f1bcdd1a8ecfda51bfec7cbd184f6010f43e8e35 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 30 Jan 2018 12:24:35 +0100 Subject: [PATCH 09/10] Fix naming conflict and redo formatting --- run_operator_locally.sh | 143 ++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 73 deletions(-) diff --git a/run_operator_locally.sh b/run_operator_locally.sh index 0d88c6e9f..ebdc3196d 100755 --- a/run_operator_locally.sh +++ b/run_operator_locally.sh @@ -19,73 +19,73 @@ readonly OPERATOR_PORT="8080" # minikube needs time to create resources, # so the script retries actions until all the resources become available -function retry(){ +function retry(){ - # errexit may break "eval $cmd", so we disable it temporarily + # errexit may break "eval $retry_cmd", so we disable it temporarily set +o errexit - - local -r cmd="$1" + + local -r retry_cmd="$1" local -r retry_msg="$2" # times out after 1 minute for i in {1..20}; do - if eval "$cmd"; then - set -o errexit # enable again + if eval "$retry_cmd"; then + set -o errexit # enable again return 0 fi - echo "$retry_msg" + echo "$retry_msg" sleep 3 done - >2& echo "The command $cmd timed out" + >2& echo "The command $retry_cmd timed out" return 1 } function display_help(){ - echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" + echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" } function clean_up(){ - + 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 + echo "Delete the existing local cluster so that we can cleanly apply resources from scratch..." + minikube delete fi if [[ -e "$PATH_TO_LOCAL_OPERATOR_MANIFEST" ]]; then - rm --verbose "$PATH_TO_LOCAL_OPERATOR_MANIFEST" + 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 + + 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 fi } function start_minikube(){ - + echo "==== START MINIKUBE ==== " echo "May take a few minutes ..." - + minikube start kubectl config set-context minikube @@ -99,8 +99,8 @@ 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 tools > /dev/null 2>&1 make deps > /dev/null 2>&1 make local > /dev/null 2>&1 } @@ -109,10 +109,10 @@ function build_operator_binary(){ function deploy_self_built_image() { echo "==== DEPLOY CUSTOM OPERATOR IMAGE ==== " - + build_operator_binary - - # the fastest way to run a docker image locally is to reuse the docker from minikube + + # the fastest way to run a 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) @@ -121,35 +121,35 @@ function deploy_self_built_image() { local -x TAG TAG=$(git describe --tags --always --dirty="-dev") readonly TAG - + # build the image make docker > /dev/null 2>&1 - + # update the tag in the postgres operator conf # since the image with this tag already exists on the machine, # docker should not attempt to fetch it from the registry due to imagePullPolicy sed --expression "s/\(image\:.*\:\).*$/\1$TAG/" manifests/postgres-operator.yaml > "$PATH_TO_LOCAL_OPERATOR_MANIFEST" - + retry "kubectl create -f \"$PATH_TO_LOCAL_OPERATOR_MANIFEST\"" "attempt to create $PATH_TO_LOCAL_OPERATOR_MANIFEST resource" } 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" + for file in "configmap.yaml" "serviceaccount.yaml" do - retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" + retry "kubectl create -f manifests/\"$file\"" "attempt to create $file resource" done if [[ "$should_build_custom_operator" = true ]]; then # set in main() - deploy_self_built_image + deploy_self_built_image else - retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" + retry "kubectl create -f manifests/postgres-operator.yaml" "attempt to create /postgres-operator.yaml resource" fi local -r msg="Wait for the postgresql custom resource definition to register..." @@ -161,76 +161,73 @@ function start_operator(){ 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 -r check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" local -r check_msg="Wait for port forwarding to take effect" echo "Command for checking: $check_cmd" if retry "$check_cmd" "$check_msg"; then - echo "==== SUCCESS: OPERATOR IS RUNNING ==== " - echo "To stop it cleanly, run 'minikube delete'" + 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 + >2& echo "==== FAILURE: OPERATOR DID NOT START OR PORT FORWARDING DID NOT WORK" + 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 + 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_custom_operator=false # used in start_operator() while true do - # if the 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_custom_operator=true - break - ;; - *) break - ;; - esac + # if the 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_custom_operator=true + break + ;; + *) break + ;; + esac done - - clean_up + + clean_up start_minikube start_operator forward_ports check_health - + exit 0 } main "$@" - From 87098faa385267e7cfc7a5d31daf26db99ed9aae Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Wed, 31 Jan 2018 17:18:12 +0100 Subject: [PATCH 10/10] Respond to code review --- run_operator_locally.sh | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/run_operator_locally.sh b/run_operator_locally.sh index ebdc3196d..6c5f15a9f 100755 --- a/run_operator_locally.sh +++ b/run_operator_locally.sh @@ -11,7 +11,7 @@ set -o pipefail IFS=$'\n\t' -readonly PATH_TO_LOCAL_OPERATOR_MANIFEST="/tmp/local-postgres-operator.yaml" +readonly PATH_TO_LOCAL_OPERATOR_MANIFEST="/tmp/local-postgres-operator-manifest.yaml" readonly PATH_TO_PORT_FORWARED_KUBECTL_PID="/tmp/kubectl-port-forward.pid" readonly LOCAL_PORT="8080" readonly OPERATOR_PORT="8080" @@ -21,16 +21,12 @@ readonly OPERATOR_PORT="8080" # so the script retries actions until all the resources become available function retry(){ - # errexit may break "eval $retry_cmd", so we disable it temporarily - set +o errexit - local -r retry_cmd="$1" local -r retry_msg="$2" # times out after 1 minute for i in {1..20}; do if eval "$retry_cmd"; then - set -o errexit # enable again return 0 fi echo "$retry_msg" @@ -43,7 +39,7 @@ function retry(){ function display_help(){ - echo "Usage: ./run_locally.sh [ -r | --rebuild-operator ] [ -h | --help ]" + echo "Usage: $0 [ -r | --rebuild-operator ] [ -h | --help ]" } @@ -68,14 +64,13 @@ function clean_up(){ if [[ -e "$PATH_TO_PORT_FORWARED_KUBECTL_PID" ]]; then local pid - pid=$(cat "$PATH_TO_PORT_FORWARED_KUBECTL_PID") + pid=$( < "$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 + if kill "$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 + rm --verbose "$PATH_TO_PORT_FORWARED_KUBECTL_PID" fi } @@ -99,10 +94,8 @@ 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 deps local > /dev/null 2>&1 - make tools > /dev/null 2>&1 - make deps > /dev/null 2>&1 - make local > /dev/null 2>&1 } @@ -171,7 +164,7 @@ function forward_ports(){ # 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" + echo $! > "$PATH_TO_PORT_FORWARED_KUBECTL_PID" } @@ -179,7 +172,7 @@ function check_health(){ echo "==== RUN HEALTH CHECK ==== " - local -r check_cmd="curl --location --silent http://127.0.0.1:$LOCAL_PORT/clusters &> /dev/null" + local -r check_cmd="curl --location --silent --output /dev/null http://127.0.0.1:$LOCAL_PORT/clusters" local -r check_msg="Wait for port forwarding to take effect" echo "Command for checking: $check_cmd"