#!/bin/sh
# logpulse-agent installer
#
# Usage:
#   curl -fsSL https://get.logpulse.io | sudo sh
#   curl -fsSL https://get.logpulse.io | LOGPULSE_VERSION=v0.1.0 sudo sh
#
# What this does:
#   1. Detects OS/arch
#   2. Downloads the version-specific tarball + SHA-256 checksum
#   3. Verifies the checksum
#   4. (Optional) Verifies the cosign signature if cosign is installed
#   5. Creates the `logpulse` system user + state/log/config dirs
#   6. Installs the binary to /usr/local/bin and the systemd unit
#
# Audit before running:
#   curl -fsSL https://get.logpulse.io | less
#
# Source: https://github.com/Layer-Group/LogPulse/tree/main/apps/agent/installer
set -eu

DOWNLOADS_BASE="${LOGPULSE_DOWNLOADS_BASE:-https://dl.logpulse.io}"
INSTALL_DIR="/opt/logpulse-agent"
STATE_DIR="/var/lib/logpulse-agent"
LOG_DIR="/var/log/logpulse-agent"
CONFIG_DIR="/etc/logpulse-agent"
SERVICE_USER="logpulse"
# /usr/bin (not /usr/local/bin) so that sudo's secure_path picks it up on
# RHEL/Rocky/Alma — those distros omit /usr/local/bin from the default
# sudoers secure_path. Same convention as Datadog and Tailscale.
BIN_LINK="/usr/bin/logpulse-agent"

err() { printf 'error: %s\n' "$1" >&2; exit 1; }
info() { printf '==> %s\n' "$1"; }

# --- Pre-flight checks ----------------------------------------------------

[ "$(id -u)" -eq 0 ] || err "must run as root (try: curl … | sudo sh)"

OS_NAME="$(uname -s | tr '[:upper:]' '[:lower:]')"
[ "$OS_NAME" = "linux" ] || err "only Linux is supported in v1 (got: $OS_NAME)"

case "$(uname -m)" in
  x86_64|amd64)  ARCH=amd64 ;;
  aarch64|arm64) ARCH=arm64 ;;
  *) err "unsupported architecture: $(uname -m)" ;;
esac

command -v curl >/dev/null 2>&1 || err "curl is required"
command -v tar  >/dev/null 2>&1 || err "tar is required"
command -v sha256sum >/dev/null 2>&1 || err "sha256sum is required"
command -v systemctl >/dev/null 2>&1 || err "systemd is required"

# --- Resolve version ------------------------------------------------------

if [ -n "${LOGPULSE_VERSION:-}" ]; then
  VERSION="$LOGPULSE_VERSION"
else
  info "fetching latest version"
  VERSION="$(curl -fsSL "$DOWNLOADS_BASE/latest.txt" | tr -d '[:space:]')"
fi
[ -n "$VERSION" ] || err "could not determine version to install"
info "installing logpulse-agent $VERSION ($OS_NAME/$ARCH)"

# --- Download + verify tarball -------------------------------------------

TARBALL="logpulse-agent_${VERSION}_${OS_NAME}_${ARCH}.tar.gz"
URL="$DOWNLOADS_BASE/$VERSION/$TARBALL"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

info "downloading $TARBALL"
curl -fsSL -o "$TMP/$TARBALL"        "$URL"
curl -fsSL -o "$TMP/$TARBALL.sha256" "$URL.sha256"

info "verifying SHA-256 checksum"
( cd "$TMP" && sha256sum -c "$TARBALL.sha256" >/dev/null ) \
  || err "checksum mismatch — refusing to install"

if command -v cosign >/dev/null 2>&1; then
  info "verifying cosign signature"
  curl -fsSL -o "$TMP/$TARBALL.sig" "$URL.sig" 2>/dev/null || {
    printf 'warn: cosign signature not found at %s.sig — continuing\n' "$URL"
  }
  if [ -f "$TMP/$TARBALL.sig" ]; then
    cosign verify-blob \
      --certificate-identity-regexp "https://github\.com/Layer-Group/LogPulse/.github/workflows/release-agent\.yml@refs/tags/.*" \
      --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
      --signature "$TMP/$TARBALL.sig" \
      "$TMP/$TARBALL" \
      || err "cosign verification failed — refusing to install"
  fi
else
  printf 'note: cosign not installed; skipping signature verification (sha256 still verified)\n'
