#!/bin/sh
set -eu

usage() {
  echo "usage: $0 <service> <image> <rollout-kind> <namespace> <workload> <container> <aws-profile-or-> <region> <cluster-name> <kubeconfig> <context>" >&2
  exit 2
}

[ "$#" -eq 11 ] || usage

service=$1
image=$2
rollout_kind=$3
namespace=$4
workload=$5
container=$6
aws_profile=$7
region=$8
cluster_name=$9
kubeconfig=${10}
context=${11}
rollout_timeout=${CP9_STARTER_REMOTE_ROLLOUT_TIMEOUT:-300s}
rollout_stamp=${CP9_IMAGE_ROLLOUT_STAMP:-}

aws_cli() {
  if [ -n "$aws_profile" ] && [ "$aws_profile" != "-" ]; then
    aws --profile "$aws_profile" "$@"
    return
  fi
  aws "$@"
}

kubectl_cmd() {
  kubectl --kubeconfig "$kubeconfig" --context "$context" "$@"
}

not_found() {
  case "$1" in
    *NotFound*|*"not found"*|*"Not Found"*) return 0 ;;
    *) return 1 ;;
  esac
}

if [ -z "$cluster_name" ] || [ -z "$region" ] || [ -z "$context" ]; then
  printf '%s\n' "[cp9 starter remote rollout] $service: remote EKS substrate is not available; rollout waits for activation"
  exit 0
fi

mkdir -p "$(dirname "$kubeconfig")"
printf '%s\n' "[cp9 starter remote rollout] $service: refresh kubeconfig for $cluster_name"
kubeconfig_tmp=$(mktemp "${kubeconfig}.tmp.XXXXXX")
trap 'rm -f "$kubeconfig_tmp"' EXIT HUP INT TERM
aws_cli eks update-kubeconfig \
  --region "$region" \
  --name "$cluster_name" \
  --kubeconfig "$kubeconfig_tmp" \
  --alias "$context" >/dev/null
chmod 600 "$kubeconfig_tmp"
mv "$kubeconfig_tmp" "$kubeconfig"
trap - EXIT HUP INT TERM

if ! namespace_output=$(kubectl_cmd get namespace "$namespace" 2>&1); then
  if not_found "$namespace_output"; then
    printf '%s\n' "[cp9 starter remote rollout] $service: namespace $namespace is absent; rollout waits for activation"
    exit 0
  fi
  printf '%s\n' "$namespace_output" >&2
  exit 1
fi

case "$rollout_kind" in
  kubernetes-deployment) resource_kind=deployment ;;
  kubernetes-statefulset) resource_kind=statefulset ;;
  kubernetes-daemonset) resource_kind=daemonset ;;
  *) echo "unsupported Starter rollout kind: $rollout_kind" >&2; exit 2 ;;
esac

if ! workload_output=$(kubectl_cmd -n "$namespace" get "$resource_kind" "$workload" 2>&1); then
  if not_found "$workload_output"; then
    printf '%s\n' "[cp9 starter remote rollout] $service: $resource_kind $namespace/$workload is absent; rollout waits for activation"
    exit 0
  fi
  printf '%s\n' "$workload_output" >&2
  exit 1
fi

jsonpath="{.spec.template.spec.containers[?(@.name=='$container')].image}"
current_image=$(kubectl_cmd -n "$namespace" get "$resource_kind" "$workload" -o "jsonpath=$jsonpath")
if [ -z "$current_image" ]; then
  echo "container $container was not found in $resource_kind $namespace/$workload" >&2
  exit 1
fi

action=unchanged
if [ "$current_image" != "$image" ]; then
  printf '%s\n' "[cp9 starter remote rollout] $service: set $namespace/$workload container $container image $current_image -> $image"
  kubectl_cmd -n "$namespace" set image "$resource_kind/$workload" "$container=$image"
  action=patched-image
fi

if [ -n "$rollout_stamp" ]; then
  stamp_patch=$(
    python3 - "$rollout_stamp" <<'PY'
import json
import sys

print(json.dumps({
    "spec": {
        "template": {
            "metadata": {
                "annotations": {
                    "cp9.tidbcloud.com/source-image-stamp": sys.argv[1],
                },
            },
        },
    },
}))
PY
  )
  kubectl_cmd -n "$namespace" patch "$resource_kind" "$workload" --type merge -p "$stamp_patch"
  if [ "$action" = "unchanged" ]; then
    action=patched-stamp
  else
    action="$action,patched-stamp"
  fi
fi

kubectl_cmd -n "$namespace" rollout status "$resource_kind/$workload" --timeout="$rollout_timeout"
printf '%s\n' "[cp9 starter remote rollout] $service: rollout ready for $namespace/$workload ($action)"
