# Copyright (C) 2026 Ilker Manap
# SPDX-License-Identifier: AGPL-3.0-or-later

# maas-samba-ad - Samba Active Directory domain controller image for MAAS
#
# Hizli baslangic (build host uzerinde, root olarak):
#   sudo ./scripts/install-deps.sh
#   sudo make image
#   make preseed
#   make upload MAAS_PROFILE=admin
#
SHELL := /bin/bash
.DEFAULT_GOAL := help

# ---------------------------------------------------------------- version settings
# Samba's AD DC comes straight from Debian - no third-party repository is
# involved, so there is nothing to pin beyond the Debian release itself.
DEBIAN_SERIES    ?= trixie
DEBIAN_VERSION   ?= 13

# Packages beyond the domain controller itself.
AD_EXTRA_PACKAGES ?= acl attr net-tools ldap-utils python3-gpg bind9-dnsutils \
                     ethtool ipmitool nvme-cli lsscsi sudo

# ---------------------------------------------------------------- imaj ayarlari
# amd64 | arm64.  arm64 is wired up but has never been built or deployed -
# see "Verified status" in the README.  Building arm64 on an x86_64 host means
# TCG emulation with no KVM, which is very slow; prefer a native arm64 builder.
ARCH             ?= amd64
SUBARCH          ?= generic
BOOT             ?= uefi
TIMEOUT          ?= 3h
PACKER_LOG       ?= 0

# Build VM kaynaklari. Upstream sablon 4G/2CPU/2GB ile gelir; Debian cloud image
# (~3G) plus Samba and its dependencies does not fit in 4G, so we patch it.
# Sonuc tgz yalnizca kullanilan dosyalari icerdiginden buyuk disk imaji sismez.
DISK_SIZE        ?= 16G
BUILD_CPUS       ?= 4
BUILD_MEM        ?= 4096

# --- derleme hizi -------------------------------------------------------------
# stable | daily
#   stable: cloud.debian.org/.../trixie/latest  (sabit URL -> packer onbellegi
#           calisir, tekrarlanan derlemelerde ~350MB indirme yok, tekrarlanabilir)
#   daily : upstream sablonun varsayilani (her gun degisir, onbellek isabet etmez)
DEBIAN_IMAGE_CHANNEL ?= stable

# Tarball sikistirma seviyesi. Upstream --best (9) kullaniyor; 6 belirgin daha
# hizli ve imaj yalnizca ~%2-3 buyuyor. pigz varsa cok cekirdekli calisir.
GZIP_LEVEL       ?= 6

# Yerel APT onbellegi (or. apt-cacher-ng): http://10.0.2.2:3142
# Packer'in user-mode aginda build VM host'u 10.0.2.2 olarak gorur.
# Bos birakilirsa proxy kullanilmaz.  Bkz: make deps-cache
APT_PROXY        ?=

IMAGE_NAME       ?= samba-ad-dc
IMAGE_TITLE      ?= Samba AD Domain Controller (Debian $(DEBIAN_VERSION))

# ---------------------------------------------------------------- yollar
WORKDIR          ?= $(CURDIR)/build
PM_REPO          ?= https://github.com/canonical/packer-maas.git
# Test edilmis upstream commit'e sabitlenmistir. 'main' birakmak, upstream'de
# yapilan bir degisikligin derlemeyi haber vermeden bozmasi anlamina gelir.
# Ileri tasimak icin: PM_REF=main ile derleyip test edin, sonra yeni SHA'yi buraya yazin.
PM_REF           ?= c23d5dd985f52b2eaccc893e886213a424a243a5
PM               := $(WORKDIR)/packer-maas
TPL              := $(PM)/debian

OVERLAY_TGZ      := $(WORKDIR)/adc-maas-overlay.tar.gz
CUSTOMIZE        := $(WORKDIR)/customize-samba-ad.sh
OUTPUT           ?= $(WORKDIR)/$(IMAGE_NAME).tar.gz
PRESEED          := $(WORKDIR)/curtin_userdata_custom_$(ARCH)_$(SUBARCH)_$(IMAGE_NAME)