fi

# --- Create user + dirs ---------------------------------------------------

if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then
  info "creating system user '$SERVICE_USER'"
  useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER"
fi

# /etc/logpulse-agent must be writable by the agent user — Vector config is
# rewritten there on every successful config poll. `install -d` is idempotent
# and also fixes ownership on existing installs (was root:root 0755 in v0.1.4
# and earlier; the agent failed to write vector.yaml.tmp).
install -d -o "$SERVICE_USER" -g "$SERVICE_USER" -m 0750 "$STATE_DIR" "$LOG_DIR" "$CONFIG_DIR"

# --- Extract --------------------------------------------------------------

info "extracting to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
tar -xzf "$TMP/$TARBALL" -C "$INSTALL_DIR"

# Normalise permissions. Tarballs produced by `mktemp -d` carried a 0700
# root mode through to the install dir, blocking the unprivileged
# `logpulse` service user from traversing /opt/logpulse-agent. Force
# 0755 on dirs and preserve 0755 on the binary; non-exec files keep their
# stored mode. This is idempotent — safe to re-run.
chmod -R u+rwX,go+rX "$INSTALL_DIR"

# --- Wire up binary + systemd --------------------------------------------

ln -sf "$INSTALL_DIR/bin/logpulse-agent" "$BIN_LINK"

# Best-effort cleanup of the v0.1.0 layout where the symlink lived in
# /usr/local/bin. Harmless if it never existed.
rm -f /usr/local/bin/logpulse-agent

if [ -f "$INSTALL_DIR/systemd/logpulse-agent.service" ]; then
  install -m 0644 "$INSTALL_DIR/systemd/logpulse-agent.service" /etc/systemd/system/logpulse-agent.service
  systemctl daemon-reload
fi

# --- Vector dependency ---------------------------------------------------
# The agent shells out to `vector validate` and starts Vector as a child
# process. Without Vector on PATH, no logs are collected.
#
# We install Vector from the official timber.io package repositories, which
# is the same path Vector's own docs recommend. Set LOGPULSE_INSTALL_VECTOR=0
# to skip (e.g. if you manage Vector via your own configuration management).

install_vector() {
  if command -v vector >/dev/null 2>&1; then
    info "vector already installed: $(vector --version 2>&1 | head -1)"
    return 0
  fi

  if command -v dnf >/dev/null 2>&1; then
    info "adding Vector RPM repository (timber.io)"
    curl -1sLf 'https://repositories.timber.io/public/vector/cfg/setup/bash.rpm.sh' | bash
    info "installing vector via dnf"
    dnf install -y vector
  elif command -v yum >/dev/null 2>&1; then
    info "adding Vector RPM repository (timber.io)"
    curl -1sLf 'https://repositories.timber.io/public/vector/cfg/setup/bash.rpm.sh' | bash
    info "installing vector via yum"
    yum install -y vector
  elif command -v apt-get >/dev/null 2>&1; then
    info "adding Vector DEB repository (timber.io)"
    curl -1sLf 'https://repositories.timber.io/public/vector/cfg/setup/bash.deb.sh' | bash
    info "installing vector via apt-get"
    apt-get install -y vector
  else
    printf 'warn: cannot auto-install Vector on this distribution.\n' >&2
    printf 'warn: install manually: https://vector.dev/docs/setup/installation/\n' >&2
    return 1
  fi
}

if [ "${LOGPULSE_INSTALL_VECTOR:-1}" = "1" ]; then
  install_vector || printf 'warn: Vector install failed — agent will not collect logs until Vector is installed.\n' >&2
else
  info "skipping Vector install (LOGPULSE_INSTALL_VECTOR=0)"
fi

# Restart only if the service is currently running. Never start a service that
# was deliberately stopped — the operator may have stopped it intentionally.
if systemctl is-active --quiet logpulse-agent 2>/dev/null; then
  info "restarting logpulse-agent to load the new binary"
  systemctl restart logpulse-agent
fi

# --- Done -----------------------------------------------------------------

cat <<EOF

LogPulse Agent $VERSION installed.

Next steps:
  sudo logpulse-agent enroll --token=<ENROLLMENT_TOKEN> [--group=<slug>]
  sudo systemctl enable --now logpulse-agent

Logs:    journalctl -u logpulse-agent -f
Status:  logpulse-agent status
Docs:    https://logpulse.io/docs/agents
EOF
