.PHONY: all install install-etc install-var uninstall pre-requisites clean dryrun .PHONY: tail-logs butane help fcos-vm clean-vm console units units-pre .PHONY: clean-pre clean-post install-pre install-post uninstall-pre uninstall-post .PHONY: install-files install-files-pre install-files-post install-actions .PHONY: install-actions-pre install-actions-post all: help help: @echo "Available targets:" @echo " help - Show this help message" @echo " install - Install quadlets and systemd units" @echo " uninstall - Uninstall quadlets and systemd units" @echo " clean - Remove the quadlets persistent data and configuration" @echo " dryrun - Perform a dry run of the podman systemd generator" @echo " tail-logs - Tail the logs of the quadlet units" @echo " butane - Build Butane specifications suitable for Fedora CoreOS" @echo " fcos-vm - Launch a Fedora CoreOS VM with the generated Butane spec" @echo " clean-vm - Clean up the Fedora CoreOS VM and its resources" @echo " console - Connect to the Fedora CoreOS VM console" TARGET_CHROOT ?= PROJECT_NAME := $(shell basename "$${PWD}") QUADLETS_FILES = $(wildcard *.container *.volume *.network *.pod *.build) SYSTEMD_FILES = $(wildcard *.service *.target *.timer *.mount) SYSTEMD_UNIT_NAMES := $(wildcard *.service *.target *.timer *.mount) SYSTEMD_TIMER_NAMES := $(wildcard *.timer) SYSTEMD_MAIN_UNIT_NAMES := $(wildcard *.target) QUADLET_UNIT_NAMES := $(patsubst %.container, %.service, $(wildcard *.container)) \ $(patsubst %.volume, %-volume.service, $(wildcard *.volume)) \ $(patsubst %.network, %-network.service, $(wildcard *.network)) \ $(patsubst %.pod, %-pod.service, $(wildcard *.pod)) \ $(patsubst %.build, %-build.service, $(wildcard *.build)) CONFIG_FILES = $(wildcard config/*) TMPFILESD_FILES = $(wildcard tmpfiles.d/*) SYSCTLD_FILES = $(wildcard sysctl.d/*) TARGET_QUADLETS_FILES = $(addprefix $(TARGET_CHROOT)/etc/containers/systemd/, $(QUADLETS_FILES)) TARGET_SYSTEMD_FILES = $(addprefix $(TARGET_CHROOT)/etc/systemd/system/, $(SYSTEMD_FILES)) TARGET_CONFIG_FILES = $(patsubst config/%, $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)/%, $(CONFIG_FILES)) TARGET_FILES = $(TARGET_QUADLETS_FILES) $(TARGET_SYSTEMD_FILES) $(TARGET_CONFIG_FILES) TARGET_TMPFILESD_FILES = $(patsubst tmpfiles.d/%, $(TARGET_CHROOT)/etc/tmpfiles.d/%, $(TMPFILESD_FILES)) TARGET_SYSCTLD_FILES = $(patsubst sysctl.d/%, $(TARGET_CHROOT)/etc/sysctl.d/%, $(SYSCTLD_FILES)) DEPENDENCIES ?= I_KNOW_WHAT_I_AM_DOING ?= DEPENDENCIES_IGNITION_FILES = $(shell for dep in $(DEPENDENCIES); do echo $(TOP_LEVEL_DIR)/$$dep/$$dep.ign; done) PROJECT_UID ?= 0 PROJECT_GID ?= 0 pre-requisites: @if [ -z "$(TOP_LEVEL_DIR)" ]; then \ echo "Do not run this Makefile from the top-level directory!" >&2; \ exit 1; \ fi ; \ if [ "$$(id -u)" -ne 0 ]; then \ echo "This Makefile must be run as root" >&2; \ exit 1; \ fi dryrun: QUADLET_UNIT_DIRS="$$PWD" /usr/lib/systemd/system-generators/podman-system-generator -dryrun > /dev/null $(TARGET_CHROOT)/etc/containers/systemd: install -D -d -m 0755 -o root -g root $@ $(TARGET_CHROOT)/etc/systemd/system: install -D -d -m 0755 -o root -g root $@ $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME): install -D -d -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) $@ $(TARGET_CHROOT)/etc/tmpfiles.d: install -D -d -m 0755 -o root -g root $@ $(TARGET_CHROOT)/etc/sysctl.d: install -D -d -m 0755 -o root -g root $@ $(TARGET_CHROOT)/etc/containers/systemd/%: % $(TARGET_CHROOT)/etc/containers/systemd install -m 0644 -o root -g root $< $@ $(TARGET_CHROOT)/etc/systemd/system/%: % $(TARGET_CHROOT)/etc/systemd/system install -m 0644 -o root -g root $< $@ $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)/%: config/% $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME) @run() { echo $$*; "$$@"; }; \ if [ -x $< ]; then \ run install -D -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) $< $@; \ else \ run install -D -m 0644 -o $(PROJECT_UID) -g $(PROJECT_GID) $< $@; \ fi $(TARGET_CHROOT)/var/lib/quadlets/$(PROJECT_NAME): install -d -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) $@ $(TARGET_CHROOT)/etc/tmpfiles.d/%: tmpfiles.d/% $(TARGET_CHROOT)/etc/tmpfiles.d install -D -m 0644 -o root -g root $< $@ $(TARGET_CHROOT)/etc/sysctl.d/%: sysctl.d/% $(TARGET_CHROOT)/etc/sysctl.d install -D -m 0644 -o root -g root $< $@ install-etc: $(TARGET_QUADLETS_FILES) $(TARGET_SYSTEMD_FILES) $(TARGET_CONFIG_FILES) $(TARGET_TMPFILESD_FILES) $(TARGET_SYSCTLD_FILES) install-var: $(TARGET_CHROOT)/var/lib/quadlets/$(PROJECT_NAME) install-files-pre:: @run() { echo $$*; "$$@"; }; \ for dep in $(DEPENDENCIES); do \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-files; \ done install-files: install-files-pre install-etc install-var $(MAKE) install-files-post install-files-post:: install-actions-pre:: @run() { echo $$*; "$$@"; }; \ for dep in $(DEPENDENCIES); do \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-actions; \ done install-actions: install-actions-pre systemctl daemon-reload systemd-analyze --generators=true verify $(QUADLET_UNIT_NAMES) $(SYSTEMD_UNIT_NAMES) @run() { echo $$*; "$$@"; }; \ if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \ run systemd-tmpfiles --create /etc/tmpfiles.d/$(PROJECT_NAME).conf; \ fi; \ if [ -f /etc/sysctl.d/$(PROJECT_NAME).conf ]; then \ run sysctl -q -p /etc/sysctl.d/$(PROJECT_NAME).conf; \ fi systemctl enable $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) systemctl start $(SYSTEMD_MAIN_UNIT_NAMES) $(MAKE) install-actions-post install-pre:: install-post:: install: pre-requisites dryrun install-pre $(MAKE) install-files $(MAKE) install-actions $(MAKE) install-post uninstall-pre:: uninstall-post:: @run() { echo $$*; "$$@"; }; \ for dep in $(DEPENDENCIES); do \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep uninstall; \ done uninstall: pre-requisites uninstall-pre systemctl disable $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) || true systemctl stop $(SYSTEMD_UNIT_NAMES) $(QUADLET_UNIT_NAMES) || true @run() { echo $$*; "$$@"; }; \ if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \ run systemd-tmpfiles --purge /etc/tmpfiles.d/$(PROJECT_NAME).conf; \ fi rm -f $(TARGET_QUADLETS_FILES) $(TARGET_SYSTEMD_FILES) $(TARGET_CONFIG_FILES) systemctl daemon-reload $(MAKE) uninstall-post tail-logs: pre-requisites @run() { echo $$*; "$$@"; }; \ declare -a journalctl_args=( -f ); \ for unit in $$($(MAKE) -s units 2>/dev/null | sort -u); do \ journalctl_args+=( -u "$$unit" ); \ done; \ run journalctl "$${journalctl_args[@]}" $(PROJECT_NAME).bu: install-files @if [ -z "$(TARGET_CHROOT)" ]; then \ echo "TARGET_CHROOT is not set!"; exit 1; \ fi $(TOP_LEVEL_DIR)/generate-butane-spec.sh $(TARGET_CHROOT) $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) > $(PROJECT_NAME).bu $(PROJECT_NAME).ign: butane butane --strict -o $(PROJECT_NAME).ign $(PROJECT_NAME).bu butane: @run() { echo $$*; "$$@"; }; \ if [ -z "$(TARGET_CHROOT)" ]; then \ run $(MAKE) TARGET_CHROOT=$$(mktemp -d /tmp/butane-XXXXXX) $(PROJECT_NAME).bu; \ else \ run $(MAKE) $(PROJECT_NAME).bu; \ fi $(TOP_LEVEL_DIR)/local.ign: $(TOP_LEVEL_DIR)/local.bu butane --strict -o $@ $< # Because we don't know how to build this file, it is safer to declare it as phony and let the Makefile of the dependency handle it. .PHONY: $(DEPENDENCIES_IGNITION_FILES) $(DEPENDENCIES_IGNITION_FILES): $(MAKE) -C $(dir $@) $(notdir $@) fcos.ign: fcos.bu $(TOP_LEVEL_DIR)/local.ign $(PROJECT_NAME).ign $(DEPENDENCIES_IGNITION_FILES) @run() { echo $$*; "$$@"; }; \ tmp=$$(mktemp -d /tmp/butane-XXXXXX); \ run cp $(filter %.ign,$^) $$tmp; \ run butane --strict -d $$tmp -o $@ fcos.bu; \ run rm -rf $$tmp /var/lib/libvirt/images/library/fedora-coreos.qcow2: @run() { echo $$*; "$$@"; }; \ run mkdir -p /var/lib/libvirt/images/library/ ; \ if ! run coreos-installer download -p qemu -f qcow2.xz -d -C /var/lib/libvirt/images/library/ ; then \ echo "CoreOS QCOW2 image could not be downloaded." >&2; \ exit 1; \ fi ; \ qcow2=$$(ls -1ctr /var/lib/libvirt/images/library/fedora-coreos-*.qcow2 | tail -n 1) ; \ run mv "$$qcow2" $@ /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign: fcos.ign install -D -o root -g root -m 0644 $< $@ /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2: /var/lib/libvirt/images/library/fedora-coreos.qcow2 install -D -o root -g root -m 0644 $< $@ /srv/fcos-$(PROJECT_NAME): install -d -o root -g root -m 0755 $@ fcos-vm: pre-requisites clean-vm /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2 /srv/fcos-$(PROJECT_NAME) virt-install --name=fcos-$(PROJECT_NAME) --import --noautoconsole \ --ram=4096 --vcpus=2 --os-variant=fedora-coreos-stable \ --disk path=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2,format=qcow2,size=50 \ --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign" \ --network network=default,model=virtio \ --console=pty,target.type=virtio --serial=pty --graphics=none --boot=uefi \ --memorybacking=access.mode=shared,source.type=memfd \ --filesystem=type=mount,accessmode=passthrough,driver.type=virtiofs,driver.queue=1024,source.dir=/srv/fcos-$(PROJECT_NAME),target.dir=data clean-vm: pre-requisites virsh destroy fcos-$(PROJECT_NAME) || true virsh undefine fcos-$(PROJECT_NAME) --nvram || true rm -rf /var/lib/libvirt/images/fcos-$(PROJECT_NAME) rm -rf /srv/fcos-$(PROJECT_NAME) console: pre-requisites @while sleep 2; do virsh console fcos-$(PROJECT_NAME); echo -e "Disconnected. Reconnecting in 2 seconds...\nPress Ctrl-C to abort.\n"; done units-pre:: @for dep in $(DEPENDENCIES); do \ $(MAKE) -s -C $(TOP_LEVEL_DIR)/$$dep units 2>/dev/null; \ done units: units-pre @for unit in $(SYSTEMD_UNIT_NAMES) $(QUADLET_UNIT_NAMES); do echo "$$unit"; done clean-pre:: @run() { echo $$*; "$$@"; }; \ for dep in $(DEPENDENCIES); do \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep clean; \ done clean-post:: clean: clean-pre pre-requisites rm -f *.butane @run() { echo $$*; "$$@"; }; \ if [ "$(I_KNOW_WHAT_I_AM_DOING)" != "yes" ]; then \ read -p "This will remove all data of '$(PROJECT_NAME)'. Are you sure? (only 'yes' is accepted) " ans; \ if [ "$$ans" != "yes" ] && [ "$$ans" != "YES" ]; then \ echo "Aborted."; exit 1; \ fi; \ fi rm -rf /var/lib/quadlets/$(PROJECT_NAME)/ /var/run/quadlets/$(PROJECT_NAME)/ /etc/quadlets/$(PROJECT_NAME)/ $(MAKE) clean-post