# ---------------------------------------------------------------- MAAS ayarlari
MAAS_PROFILE     ?= admin
MAAS_ARCH        ?= $(ARCH)/$(SUBARCH)
MAAS_IMAGE_NAME  ?= custom/$(IMAGE_NAME)
# MAAS snap kurulumu icin: /var/snap/maas/current/preseeds
MAAS_PRESEED_DIR ?= /var/snap/maas/current/preseeds

# UEFI firmware, keyed on the TARGET architecture - an aarch64 guest needs
# AAVMF whatever the build host is. (Upstream packer-maas keys this on the host
# architecture instead, which only works when host and target match.)
ifeq ($(strip $(ARCH)),arm64)
FW_DIR           ?= /usr/share/AAVMF
FW               ?= AAVMF
else
FW_DIR           ?= /usr/share/OVMF
FW               ?= OVMF
endif
FW_SFX           ?= $(shell test -f $(FW_DIR)/$(FW)_CODE.fd && echo "" || echo "_4M")

# KVM is only usable when the host and the guest share an architecture.
# Otherwise QEMU falls back to TCG emulation, which is very slow.
HOST_IS_ARM      := $(shell test "$$(uname -m)" = aarch64 && echo true || echo false)

# ---------------------------------------------------------------- hedefler
.PHONY: help deps deps-cache check-upstream print-var checkout overlay customize image verify preseed install-preseed upload clean distclean lint

help:
	@echo "maas-samba-ad - Samba AD Domain Controller MAAS image"
	@echo
	@echo "  make deps             Build host bagimliliklarini kur (root gerekir)"
	@echo "  make deps-cache       Yerel APT onbellegi kur (derlemeyi hizlandirir)"
	@echo "  make image            Imaji derle -> $(OUTPUT)   (root gerekir)"
	@echo "  make verify           Uretilen imajin icerigini dogrula"
	@echo "  make check-upstream   Depodaki surumleri elimizdeki imajla karsilastir"
	@echo "  make preseed          MAAS curtin preseed dosyasini uret"
	@echo "  make install-preseed  Preseed'i $(MAAS_PRESEED_DIR) altina kopyala (root)"
	@echo "  make upload           Imaji MAAS'a yukle (MAAS_PROFILE=$(MAAS_PROFILE))"
	@echo "  make clean            Ara dosyalari sil"
	@echo "  make distclean        build/ dizinini tamamen sil"
	@echo
	@echo "Onemli degiskenler:"
	@echo "  DEBIAN_SERIES=$(DEBIAN_SERIES)  IMAGE_NAME=$(IMAGE_NAME)"
	@echo "  ARCH=$(ARCH)  BOOT=$(BOOT)"
	@echo "  OUTPUT=$(OUTPUT)"

deps:
	./scripts/install-deps.sh

# --- packer-maas deposunu getir -----------------------------------------------
$(PM)/.git:
	@mkdir -p $(WORKDIR)
	git clone $(PM_REPO) $(PM)

# PM_REF bir dal, etiket ya da commit SHA olabilir.
checkout: $(PM)/.git
	@cd $(PM) && git fetch -q --all --tags && git checkout -q -f $(PM_REF) \
	    && (git symbolic-ref -q HEAD >/dev/null && git pull -q --ff-only || true)
	@echo "packer-maas: $$(cd $(PM) && git rev-parse --short HEAD) ($(PM_REF))"

# --- imaja gomulecek overlay ---------------------------------------------------
overlay: $(OVERLAY_TGZ)

$(OVERLAY_TGZ): $(shell find overlay -type f 2>/dev/null)
	@mkdir -p $(WORKDIR)
	COPYFILE_DISABLE=1 tar czf $@ -C overlay --no-xattrs --exclude='.keep' .
	@echo "overlay: $@ ($$(du -h $@ | cut -f1))"

# --- packer'in VM icinde calistiracagi customize script -------------------------
customize: $(CUSTOMIZE)

