Created
October 14, 2016 14:03
-
-
Save aklinkert/5d2e4b81d7cf3c0be524663c63dc3da6 to your computer and use it in GitHub Desktop.
Revisions
-
aklinkert created this gist
Oct 14, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,104 @@ #!/usr/bin/env bash set -e VERSION="${CIRCLE_SHA1}" KUBE_CONTEXT="$(kubectl config current-context)" # getKubeValue "${KUBE_CONTEXT}" "${KUBE_NAMESPACE}" "${deployment}" "${path}" getKubeValue() { kubectl --context "${1}" --namespace "${2}" get "deployment/${3}" -o "jsonpath={${4}}" } # getKubeRevision "${KUBE_CONTEXT}" "${KUBE_NAMESPACE}" "${deployment}" getKubeRevision() { kubectl --context "${1}" --namespace "${2}" get "deployment/${3}" -o go-template --template='{{ index .metadata.annotations "deployment.kubernetes.io/revision"}}' } # updateKubernetesDeployment "${KUBE_CONTEXT}" "${KUBE_NAMESPACE}" "${deployment}" "${repo}" updateKubernetesDeployment() { local deployedImage deployedRepo currentRevision wantedReplicas availableReplicas updatedReplicas wantedGeneration observedGeneration # first check, if desired deployment does exist. If not, we can exit early if ! kubectl --context "${KUBE_CONTEXT}" --namespace "${KUBE_NAMESPACE}" describe deployment "${deployment}" > /dev/null ; then echo "Deployment '${deployment}' does not exist." return 0 fi deployedImage="$(getKubeValue "${1}" "${2}" "${3}" ".spec.template.spec.containers[0].image")" deployedRepo="$(echo "${deployedImage}" |cut -d':' -f1)" echo "Deployment ${3} has currently the repo ${deployedRepo} deployed, trying to match repo ${4} ..." # next we check, that the deployment we wanna update has given repo deployed. If not, we can exit early if ! [[ "${deployedRepo}" == "${4}" ]]; then echo "Deployment '${deployment}' does not contain docker repo ${repo}." return 0 fi # get the current revision to enable rollbacks currentRevision=$(getKubeRevision "${1}" "${2}" "${3}") echo "Current revision is ${currentRevision}" # actually update the deployment to new image version echo "Updating kubernetes deployment ${3} to use ${4}:${VERSION} in env ${2} ..." kubectl --context "${1}" --namespace "${2}" patch deployment "${3}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\": \"${3}\",\"image\":\"${4}:${VERSION}\"}]}}}}" echo "Updated to revision $(getKubeRevision "${1}" "${2}" "${3}")" sleep 1 # try 30 times to check the deployment for success for i in $(seq 1 30); do wantedReplicas="$(getKubeValue "${1}" "${2}" "${3}" ".spec.replicas")" availableReplicas="$(getKubeValue "${1}" "${2}" "${3}" ".status.availableReplicas")" updatedReplicas="$(getKubeValue "${1}" "${2}" "${3}" ".status.updatedReplicas")" wantedGeneration="$(getKubeValue "${1}" "${2}" "${3}" ".metadata.generation")" observedGeneration="$(getKubeValue "${1}" "${2}" "${3}" ".status.observedGeneration")" echo "check ${i} | wanted repl: ${wantedReplicas}; updated repl: ${updatedReplicas}; available repl: ${availableReplicas}; wanted gen: ${wantedGeneration}; observed gen: ${observedGeneration}" # when the deployment was successful, we can exit the function, our job here is done if [[ "${wantedReplicas}" == "${updatedReplicas}" ]] && [[ "${wantedGeneration}" && "${observedGeneration}" ]] && [[ 0 -lt "${availableReplicas}" ]]; then echo "Kubernetes deployment of ${3} was successful after ${i} check iterations." return 0 fi done # when the check loop ended without returning, we can assume that the deployment is broken. In this case, we roll back to the previous reversion. echo "Kubernetes deployment of ${3} was NOT successful! Rolling back to previous revision ${currentRevision} ..." kubectl --context "${1}" --namespace "${2}" rollout undo "deployment/${3}" --to-revision="${currentRevision}" return 1 } echo "Using kubectl context ${KUBE_CONTEXT} and namespace ${KUBE_NAMESPACE}" echo "checking if context for env exists ... " if ! kubectl get nodes --context "${KUBE_CONTEXT}" > /dev/null ; then echo "Desired context does not exist" exit 0 fi if [ -z "${KUBE_DEPLOYMENTS}" ] && [ -n "${KUBE_DEPLOYMENT:-}" ]; then KUBE_DEPLOYMENTS="${KUBE_DEPLOYMENT}" fi if [ -z "${KUBE_DEPLOYMENTS}" ]; then echo "No kubernetes deployment env var set" exit 0 fi declare -a deployments deployments=(${KUBE_DEPLOYMENTS}) declare -a repos repos=(${DOCKER_REPOS}) for repo in "${repos[@]}" ; do for deployment in "${deployments[@]}" ; do updateKubernetesDeployment "${KUBE_CONTEXT}" "${KUBE_NAMESPACE}" "${deployment}" "${repo}" done done echo "Done."