From d114e0a551120088e80af7cf06c3cfabe17dc9c8 Mon Sep 17 00:00:00 2001 From: Michael Janczyk Date: Wed, 2 Aug 2023 16:19:22 +0200 Subject: Makefile great again hcl2: test of new hcl2 packer templates. --- .gitignore | 2 + hcl2/Makefile | 287 ++++++++++++++++++++++++++++++ hcl2/alma-9-x86_64/base.pkrvars.hcl | 19 ++ hcl2/alma-9-x86_64/http/anaconda-ks.cfg | 56 ++++++ hcl2/base.pkr.hcl | 25 +++ hcl2/centos-9-x86_64/base.pkrvars.hcl | 19 ++ hcl2/centos-9-x86_64/http/anaconda-ks.cfg | 56 ++++++ hcl2/flavor.pkr.hcl | 28 +++ hcl2/rocky-9-x86_64/base.pkrvars.hcl | 19 ++ hcl2/rocky-9-x86_64/http/anaconda-ks.cfg | 56 ++++++ hcl2/source.pkr.hcl | 26 +++ hcl2/variables.pkr.hcl | 124 +++++++++++++ 12 files changed, 717 insertions(+) create mode 100644 hcl2/Makefile create mode 100644 hcl2/alma-9-x86_64/base.pkrvars.hcl create mode 100644 hcl2/alma-9-x86_64/http/anaconda-ks.cfg create mode 100644 hcl2/base.pkr.hcl create mode 100644 hcl2/centos-9-x86_64/base.pkrvars.hcl create mode 100644 hcl2/centos-9-x86_64/http/anaconda-ks.cfg create mode 100644 hcl2/flavor.pkr.hcl create mode 100644 hcl2/rocky-9-x86_64/base.pkrvars.hcl create mode 100644 hcl2/rocky-9-x86_64/http/anaconda-ks.cfg create mode 100644 hcl2/source.pkr.hcl create mode 100644 hcl2/variables.pkr.hcl diff --git a/.gitignore b/.gitignore index 0ef3cd0..8ec13af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +ansible-* +builds/ qemu/ virtualbox-iso/ vmware-iso/ diff --git a/hcl2/Makefile b/hcl2/Makefile new file mode 100644 index 0000000..77fe366 --- /dev/null +++ b/hcl2/Makefile @@ -0,0 +1,287 @@ +# Simple Makefile to build base VM images using packer and ansible +# TODO +# * support ssh as user instead of root +# * testing target +PACKER ?= packer +ANSIBLE_DIR_BOOT ?= ansible-dracut +ANSIBLE_DIR_PROV ?= ansible-roles-prov +HASHER ?= sha256sum +SHELL := /usr/bin/env bash +BUILDS := builds + +ARCH := $(shell uname -m | sed 's/i686/i386/') + +AVAILABLE_BUILDERS := QEMU +BUILDER_QEMU_EXE := qemu-system-$(ARCH) +BUILDER_QEMU_NAME := qemu +BUILDER_QEMU_PROV := $(BUILDER_QEMU_NAME) + +BUILDERS := qemu + +override BUILDER = qemu +override PROVISIONER = qemu + +# The packer templates, detected as *.json (excluding base.json) +TEMPLATES := $(patsubst %/,%,$(dir $(wildcard */base.pkrvars.hcl))) + +# The provisioning flavors, detected as ansible-/setup-.yml +# Find all paths beginnig with "ansible-" and and save this suffix in PATTERNS +PATTERNS := $(patsubst ansible-%, %, $(wildcard ansible-*)) +# Extract from ansible-/setup-.yml using PATTERNS as +FLAVORS := $(foreach p, $(PATTERNS), \ + $(patsubst ansible-$(p)/setup-$(p).yml, $(p), \ + $(wildcard ansible-$(p)/setup-$(p).yml))) +# Extra flavor from variable ANSIBLE_DIR_PROV, using pattern ANSIBLE_DIR_PROV/setup-.yml +FLAVORS += $(patsubst $(ANSIBLE_DIR_PROV)/setup-%.yml,%, \ + $(wildcard $(ANSIBLE_DIR_PROV)/setup-*.yml)) +FLAVORS := $(strip $(FLAVORS)) + +BASETARGETS := $(strip $(foreach t, $(TEMPLATES), $(t)/base)) +PROVTARGETS := $(strip $(foreach t, $(TEMPLATES), \ + $(foreach f, $(FLAVORS), $(t)/$(f)))) +PROVIMAGES := $(strip $(foreach t, $(TEMPLATES), \ + $(foreach f, $(FLAVORS), $(t)/$(f): %/$(f): %/base))) +REPROVTARGETS := $(strip $(foreach t, $(TEMPLATES), \ + $(foreach f, $(FLAVORS), \ + $(filter-out $(t)/$(f).latest, \ + $(wildcard $(t)/$(f).*))))) +COMPRESSPOSSIBLE := $(foreach t, $(TEMPLATES), \ + $(foreach f, $(FLAVORS), $(wildcard $(t)/$(f).*))) +COMPRESSTARGETS := $(foreach p, $(COMPRESSPOSSIBLE), $(p)/compress) +BOOTTARGETS := $(foreach t, $(TEMPLATES), $(t)/base/boot) +BOOTTARGETS += $(foreach p, $(PROVTARGETS), $(p)/boot) +BOOTTARGETS := $(strip $(BOOTTARGETS)) +CURBOOTTARGETS := $(foreach p, $(REPROVTARGETS), $(p)/boot) +BASERMTARGETS := $(foreach t, $(BASETARGETS), rm/$(t)) +PROVRMTARGETS := $(foreach t, $(REPROVTARGETS), rm/$(t)) + +ifndef ANSIBLE_PROV_EXTRA_ARGS + ANSIBLE_PROV_EXTRA_ARGS := +endif + +ifdef DEBUG + VERBOSE := 1 + ifeq ($(DEBUG),STEP) + override PACKER_OPTS += -debug + else + override PACKER_OPTS += -on-error=ask + endif +endif + +ifdef FORCE + override PACKER_OPTS += -force +endif + +ifdef WINDOW + override PACKER_OPTS += -var headless=false +endif + +override PACKER_OPTS += -warn-on-undeclared-var + +# We support parallel Provisioning packer builds. +# To ensure data consistency we save the used ansible roles before executing in +# its own environment, tagged by the current date & time. +TIMESTAMP := $(shell date "+%Y-%m-%d_%H-%M-%S") + +ifdef VERBOSE + $(info timestamp: $(TIMESTAMP)) + $(info ) + $(info packer: executable: $(PACKER)) + $(info packer: options: $(PACKER_OPTS)) + $(info hasher: $(HASHER)) + $(info ) + $(info ansible: boot: $(ANSIBLE_DIR_BOOT)) + $(info ansible: flavors: $(FLAVORS)) + $(info ) + $(info builder: available: $(AVAILABLE_BUILDERS)) + $(info builder: chosen: $(BUILDER)) + $(info ) + $(info targets: base: $(BASETARGETS)) + $(info targets: boot: $(BOOTTARGETS)) + $(info targets: provision: $(PROVTARGETS)) + $(info targets: reprovision: $(REPROVTARGETS)) + $(info ) + override PACKER := PACKER_LOG=1 $(PACKER) +endif + +.PHONY: help clean_except_last clean_bases clean_all clean_failed backinglock $(REPROVTARGETS) +help: + +# Creating base images. When DRACUT_INIT is specified, the dracut module +# repository will be initially cloned and its required components (dnbd3, +# xmount, libxmount-qemu) will be pre-build to accelerate subsequent builds. +$(BASETARGETS): + $(info ** Building template '$(@D)' using '$(BUILDER)' **) + $(eval INIT_TAG := $(if $(DRACUT_INIT), install, untagged)) + $(PACKER) build -only=base.$(BUILDER).ansible \ + $(PACKER_OPTS) \ + -var-file=$(@D)/base.pkrvars.hcl \ + -var http_dir=$(@D)/http \ + -var output_directory=$(BUILDS)/$(@D)/base \ + -var playbook_file=$(ANSIBLE_DIR_BOOT)/slx-builder.yml \ + -var vm_name=$(@D) \ + -var extra_ansible_args=-t,$(INIT_TAG) \ + ./ + $(HASHER) $(BUILDS)/$(@D)/base/$(@D) >$(BUILDS)/$(@D)/base/CHECKSUM + +# Provisioning images +$(PROVIMAGES) + +$(PROVTARGETS) $(REPROVTARGETS): + $(eval FLAVOR := $(basename $(@F))) + $(eval ANSIBLE_DIR_PROV := $(if ansible-$(FLAVOR)/setup-$(FLAVOR).yml,\ + ansible-$(FLAVOR))) + $(eval VERSION := $(if $(suffix $(@)), $(subst .,,$(suffix $(@))), 0)) + $(eval BASE_IMAGE := $(if $(wildcard $(BUILDS)/$(@)/$(@D)-$(FLAVOR)),\ + $(BUILDS)/$(@)/$(@D)-$(FLAVOR),\ + $(BUILDS)/$(@D)/base/$(@D))) + $(eval BUILD_DIR := $(BUILDS)/$(@D)/$(FLAVOR).$(TIMESTAMP)) + $(info ** Provisioning '$(@D)' with '$(FLAVOR)' **) + @mkdir -p $(BUILD_DIR) + @cp -r `readlink -f $(ANSIBLE_DIR_PROV)` $(BUILD_DIR)/$(ANSIBLE_DIR_PROV) + @ln -sfn $(FLAVOR).$(TIMESTAMP) $(BUILDS)/$(@D)/$(FLAVOR).latest + @ln -sfr $(BUILD_DIR) $(dir $(BASE_IMAGE))/$(TIMESTAMP).backinglock + @-cp -r $(BUILDS)/$@/$(ANSIBLE_DIR_PROV) $(BUILD_DIR) + @-cp -r $(BUILDS)/$@/$(ANSIBLE_DIR_PROV).* $(BUILD_DIR) + $(PACKER) build -only=flavor.$(BUILDER).ansible \ + $(PACKER_OPTS) \ + -var disk_image=true \ + -var iso_url=$(BASE_IMAGE) \ + -var iso_checksum=file:$(dir $(BASE_IMAGE))CHECKSUM \ + -var output_directory=$(BUILD_DIR)/image \ + -var playbook_file=$(BUILD_DIR)/$(ANSIBLE_DIR_PROV)/setup-$(FLAVOR).yml \ + -var vm_name=$(@D)-$(FLAVOR) \ + -var extra_ansible_args=$(ANSIBLE_PROV_EXT RA_ARGS) \ + ./ + $(HASHER) $(BUILD_DIR)/image/$(@D)-$(FLAVOR) \ + >$(BUILD_DIR)/image/CHECKSUM + +# Generating boot files +$(BOOTTARGETS): %/boot: % + +$(BOOTTARGETS) $(CURBOOTTARGETS): + $(eval FLAVOR := $(notdir $(@D))) + $(eval BASE := $(patsubst %/, %, $(dir $(@D)))) + $(eval BASE_DIR := $(if $(filter base, $(notdir $(BUILDS)/$(@D))),\ + ,\ + $(if $(wildcard $(BUILDS)/$(@D)/image/.),\ + $(BUILDS)/$(@D),\ + $(BUILDS)/$(@D).$(TIMESTAMP)))) + $(eval BUILD_DIR := $(if $(BASE_DIR)/image,\ + $(BASE_DIR)/image,\ + $(BUILDS)/$(@D))) + $(eval BUILD_DIR := $(if $(filter $(@), $(CURBOOTTARGETS)),\ + $(BASE_DIR)/image,\ + $(BUILD_DIR))) + $(info ** Generating boot files for '$(BUILD_DIR)') + $(PACKER) build -only=flavor.$(BUILDER).ansible \ + $(PACKER_OPTS) \ + -var disk_image=true \ + -var iso_url=$(BUILD_DIR)/$(BASE)-$(FLAVOR) \ + -var iso_checksum=file:$(dir $(BUILD_DIR))image/CHECKSUM \ + -var output_directory=$(BUILD_DIR)/tmp \ + -var playbook_file=$(ANSIBLE_DIR_BOOT)/slx-builder.yml \ + -var vm_name=$(BASE)-$(FLAVOR).tmp \ + -var extra_ansible_args=-t,install,-t,build \ + -var extra_ansible_args=$(ANSIBLE_PROV_EXTRA_ARGS) \ + ./ + @mkdir -p $(BUILD_DIR)/boot + @mv -f $(ANSIBLE_DIR_BOOT)/boot_files/* $(BUILD_DIR)/boot + $(if $(DEBUG),,@rm -rf $(BUILD_DIR)/tmp) + +# Safe removal of images +$(BASERMTARGETS): +rm/%: %/*.backinglock + $(eval BUILD_DIR := $(subst rm/,,$(@))) + @rm -rf $(BUILD_DIR) + +$(PROVRMTARGETS): +rm/%: %/build/*.backinglock + $(eval BUILD_DIR := $(subst rm/,,$(@))/build) + $(eval FATHER_BUILD := $(dir $(shell qemu-img info $(BUILD_DIR)/rootfs-image | grep "backing file" | cut -d\ -f3-))) + $(eval BUILD_TIME := $(subst .,,$(suffix $(@)))) + @rm -rf $(FATHER_BUILD)/$(BUILD_TIME).backinglock + @rm -rf $(BUILD_DIR) + +%.backinglock: backinglock + @qemu-img convert -f qcow2 $(@)/build/rootfs-image -O qcow2 $(@)/build/rootfs-image.tmp + @rm $(@)/build/rootfs-image + @mv $(@)/build/rootfs-image.tmp $(@)/build/rootfs-image + @rm $(@) + +backinglock: + +clean_except_last: + @-$(foreach template,$(TEMPLATES),\ + $(eval exclusions := $(shell test -d $(template) && \ + find $(template) \ + -maxdepth 1 \ + -type l \ + -print0 \ + | xargs -r -0 -n1 readlink))\ + test -d $(template) && \ + find $(template)/* \ + -maxdepth 0 \ + -type d \ + $(foreach file,$(exclusions),-not -name $(file) ) \ + -not -name base \ + -print0 \ + | xargs -r -0 -n1 rm -rf; ) + +clean_failed: + @-$(foreach template,$(TEMPLATES),\ + test -d $(template) && \ + find $(template)/* \ + -maxdepth 0 \ + -type d \ + -not -name base \ + -print0 \ + | xargs -r -0 -n1 -i \ + $(SHELL) -c 'test -d "{}/build" || rm -rf "{}"'; ) + +clean_bases: + @-$(foreach template,$(TEMPLATES),\ + test -d $(template) && rm -rf $(template)/base;) + +clean_all: + @-$(foreach template,$(TEMPLATES),\ + test -d $(template) && rm -rf $(template);) + +help: + @printf "Usage:\n\tmake