#!/usr/bin/env bash
# Dockerのrestart設定ごとに、デーモン再起動の後にコンテナが戻るかを記録する。
# 注意: `sudo systemctl restart docker` を実行するため、同じホストの全コンテナが一度止まる。
# 止めてよい使い捨てのDocker環境だけで実行する。結果はJSONで標準出力に出す。
set -euo pipefail

IMAGE=alpine:3.20
PREFIX=rplab
POLICIES="no on-failure always unless-stopped"
docker pull -q "$IMAGE" >/dev/null

# 型 sig137: SIGTERMを無視し、停止時に強制終了される（終了コード137）
# 型 exit0 : SIGTERMを受けると終了コード0で終わる
cmd_for() {
  case "$1" in
    sig137) echo "sleep 100000" ;;
    exit0) echo 'trap "exit 0" TERM; sleep 100000 & wait' ;;
  esac
}

for kind in sig137 exit0; do
  for p in $POLICIES; do
    for state in running stopped; do
      docker run -d --name "$PREFIX-$kind-$p-$state" --restart "$p" "$IMAGE" sh -c "$(cmd_for "$kind")" >/dev/null
    done
  done
done
# 失敗し続けるコンテナ（on-failure:3）
docker run -d --name "$PREFIX-fail-onf3" --restart on-failure:3 "$IMAGE" sh -c 'sleep 1; exit 1' >/dev/null

# 再起動の設定は起動から10秒以上たってから有効になる（Docker公式）
sleep 15
for kind in sig137 exit0; do
  for p in $POLICIES; do
    docker stop -t 2 "$PREFIX-$kind-$p-stopped" >/dev/null
  done
done
sleep 10

snapshot() {
  docker ps -a --filter "name=$PREFIX-" --format '{{.Names}}' | sort | while read -r n; do
    docker inspect -f '{"name":"{{.Name}}","policy":"{{.HostConfig.RestartPolicy.Name}}","status":"{{.State.Status}}","exitCode":{{.State.ExitCode}},"restartCount":{{.RestartCount}}}' "$n"
  done | paste -sd, -
}

BEFORE="[$(snapshot)]"
sudo systemctl restart docker
sleep 15
AFTER="[$(snapshot)]"

cat <<EOF
{"ranAt":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","os":"$(. /etc/os-release && echo "$PRETTY_NAME")","dockerEngine":"$(docker version -f '{{.Server.Version}}')","liveRestore":$(docker info -f '{{.LiveRestoreEnabled}}'),"dockerEnabledOnBoot":"$(systemctl is-enabled docker)","restartMethod":"sudo systemctl restart docker","before":$BEFORE,"after":$AFTER}
EOF

docker rm -f $(docker ps -aq --filter "name=$PREFIX-") >/dev/null
