#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

set -e

UNIT_DIR="${1:-/tmp}"

cmdline=( $(</proc/cmdline) )
cmdline_arg() {
    local name="$1" value="$2"
    for arg in "${cmdline[@]}"; do
        if [[ "${arg%%=*}" == "${name}" ]]; then
            value="${arg#*=}"
        fi
    done
    echo "${value}"
}

cmdline_bool() {
    local value=$(cmdline_arg "$@")
    case "$value" in
        ""|0|no|off) return 1;;
        *) return 0;;
    esac
}

add_requires() {
    local name="$1"; shift
    local target="$1"; shift
    local requires_dir="${UNIT_DIR}/${target}.requires"
    mkdir -p "${requires_dir}"
    ln -sf "../${name}" "${requires_dir}/${name}"
}

# This can't be done with ConditionKernelCommandLine because that always
# starts the unit's dependencies. We want to start networkd only on first
# boot.
if $(cmdline_bool 'ignition.firstboot' 0); then
    add_requires ignition-complete.target initrd.target
    for svc in fetch disks files mount ask-var-mount; do
        add_requires ignition-${svc}.service ignition-complete.target
    done
    add_requires coreos-teardown-initramfs-network.service ignition-complete.target
    #if [[ $(cmdline_arg coreos.oem.id) == "packet" ]]; then
    #    add_requires coreos-static-network.service
    #fi

    # On EC2, shut down systemd-networkd if ignition fails so that the instance
    # fails EC2 instance checks.
    #if [[ $(cmdline_arg coreos.oem.id) == "ec2" ]]; then
    #    mkdir -p ${UNIT_DIR}/systemd-networkd.service.d
    #    cat > ${UNIT_DIR}/systemd-networkd.service.d/10-conflict-emergency.conf <<EOF
#[Unit]
#Conflicts=emergency.target
#Conflicts=emergency.service
#Conflicts=dracut-emergency.service
#EOF
    #fi
else
    # If we're doing a non-Ignition (subsequent) boot, then
    # queue a different target.  This is necessary so that units
    # like `ignition-ostree-mount-sysroot.service`
    # can cleanly distinguish between the two.
    add_requires ignition-subsequent.target initrd.target
fi

# Write ignition-setup.service customized for PXE/ISO or regular boot
cat > ${UNIT_DIR}/ignition-setup.service <<EOF
[Unit]
Description=Ignition (setup)
DefaultDependencies=false
Before=initrd.target

# Make sure if ExecStart= fails, the boot fails
OnFailure=emergency.target
OnFailureJobMode=isolate

Requires=local-fs-pre.target
Before=local-fs-pre.target
Before=ignition-disks.service
Before=ignition-files.service

Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/run/ignition.env
# The MountFlags=slave is so the umount of /boot is guaranteed to happen
# /boot will only be mounted for the lifetime of the unit.
MountFlags=slave
ExecStart=/usr/sbin/ignition-setup
EOF

RANDOMIZE_DISK_GUID=$(cmdline_arg coreos.randomize_disk_guid)
if [ -n "$RANDOMIZE_DISK_GUID" ]; then
    escaped_guid=$(systemd-escape --path "/dev/disk/by-diskuuid/$RANDOMIZE_DISK_GUID")
    add_requires "disk-uuid@${escaped_guid}.service"
fi

oemid=$(cmdline_arg coreos.oem.id)
# Compatibility Ignition 2 (impl spec 3) as created by coreos-assembler
if [ -z "${oemid}" ]; then
    platformid=$(cmdline_arg ignition.platform.id)
    case "${platformid}" in
        aws) oemid=ec2;;
        gcp) oemid=gce;;
        *) oemid=${platformid}
    esac
fi

if [[ "${oemid}" == "digitalocean" ]]; then
    add_requires coreos-digitalocean-network.service
fi

echo "OEM_ID=${oemid}" > /run/ignition.env
