├── .travis.yml ├── LICENSE ├── README.md └── wait-for-deployment /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | 3 | before_install: 4 | - sudo apt-get install -y shellcheck 5 | 6 | script: 7 | - shellcheck wait-for-deployment 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Timo Reimann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kubernetes-scripts 2 | Collection of scripts useful for working with Kubernetes 3 | -------------------------------------------------------------------------------- /wait-for-deployment: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Waits for a deployment to complete. 3 | # 4 | # Includes a two-step approach: 5 | # 6 | # 1. Wait for the observed generation to match the specified one. 7 | # 2. Waits for the number of available replicas to match the specified one. 8 | # 9 | # Spawn from my answer to this StackOverflow question: http://stackoverflow.com/questions/37448357/ensure-kubernetes-deployment-has-completed-and-all-pods-are-updated-and-availabl 10 | # 11 | set -o errexit 12 | set -o pipefail 13 | set -o nounset 14 | # -m enables job control which is otherwise only enabled in interactive mode 15 | # http://unix.stackexchange.com/a/196606/73578 16 | set -m 17 | 18 | DEFAULT_TIMEOUT=60 19 | DEFAULT_NAMESPACE=default 20 | 21 | monitor_timeout() { 22 | local -r wait_pid="$1" 23 | sleep "${timeout}" 24 | echo "Timeout ${timeout} exceeded" >&2 25 | kill "${wait_pid}" 26 | } 27 | 28 | get_generation() { 29 | get_deployment_jsonpath '{.metadata.generation}' 30 | } 31 | 32 | get_observed_generation() { 33 | get_deployment_jsonpath '{.status.observedGeneration}' 34 | } 35 | 36 | get_specified_replicas() { 37 | get_deployment_jsonpath '{.spec.replicas}' 38 | } 39 | 40 | get_replicas() { 41 | get_deployment_jsonpath '{.status.replicas}' 42 | } 43 | 44 | get_updated_replicas() { 45 | get_deployment_jsonpath '{.status.updatedReplicas}' 46 | } 47 | 48 | get_available_replicas() { 49 | get_deployment_jsonpath '{.status.availableReplicas}' 50 | } 51 | 52 | get_deployment_jsonpath() { 53 | local -r jsonpath="$1" 54 | 55 | kubectl --namespace "${namespace}" get deployment "${deployment}" -o "jsonpath=${jsonpath}" 56 | } 57 | 58 | display_usage_and_exit() { 59 | echo "Usage: $(basename "$0") [-n ] [-t ] " >&2 60 | echo "Arguments:" >&2 61 | echo "deployment REQUIRED: The name of the deployment the script should wait on" >&2 62 | echo "-n OPTIONAL: The namespace the deployment exists in, defaults is the 'default' namespace" >&2 63 | echo "-t OPTIONAL: How long to wait for the deployment to be available, defaults to ${DEFAULT_TIMEOUT} seconds, must be greater than 0" >&2 64 | exit 1 65 | } 66 | 67 | namespace=${DEFAULT_NAMESPACE} 68 | timeout=${DEFAULT_TIMEOUT} 69 | 70 | while getopts ':n:t:' arg 71 | do 72 | case ${arg} in 73 | n) namespace=${OPTARG};; 74 | t) timeout=${OPTARG};; 75 | *) display_usage_and_exit 76 | esac 77 | done 78 | 79 | shift $((OPTIND-1)) 80 | if [ "$#" -ne 1 ] ; then 81 | display_usage_and_exit 82 | fi 83 | readonly deployment="$1" 84 | 85 | if [[ ${timeout} -le 0 ]]; then 86 | display_usage_and_exit 87 | fi 88 | 89 | echo "Waiting for deployment of ${deployment} in namespace ${namespace} with a timeout ${timeout} seconds" 90 | 91 | monitor_timeout $$ & 92 | readonly timeout_monitor_pid=$! 93 | 94 | trap 'kill -- -${timeout_monitor_pid}' EXIT #Stop timeout monitor 95 | 96 | generation=$(get_generation); readonly generation 97 | current_generation=$(get_observed_generation) 98 | 99 | echo "Expected generation for deployment ${deployment}: ${generation}" 100 | while [[ ${current_generation} -lt ${generation} ]]; do 101 | sleep .5 102 | echo "Currently observed generation: ${current_generation}" 103 | current_generation=$(get_observed_generation) 104 | done 105 | echo "Observed expected generation: ${current_generation}" 106 | 107 | specified_replicas="$(get_specified_replicas)"; readonly specified_replicas 108 | echo "Specified replicas: ${specified_replicas}" 109 | 110 | current_replicas=$(get_replicas) 111 | updated_replicas=$(get_updated_replicas) 112 | available_replicas=$(get_available_replicas) 113 | 114 | while [[ ${updated_replicas} -lt ${specified_replicas} || ${current_replicas} -gt ${updated_replicas} || ${available_replicas} -lt ${updated_replicas} ]]; do 115 | sleep .5 116 | echo "current/updated/available replicas: ${current_replicas}/${updated_replicas}/${available_replicas}, waiting" 117 | current_replicas=$(get_replicas) 118 | updated_replicas=$(get_updated_replicas) 119 | available_replicas=$(get_available_replicas) 120 | done 121 | 122 | echo "Deployment ${deployment} successful. All ${available_replicas} replicas are ready." 123 | --------------------------------------------------------------------------------