$(CUSTOMIZE): scripts/customize-samba-ad.sh.in $(OVERLAY_TGZ)
	@mkdir -p $(WORKDIR)
	@sed -e 's|@@DEBIAN_SERIES@@|$(DEBIAN_SERIES)|g' \
	     -e 's|@@AD_EXTRA_PACKAGES@@|$(AD_EXTRA_PACKAGES)|g' \
	     -e 's|@@PM_REF@@|$(PM_REF)|g' \
	     $< > $@
	@echo '__ADC_MAAS_OVERLAY__' >> $@
	@base64 < $(OVERLAY_TGZ) >> $@
	@chmod +x $@
	@echo "customize script: $@"

# --- imaj derleme ---------------------------------------------------------------
image: checkout $(CUSTOMIZE)
	@if [ "$$(id -u)" -ne 0 ]; then echo "HATA: 'make image' root gerektirir (sudo make image)"; exit 1; fi
	@command -v packer >/dev/null || { echo "HATA: packer yok, once 'make deps'"; exit 1; }
	@echo "==> Sablon yamalaniyor: disk=$(DISK_SIZE) cpus=$(BUILD_CPUS) mem=$(BUILD_MEM)"
	sed -i -E 's|^([[:space:]]*disk_size[[:space:]]*=[[:space:]]*).*|\1"$(DISK_SIZE)"|' $(TPL)/debian-cloudimg.pkr.hcl
	sed -i -E 's|^([[:space:]]*cpus[[:space:]]*=[[:space:]]*).*|\1$(BUILD_CPUS)|' $(TPL)/debian-cloudimg.pkr.hcl
	sed -i -E 's|^([[:space:]]*memory[[:space:]]*=[[:space:]]*).*|\1$(BUILD_MEM)|' $(TPL)/debian-cloudimg.pkr.hcl
ifeq ($(strip $(DEBIAN_IMAGE_CHANNEL)),stable)
	@echo "==> Kararli Debian cloud image kullanilacak (packer onbellegi isabet eder)"
	sed -i -E 's|/daily/latest/|/latest/|g; s|-daily\.qcow2|.qcow2|g' $(TPL)/debian-cloudimg.pkr.hcl
	@grep -nE 'iso_url|iso_checksum' $(TPL)/debian-cloudimg.pkr.hcl
endif
	sed -i -E 's|--best --force|-$(GZIP_LEVEL) --force|' $(PM)/scripts/fuse-tar-root
	@grep -nE 'disk_size|^  cpus|^  memory' $(TPL)/debian-cloudimg.pkr.hcl
	cp -v $(FW_DIR)/$(FW)_CODE$(FW_SFX).fd $(TPL)/OVMF_CODE.fd
	cp -v $(FW_DIR)/$(FW)_VARS$(FW_SFX).fd $(TPL)/OVMF_VARS.fd
ifeq ($(strip $(ARCH)),arm64)
	# AAVMF images must be padded to 64 MiB for QEMU's arm64 "virt" machine.
	truncate -s 64m $(TPL)/OVMF_CODE.fd
	truncate -s 64m $(TPL)/OVMF_VARS.fd
endif
	rm -rf $(TPL)/output-cloudimg $(TPL)/seeds-cloudimg.iso
	cd $(TPL) && PACKER_LOG=$(PACKER_LOG) packer init .
	cd $(TPL) && PACKER_LOG=$(PACKER_LOG) packer build \
	    -var debian_series=$(DEBIAN_SERIES) \
	    -var debian_version=$(DEBIAN_VERSION) \
	    -var architecture=$(ARCH) \
	    -var boot_mode=$(BOOT) \
	    -var ovmf_suffix=$(FW_SFX) \
	    -var host_is_arm=$(HOST_IS_ARM) \
	    -var timeout=$(TIMEOUT) \
	    -var customize_script=$(CUSTOMIZE) \
	    -var filename=$(OUTPUT) \
	    -var http_proxy=$(APT_PROXY) \
	    .
	@ls -lh $(OUTPUT)

# --- MAAS preseed ---------------------------------------------------------------
preseed: $(PRESEED)

$(PRESEED): maas/curtin_userdata_custom.in
	@mkdir -p $(WORKDIR)
	@sed -e 's|@@IMAGE_NAME@@|$(IMAGE_NAME)|g' \
	     -e 's|@@ARCH@@|$(ARCH)|g' \
	     $< > $@
	@echo "preseed: $@"
	@echo "  -> MAAS region controller uzerinde $(MAAS_PRESEED_DIR)/ altina kopyalayin"

