#!/usr/bin/bash
# /usr/libexec/arrakis-frame-connector
# All configuration arrives via the environment, from
# /etc/sysconfig/arrakis-frame-connector[-<instance>].
# Usage: arrakis-frame-connector [--dry-run]
set -euo pipefail

dry_run=0
[[ ${1:-} == --dry-run ]] && dry_run=1

: "${CTR_NAME:?not set}"
: "${IMAGE:?not set}"
: "${OUTDIR:?not set}"
: "${CHANNELS:?not set}"
: "${REPLAY_ID:?not set}"
: "${FRAME_DESCRIPTION:?not set}"

: "${RUNAS:=arrakis}"
: "${DATA_ROOT:=/kafka/arrakis}"
: "${CID_FILE:=/run/${CTR_NAME}.ctr-id}"
: "${FRAME_DURATION:=1}"
: "${RETENTION_TIME:=300}"
: "${PULL_POLICY:=missing}"
: "${CGROUP_PARENT:=arrakis.slice}"
# MEMORY_LIMIT, MEMORY_SWAP, CPU_LIMIT, PIDS_LIMIT: optional, no defaults.

uid=$(id -u "$RUNAS")
gid=$(id -g "$RUNAS")

# Intentional word splitting; globbing off so a stray '*' cannot expand.
set -f
# shellcheck disable=SC2206
channels=($CHANNELS)
extra=(${EXTRA_ARGS:-})
set +f
[[ ${#channels[@]} -gt 0 ]] || { echo "CHANNELS is empty" >&2; exit 1; }

# Optional resource limits: emitted only when set to a non-empty value.
limits=()
if [[ -n ${MEMORY_LIMIT:-} ]]; then
  limits+=(--memory="$MEMORY_LIMIT")
  # --memory-swap is the memory+swap TOTAL. Equal to --memory means no swap
  # allowance. Podman's default when omitted is 2x --memory, so this fallback
  # matters on any node that has swap enabled.
  limits+=(--memory-swap="${MEMORY_SWAP:-$MEMORY_LIMIT}")
elif [[ -n ${MEMORY_SWAP:-} ]]; then
  echo "MEMORY_SWAP set without MEMORY_LIMIT; ignoring" >&2
fi
[[ -n ${CPU_LIMIT:-}  ]] && limits+=(--cpus="$CPU_LIMIT")
[[ -n ${PIDS_LIMIT:-} ]] && limits+=(--pids-limit="$PIDS_LIMIT")

flags=()
[[ -n ${SKIP_ALL_GAP:-} ]] && flags+=("$SKIP_ALL_GAP")
[[ -n ${VERBOSE:-}      ]] && flags+=("$VERBOSE")

cmd=(
  /usr/bin/podman run
    --rm --replace --name "$CTR_NAME"
    --pull="$PULL_POLICY"
    --cidfile="$CID_FILE"
    --sdnotify=conmon --cgroups=no-conmon
    --cgroup-parent="$CGROUP_PARENT"
    --user "${uid}:${gid}"
    "${limits[@]}"
    --log-driver=journald
    --net=host
    --env ARRAKIS_SERVER
    --cap-drop=ALL --security-opt=no-new-privileges
    -v "${DATA_ROOT}:${DATA_ROOT}"
    "$IMAGE"
    --source arrakis --sink frames
    --replay-id "$REPLAY_ID"
    --channels "${channels[@]}"
    --frame-duration "$FRAME_DURATION"
    --output-dir "$OUTDIR"
    --frame-description "$FRAME_DESCRIPTION"
    --retention-time "$RETENTION_TIME"
    "${flags[@]}" "${extra[@]}"
)

# Record argv in the journal (stderr), then hand off.
{ printf 'exec:'; printf ' %q' "${cmd[@]}"; printf '\n'; } >&2

(( dry_run )) && exit 0
exec "${cmd[@]}"
