#!/bin/bash
## kola:
##   # Marked as exclusive as we layer content over /usr with sysexts
##   exclusive: true
##   # Limited to FCOS for now as we don't have easy access to repos on RHCOS
##   distros: fcos
##   # Limited to x86_64 & aarch64 for now (see inline TODO)
##   architectures: "x86_64 aarch64"
##   # Should work the same on all platforms
##   # Needs internet access to download RPMs to build sysexts
##   tags: "platform-independent needs-internet"
##   description: Verify building, setting up and enabling systemd system extensions (sysexts)

set -xeuo pipefail

# shellcheck disable=SC1091
. "$KOLA_EXT_DATA/commonlib.sh"

# Install tools that we need to build the sysexts
rpm-ostree install --apply-live erofs-utils lz4

build_sysext(){
  local -r rpm="${1}"

  tmpdir="/tmp/sysext-${rpm}"
  mkdir "${tmpdir}"
  pushd "${tmpdir}" > /dev/null

  mkdir -p "rpms"
  pushd "rpms" > /dev/null

  # Download RPMs:
  # - Resolve dependency relative to the current root
  # - Only get packages for the current arch and arch independent ones
  # - Disable the OpenH264 repo as it's a frequent source of flakes
  printf "[main]\nskip_system_repo_lock=true" > dnf_config
  dnf download \
      --config=dnf_config \
      --resolve \
      --arch="noarch" \
      --arch="$(arch)" \
      --disablerepo=fedora-cisco-openh264 \
      "${rpm}"

  # Figure out version to use
  pkg="$(ls ${rpm}-*.rpm | sort -h | head -1)"
  epoch="$(rpm -qp --queryformat '%{EPOCH}' ${pkg})"
  version="$(rpm -qp --queryformat '%{VERSION}-%{RELEASE}' ${pkg})"
  if [[ "${epoch}" == "(none)" ]]; then
      epoch=""
  else
      epoch="${epoch}-"
  fi
  version="${epoch}${version}"

  popd > /dev/null

  mkdir rootfs
  pushd rootfs > /dev/null

  # Post process architecture to match systemd architecture list
  # TODO: Figure out the mapping for other architectures
  if [[ "$(arch)" == "x86_64" ]]; then
      arch="x86-64"
  elif [[ "$(arch)" == "aarch64" ]]; then
      arch="arm64"
  else
      echo "Unsupported architecture"
      exit 1
  fi

  id="$(source /etc/os-release; echo "${ID}")"
  version_id="$(source /etc/os-release; echo "${VERSION_ID}")"

  # Write extension config file
  install -d -m0755 usr/lib/extension-release.d
  {
  echo "ID=\"${id}\""
  echo "VERSION_ID=\"${version_id}\""
  echo "ARCHITECTURE=\"${arch}\""
  } | tee "usr/lib/extension-release.d/extension-release.${rpm}"

  # Extract the RPMs
  for r in ../rpms/*.rpm; do
    echo "Extracting: $(basename ${r})"
    rpm2cpio "${r}" > ${r}.tar
    cpio -idmv &> /dev/null < ${r}.tar
    rm ${r}.tar
  done

  # Reset SELinux labels
  filecontexts="/etc/selinux/targeted/contexts/files/file_contexts"
  setfiles -r . ${filecontexts} . && chcon --user=system_u --recursive .

  popd > /dev/null

  # Create the EROFS image
  name="${rpm}-${version}-${version_id}-${arch}.raw"
  mkfs.erofs -zlz4 "${name}" rootfs
  mv "${name}" /tmp

  popd > /dev/null
}

build_sysext "python3"

# Setup folders
install -d -m 0755 -o 0 -g 0 /var/lib/extensions /var/lib/extensions.d
restorecon -RFv /var/lib/extensions /var/lib/extensions.d
systemctl enable --now systemd-sysext.service

install_sysext() {
  local -r name="${1}"
  mv "/tmp/${name}"*".raw" "/var/lib/extensions.d"
  ln -snf "/var/lib/extensions.d/${name}"*".raw" "/var/lib/extensions/${name}.raw"
  restorecon -RFv "/var/lib/extensions.d" "/var/lib/extensions"
}

install_sysext python3

systemctl restart systemd-sysext.service
systemd-sysext status

if [[ ! -f "/usr/bin/python3" ]]; then
    fatal "python3 binary not found but sysext enabled"
fi

if [[ "$(/usr/bin/python3 -c 'print("python3-on-fcos-via-sysext")')" != "python3-on-fcos-via-sysext" ]]; then
    fatal "could not execute simple Python command"
fi

uninstall_sysext() {
  local -r name="${1}"
  rm "/var/lib/extensions/${name}.raw"
  rm "/var/lib/extensions.d/${name}-"*".raw"
}

uninstall_sysext python3

systemctl restart systemd-sysext.service
systemd-sysext status

if [[ -f "/usr/bin/python3" ]]; then
    fatal "python3 binary found but sysext disabled"
fi

ok "systemd system extensions functional"