install-preseed: $(PRESEED)
	@if [ "$$(id -u)" -ne 0 ]; then echo "HATA: root gerekir"; exit 1; fi
	install -D -m 0644 $(PRESEED) $(MAAS_PRESEED_DIR)/$(notdir $(PRESEED))
	@echo "kuruldu: $(MAAS_PRESEED_DIR)/$(notdir $(PRESEED))"

# --- MAAS'a yukleme -------------------------------------------------------------
upload:
	@test -f $(OUTPUT) || { echo "HATA: $(OUTPUT) yok, once 'make image'"; exit 1; }
	maas $(MAAS_PROFILE) boot-resources create \
	    name='$(MAAS_IMAGE_NAME)' \
	    title='$(IMAGE_TITLE)' \
	    architecture='$(MAAS_ARCH)' \
	    filetype='tgz' \
	    content@=$(OUTPUT)

verify:
	@test -f $(OUTPUT) || { echo "HATA: $(OUTPUT) yok, once 'make image'"; exit 1; }
	./scripts/verify-image.sh $(OUTPUT)

# Depoda hangi surumler var, elimizdeki imaj hangi surumde?
check-upstream:
	@echo "==> Available in Debian $(DEBIAN_SERIES):"
	@curl -fsS http://deb.debian.org/debian/dists/$(DEBIAN_SERIES)/main/binary-$(ARCH)/Packages.gz 2>/dev/null \
	  | gunzip \
	  | awk '/^Package: (samba|samba-ad-dc|winbind)$$/{p=$$2; next} \
	         /^Version: /{if(p!=""){print p" "$$2; p=""}}' \
	  | sort -V | awk '{v[$$1]=$$2} END{for(k in v) printf "      %-18s %s\n", k, v[k]}' \
	  || echo "      (could not reach the archive)"
	@echo "==> In the local image ($(OUTPUT)):"
	@if [ -f $(OUTPUT) ]; then \
	    tar xzf $(OUTPUT) -O ./etc/adc-maas/image-info 2>/dev/null | sed 's/^/      /' \
	      || echo "      (image-info unreadable)"; \
	  else echo "      (no image - run 'make image' first)"; fi

# Yerel APT onbellegi - tekrarlanan derlemelerde ~700MB indirmeyi ortadan kaldirir.
# Kurduktan sonra:  sudo make image APT_PROXY=http://10.0.2.2:3142
deps-cache:
	@if [ "$$(id -u)" -ne 0 ]; then echo "HATA: root gerekir (sudo make deps-cache)"; exit 1; fi
	DEBIAN_FRONTEND=noninteractive apt-get install -y apt-cacher-ng
	systemctl enable --now apt-cacher-ng
	@echo
	@echo "Hazir. Derlemede kullanmak icin:"
	@echo "  sudo make image APT_PROXY=http://10.0.2.2:3142"
	@echo "(10.0.2.2 = packer user-mode aginda build host'un adresi)"

# Tek bir degiskenin degerini bas - CI script'leri bunu kullanir.
#   make -s print-var VAR=OUTPUT
print-var:
	@echo "$($(VAR))"

lint:
	@bash -n scripts/customize-samba-ad.sh.in && echo "customize-samba-ad.sh.in: OK"
	@bash -n overlay/usr/local/sbin/adc-maas-init && echo "adc-maas-init: OK"
	@bash -n overlay/usr/local/sbin/adc-sysvol-sync && echo "adc-sysvol-sync: OK"
	@command -v shellcheck >/dev/null && shellcheck -S warning \
	    overlay/usr/local/sbin/adc-maas-init overlay/usr/local/sbin/adc-sysvol-sync \
	    scripts/install-deps.sh || true

clean:
	rm -f $(OVERLAY_TGZ) $(CUSTOMIZE) $(PRESEED)
	rm -rf $(TPL)/output-cloudimg $(TPL)/seeds-cloudimg.iso \
	       $(TPL)/OVMF_CODE.fd $(TPL)/OVMF_VARS.fd

distclean:
	rm -rf $(WORKDIR)
