#!/usr/bin/env bash
set -euo pipefail

umask 077

ts="$(date -u '+%Y%m%dT%H%M%SZ')"
host="$(hostname -f 2>/dev/null || hostname || echo unknown-host)"
base_dir="/var/tmp/niceos-support"
work_dir="${base_dir}/niceos-k8s-support-bundle-${host}-${ts}"
archive="${work_dir}.tar.xz"

log() {
    printf '[INFO] %s\n' "$*" >&2
}

warn() {
    printf '[WARN] %s\n' "$*" >&2
}

run_cmd() {
    local name="$1"
    shift

    local out="${work_dir}/commands/${name}.txt"

    {
        printf '$'
        printf ' %q' "$@"
        printf '\n\n'

        "$@"
    } >"${out}" 2>&1 || {
        local rc=$?
        printf '\n[WARN] command exited with rc=%s\n' "${rc}" >>"${out}"
        return 0
    }
}

copy_if_exists() {
    local src="$1"
    local dst="$2"

    if [ -e "${src}" ]; then
        mkdir -p "$(dirname "${work_dir}/${dst}")"
        cp -a "${src}" "${work_dir}/${dst}" 2>/dev/null || \
            warn "failed to copy ${src}"
    fi
}

install -d -m 0750 "${base_dir}"
rm -rf "${work_dir}"
install -d -m 0750 "${work_dir}"
install -d -m 0750 "${work_dir}/commands"
install -d -m 0750 "${work_dir}/config"
install -d -m 0750 "${work_dir}/logs"
install -d -m 0750 "${work_dir}/meta"

log "creating support bundle in ${work_dir}"

# ---------------------------------------------------------------------------
# Metadata
# ---------------------------------------------------------------------------
{
    echo "NICEOS_SUPPORT_BUNDLE_KIND=k8s-node"
    echo "NICEOS_SUPPORT_BUNDLE_CREATED_UTC=${ts}"
    echo "HOSTNAME=${host}"
} > "${work_dir}/meta/bundle.env"

copy_if_exists /etc/os-release config/etc-os-release
copy_if_exists /etc/niceos-release config/etc-niceos-release
copy_if_exists /etc/lsb-release config/etc-lsb-release
copy_if_exists /etc/niceos/profiles/core-node-kubernetes.env config/core-node-kubernetes.env
copy_if_exists /etc/niceos/products/core-node-kubernetes.conf config/core-node-kubernetes.product
copy_if_exists /etc/crictl.yaml config/crictl.yaml
copy_if_exists /etc/ssh/sshd_config.d/40-niceos-k8s-node.conf config/40-niceos-k8s-node.conf
copy_if_exists /etc/sysctl.d config/etc-sysctl.d
copy_if_exists /etc/systemd/journald.conf.d config/journald.conf.d
copy_if_exists /etc/systemd/coredump.conf.d config/coredump.conf.d

# Do not copy kubeconfig or PKI material. Record only safe directory listing.
if [ -d /etc/kubernetes ]; then
    find /etc/kubernetes -maxdepth 2 -printf '%M %u %g %s %TY-%Tm-%Td %TH:%TM %p\n' \
        > "${work_dir}/commands/etc-kubernetes-listing.txt" 2>&1 || :
fi

# ---------------------------------------------------------------------------
# General system state
# ---------------------------------------------------------------------------
run_cmd uname uname -a
run_cmd uptime uptime
run_cmd date-utc date -u
run_cmd hostname hostnamectl
run_cmd os-release cat /etc/os-release
run_cmd rpm-qa rpm -qa
run_cmd df df -hT
run_cmd free free -h
run_cmd mount mount
run_cmd lsblk lsblk -a
run_cmd ip-addr ip addr
run_cmd ip-route ip route
run_cmd resolv-conf cat /etc/resolv.conf

# ---------------------------------------------------------------------------
# Services
# ---------------------------------------------------------------------------
run_cmd systemctl-failed systemctl --no-pager --failed
run_cmd systemctl-containerd systemctl --no-pager status containerd.service
run_cmd systemctl-kubelet systemctl --no-pager status kubelet.service
run_cmd systemctl-firewall systemctl --no-pager status niceos-kubernetes-firewall.service
run_cmd systemctl-issue systemctl --no-pager status niceos-core-node-kubernetes-issue.service
run_cmd systemctl-sshd systemctl --no-pager status sshd.service

# ---------------------------------------------------------------------------
# Logs
# ---------------------------------------------------------------------------
run_cmd journal-containerd journalctl --no-pager -u containerd.service --since '24 hours ago'
run_cmd journal-kubelet journalctl --no-pager -u kubelet.service --since '24 hours ago'
run_cmd journal-firewall journalctl --no-pager -u niceos-kubernetes-firewall.service --since '24 hours ago'
run_cmd journal-sshd journalctl --no-pager -u sshd.service --since '24 hours ago'
run_cmd journal-boot journalctl --no-pager -b

# ---------------------------------------------------------------------------
# Kubernetes/container runtime diagnostics
# ---------------------------------------------------------------------------
if command -v crictl >/dev/null 2>&1; then
    run_cmd crictl-info crictl info
    run_cmd crictl-ps crictl ps -a
    run_cmd crictl-pods crictl pods
    run_cmd crictl-images crictl images
fi

if command -v kubeadm >/dev/null 2>&1; then
    run_cmd kubeadm-version kubeadm version -o short
fi

if command -v kubelet >/dev/null 2>&1; then
    run_cmd kubelet-version kubelet --version
fi

if command -v kubectl >/dev/null 2>&1; then
    run_cmd kubectl-version-client kubectl version --client=true

    if [ -r /etc/kubernetes/admin.conf ]; then
        run_cmd kubectl-nodes env KUBECONFIG=/etc/kubernetes/admin.conf kubectl get nodes -o wide
        run_cmd kubectl-pods-all env KUBECONFIG=/etc/kubernetes/admin.conf kubectl get pods -A -o wide
    fi
fi

# ---------------------------------------------------------------------------
# Network/firewall/sysctl/security
# ---------------------------------------------------------------------------
if command -v iptables-save >/dev/null 2>&1; then
    run_cmd iptables-save iptables-save
fi

if command -v ip6tables-save >/dev/null 2>&1; then
    run_cmd ip6tables-save ip6tables-save
fi

run_cmd sysctl-k8s sysctl \
    net.ipv4.ip_forward \
    net.bridge.bridge-nf-call-iptables \
    net.bridge.bridge-nf-call-ip6tables \
    kernel.panic \
    kernel.panic_on_oops

if command -v sshd >/dev/null 2>&1; then
    run_cmd sshd-effective-config sshd -T
fi

# ---------------------------------------------------------------------------
# Checksums and archive
# ---------------------------------------------------------------------------
log "creating archive ${archive}"

tar -C "${base_dir}" -cJf "${archive}" "$(basename "${work_dir}")"

sha256sum "${archive}" > "${archive}.sha256"

if command -v gostsum >/dev/null 2>&1; then
    gostsum "${archive}" > "${archive}.gost" 2>/dev/null || :
fi

rm -rf "${work_dir}"

log "support bundle created:"
echo "${archive}"
echo "${archive}.sha256"

if [ -f "${archive}.gost" ]; then
    echo "${archive}.gost"
fi