#!/bin/bash

usage() {
    cat<<EOF>&2
Usage: $0 [options]

Options:
  -h             Show this help message
EOF
    exit 1
}

while getopts "h" opt; do
    case ${opt} in
        *)
            usage
            ;;
    esac
done

get_mcp_config()
{
    local mcp="$1"
    oc get mcp "${mcp}" -o jsonpath="{.spec.configuration.name}{'\n'}"
}

get_degraded_workers_nr()
{
    oc get mcp "worker" -o jsonpath="{.status.degradedMachineCount}{'\n'}"
}

get_degraded_workers()
{
    local config=$(get_mcp_config "worker")
    oc get nodes -o json |
        jq -r '.items[] |
               select(.metadata.annotations["machineconfiguration.openshift.io/state"] == "Degraded") |
               select(.metadata.annotations["machineconfiguration.openshift.io/desiredConfig"] == "'"${config}"'") |
               .metadata.name'
}

get_mcp_worker_status()
{
    local type="$1"
    oc get mcp worker -o jsonpath='{.status.conditions[?(@.type=="'"${type}"'")].status}{"\n"}'
}

get_mcp_worker_updating()
{
    get_mcp_worker_status "Updating"
}

get_mcp_worker_degraded()
{
    get_mcp_worker_status "Degraded"
}

get_worker_current_config()
{
    local worker="$1"
    oc get node/"${worker}" -o json | jq -r '.metadata.annotations["machineconfiguration.openshift.io/currentConfig"]'
}

patch_degraded_worker_config()
{
    local worker="$1"
    local config="$2"

    echo "  - Patching ${worker}"

    local current_conf=$(get_worker_current_config "${worker}")
    echo "    from : ${current_conf}"

    local new_conf=$(oc patch node "${worker}" --type=merge -p '{"metadata":{"annotations":{"machineconfiguration.openshift.io/currentConfig":"'"${config}"'"}}}' -o json | \
                         jq -r '.metadata.annotations["'"machineconfiguration.openshift.io/currentConfig"'"]')
    echo "    to   : ${new_conf}"
    echo "    $(oc debug --quiet node/${worker} -- rm -fv /host/etc/machine-config-daemon/currentconfig)"

    echo "  - Waiting for ${worker} to recover"
    oc wait node "${worker}" --for=jsonpath='{.metadata.annotations.machineconfiguration\.openshift\.io/state}=Done' --timeout=1h
}

wait_for_worker_pool_status()
{
    local status="$1"

    oc wait mcp worker --for=jsonpath='{.status.conditions[?(@.type=="'"${status}"'")].status}=True' --timeout=1h
}

worker_config=$(get_mcp_config "worker")
echo "- Worker pool config : ${worker_config}"

echo "- Delete KataConfig"
oc delete kataconfig --all --wait=false

echo "- Wait for worker pool to update"
wait_for_worker_pool_status "Updating"

while [[ $(get_mcp_worker_updating) = "True" ]]; do
    echo "- Wait for worker pool to degrade"
    wait_for_worker_pool_status "Degraded"

    degraded_workers_nr=$(get_degraded_workers_nr)
    echo "- Degraded workers (${degraded_workers_nr}) : "

    for worker in $(get_degraded_workers); do
        patch_degraded_worker_config "${worker}" "${worker_config}"
    done
done
