Skip to content

Commit

Permalink
Update docker-rollout for SH
Browse files Browse the repository at this point in the history
  • Loading branch information
theupriser authored Feb 16, 2024
1 parent aca2f2d commit 9afc6dd
Showing 1 changed file with 30 additions and 51 deletions.
81 changes: 30 additions & 51 deletions docker-rollout
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
#!/bin/bash
#!/bin/sh
set -e

# Defaults
HEALTHCHECK_TIMEOUT=60
NO_HEALTHCHECK_TIMEOUT=10

# Print metadata for Docker CLI plugin
if [[ "$1" == "docker-cli-plugin-metadata" ]]; then
if [ "$1" = "docker-cli-plugin-metadata" ]; then
cat <<EOF
{
"SchemaVersion": "0.1.0",
"Vendor": "Karol Musur",
"Version": "v0.7",
"Version": "v0.8",
"ShortDescription": "Rollout new Compose service version"
}
EOF
exit
fi

# Save docker arguments, i.e. arguments before "rollout"
while [[ $# -gt 0 ]]; do
if [[ "$1" == "rollout" ]]; then
while [ $# -gt 0 ]; do
if [ "$1" = "rollout" ]; then
shift
break
fi
Expand Down Expand Up @@ -64,66 +64,49 @@ exit_with_usage() {
}

healthcheck() {
local container_id="$1"

# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
if docker $DOCKER_ARGS inspect --format='{{json .State.Health.Status}}' "$container_id" | grep -v "unhealthy" | grep -q "healthy"; then
return 0
fi

return 1
docker $DOCKER_ARGS inspect --format='{{json .State.Health.Status}}' "$1" | grep -v "unhealthy" | grep -q "healthy"
}

scale() {
local service="$1"
local replicas="$2"

# shellcheck disable=SC2086 # COMPOSE_FILES and ENV_FILES must be unquoted to allow multiple files
$COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES up --detach --scale "$service=$replicas" --no-recreate "$service"
$COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES up --detach --scale "$1=$2" --no-recreate "$1"
}

main() {
# shellcheck disable=SC2086 # COMPOSE_FILES and ENV_FILES must be unquoted to allow multiple files
if [[ "$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE")" == "" ]]; then
if [ -z "$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE")" ]; then
echo "==> Service '$SERVICE' is not running. Starting the service."
$COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES up --detach --no-recreate "$SERVICE"
exit 0
fi

# shellcheck disable=SC2086 # COMPOSE_FILES and ENV_FILES must be unquoted to allow multiple files
OLD_CONTAINER_IDS_STRING=$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE")
OLD_CONTAINER_IDS=()
for container_id in $OLD_CONTAINER_IDS_STRING; do
OLD_CONTAINER_IDS+=("$container_id")
done

SCALE=${#OLD_CONTAINER_IDS[@]}
OLD_CONTAINER_IDS_STRING=$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE" | tr '\n' '|' | sed 's/|$//')
OLD_CONTAINER_IDS=$(echo "$OLD_CONTAINER_IDS_STRING" | tr '|' ' ')
SCALE=$(echo "$OLD_CONTAINER_IDS" | wc -w | tr -d ' ')
SCALE_TIMES_TWO=$((SCALE * 2))
echo "==> Scaling '$SERVICE' to '$SCALE_TIMES_TWO' instances"
scale "$SERVICE" $SCALE_TIMES_TWO

# Create a variable that contains the IDs of the new containers, but not the old ones
# shellcheck disable=SC2086 # COMPOSE_FILES and ENV_FILES must be unquoted to allow multiple files
NEW_CONTAINER_IDS_STRING=$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE" | grep --invert-match --file <(echo "$OLD_CONTAINER_IDS_STRING"))
NEW_CONTAINER_IDS=()
for container_id in $NEW_CONTAINER_IDS_STRING; do
NEW_CONTAINER_IDS+=("$container_id")
done
NEW_CONTAINER_IDS=$($COMPOSE_COMMAND $COMPOSE_FILES $ENV_FILES ps --quiet "$SERVICE" | grep -Ev "$OLD_CONTAINER_IDS_STRING" | tr '\n' ' ')

# Check if first container has healthcheck
# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
if docker $DOCKER_ARGS inspect --format='{{json .State.Health}}' "${OLD_CONTAINER_IDS[0]}" | grep --quiet "Status"; then
if docker $DOCKER_ARGS inspect --format='{{json .State.Health}}' "$(echo $OLD_CONTAINER_IDS | cut -f 1 -w)" | grep -q "Status"; then
echo "==> Waiting for new containers to be healthy (timeout: $HEALTHCHECK_TIMEOUT seconds)"
for _ in $(seq 1 "$HEALTHCHECK_TIMEOUT"); do
SUCCESS=0

for NEW_CONTAINER_ID in "${NEW_CONTAINER_IDS[@]}"; do
for NEW_CONTAINER_ID in $NEW_CONTAINER_IDS; do
if healthcheck "$NEW_CONTAINER_ID"; then
SUCCESS=$((SUCCESS + 1))
fi
done

if [[ "$SUCCESS" == "$SCALE" ]]; then
if [ "$SUCCESS" = "$SCALE" ]; then
break
fi

Expand All @@ -132,21 +115,17 @@ main() {

SUCCESS=0

for NEW_CONTAINER_ID in "${NEW_CONTAINER_IDS[@]}"; do
for NEW_CONTAINER_ID in $NEW_CONTAINER_IDS; do
if healthcheck "$NEW_CONTAINER_ID"; then
SUCCESS=$((SUCCESS + 1))
fi
done

if [[ "$SUCCESS" != "$SCALE" ]]; then
if [ "$SUCCESS" != "$SCALE" ]; then
echo "==> New containers are not healthy. Rolling back." >&2

for NEW_CONTAINER_ID in "${NEW_CONTAINER_IDS[@]}"; do
# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS stop "$NEW_CONTAINER_ID"
# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS rm "$NEW_CONTAINER_ID"
done
docker $DOCKER_ARGS stop $NEW_CONTAINER_IDS
docker $DOCKER_ARGS rm $NEW_CONTAINER_IDS

exit 1
fi
Expand All @@ -155,17 +134,15 @@ main() {
sleep "$NO_HEALTHCHECK_TIMEOUT"
fi

echo "==> Stopping old containers"
echo "==> Stopping and removing old containers"

for OLD_CONTAINER_ID in "${OLD_CONTAINER_IDS[@]}"; do
# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS stop "$OLD_CONTAINER_ID"
# shellcheck disable=SC2086 # DOCKER_ARGS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS rm "$OLD_CONTAINER_ID"
done
# shellcheck disable=SC2086 # DOCKER_ARGS and OLD_CONTAINER_IDS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS stop $OLD_CONTAINER_IDS
# shellcheck disable=SC2086 # DOCKER_ARGS and OLD_CONTAINER_IDS must be unquoted to allow multiple arguments
docker $DOCKER_ARGS rm $OLD_CONTAINER_IDS
}

while [[ $# -gt 0 ]]; do
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
usage
Expand All @@ -192,9 +169,11 @@ while [[ $# -gt 0 ]]; do
exit_with_usage
;;
*)
if [[ -n "$SERVICE" ]]; then
if [ -n "$SERVICE" ]; then
echo "SERVICE is already set to '$SERVICE'"
exit_with_usage
if [ "$SERVICE" != "$1" ]; then
exit_with_usage
fi
fi

SERVICE="$1"
Expand All @@ -204,7 +183,7 @@ while [[ $# -gt 0 ]]; do
done

# Require SERVICE argument
if [[ -z "$SERVICE" ]]; then
if [ -z "$SERVICE" ]; then
echo "SERVICE is missing"
exit_with_usage
fi
Expand Down

0 comments on commit 9afc6dd

Please sign in to comment.