#!/bin/sh
# Dynamically adds After=apparmor.service to open-vm-tools units ONLY on VMware hypervisors.
#
# WHY ConditionVirtualization ALONE IS INSUFFICIENT:
# Systemd constructs its transaction and ordering graph (processing Before= and After= directives)
# when building the boot sequence long BEFORE it evaluates ConditionVirtualization= at runtime.
#
# If open-vm-tools.service statically defines both "After=apparmor.service" and "Before=cloud-init-local.service",
# systemd builds a transitive dependency chain:
#   apparmor.service -> open-vm-tools.service -> cloud-init-local.service
#
# On non-VMware platforms, ConditionVirtualization=vmware evaluates to false and skips running open-vm-tools,
# but systemd STILL enforces the ordering chain. Consequently, cloud-init-local.service is blocked from
# starting until apparmor.service finishes loading.
#
# Moving "After=apparmor.service" into this early boot generator ensures the dependency edge is only added to
# the systemd graph when actually running inside a VMware virtual machine.

set -e

NORMAL_DIR="$1"

# $SYSTEMD_VIRTUALIZATION is set by systemd (v251+) to "type:implementation" (e.g., "vm:vmware").
# https://www.freedesktop.org/software/systemd/man/latest/systemd.generator.html?#%24SYSTEMD_VIRTUALIZATION
# >=Noble use this, but Jammy is older, so we have to call systemd-detect-virt

# Exit cleanly if systemd-detect-virt is missing (e.g., inside minimal build environments)
if ! command -v systemd-detect-virt >/dev/null 2>&1; then
    exit 0
fi

# If not running directly in VMware, exit without creating drop-ins
VIRT_TYPE=$(systemd-detect-virt 2>/dev/null || true)
if [ "$VIRT_TYPE" != "vmware" ]; then
    exit 0
fi

# Dynamically inject the ordering drop-in for VMware environments
for SVC in open-vm-tools.service vgauth.service; do
    DROPIN_DIR="${NORMAL_DIR}/${SVC}.d"
    mkdir -p "${DROPIN_DIR}"
    cat <<EOF > "${DROPIN_DIR}/10-open-vm-tools-apparmor-ordering-on-vmware.conf"
# Automatically generated by open-vm-tools-apparmor-generator
[Unit]
After=apparmor.service
EOF
done

exit 0
