# 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 = ansible-roles # check which hypervisors are available ifndef BUILDER ifeq ($(shell which qemu-system-$(shell uname -m | sed 's/i686/i386/') 2>&1 > /dev/null && echo $$?), 0) AVAILABLE_BUILDERS += qemu endif ifeq ($(shell which virtualbox 2>&1 > /dev/null && echo $$?), 0) AVAILABLE_BUILDERS += virtualbox-iso endif ifeq ($(shell which vmplayer 2>&1 > /dev/null && echo $$?), 0) AVAILABLE_BUILDERS += vmware-iso endif BUILDER := $(firstword $(AVAILABLE_BUILDERS)) endif ## # Templates and flavors detection ## # The packer templates, detected as *.json (excluding base.json) TEMPLATES := $(basename $(filter-out base.json,$(wildcard *.json))) # The provisioning flavors, detected as ansible-roles/setup-.yml FLAVORS := $(patsubst $(ANSIBLE_DIR)/setup-%.yml,%, $(wildcard $(ANSIBLE_DIR)/setup-*.yml)) BASETARGETS := $(foreach template, $(TEMPLATES), $(template)/base) PROVTARGETS := $(foreach template, $(TEMPLATES), $(foreach flavor, $(FLAVORS), $(template)/$(flavor))) BOOTTARGETS := $(foreach template, $(TEMPLATES), $(template)/base/boot) BOOTTARGETS += $(foreach prov, $(PROVTARGETS), $(prov)/boot) PACKER_OPTS := -var-file=base.json ifdef DEBUG VERBOSE := 1 PACKER_OPTS += -debug PACKER_OPTS += -var='headless=false' endif TIMESTAMP := $(shell date "+%Y-%m-%d_%H-%M-%S") check_rootpw = $(if $(strip $(ROOTPW)),,$(error No root password is set, set it as ROOTPW in your environment.)) ifdef VERBOSE $(info root password: $(ROOTPW)) $(info ) $(info packer: executable: $(PACKER)) $(info packer: options: $(PACKER_OPTS)) $(info ) $(info ansible: directory: $(ANSIBLE_DIR)) $(info ) $(info builder: available: $(AVAILABLE_BUILDERS)) $(info builder: chosen: $(BUILDER)) $(info ) $(info targets: base: $(strip $(BASETARGETS))) $(info targets: boot: $(strip $(BOOTTARGETS))) $(info targets: provision: $(strip $(PROVTARGETS))) $(info ) endif .PHONY: help clean help: ## # Creating base images ## $(BASETARGETS): $(call check_rootpw) $(info ** Building template '$(@D)' using '$(BUILDER)' **) $(PACKER) build -only=$(BUILDER) \ $(PACKER_OPTS) \ -var='vm_name=rootfs-image' \ -var='output_directory=$(@D)/base' \ $(@D).json ## # Provisioning images ## # This should still only use base images $(PROVTARGETS): $(foreach flav, $(FLAVORS), %/$(flav)): %/base $(call check_rootpw) $(eval BUILD_DIR := $(@D)/$(@F).$(TIMESTAMP)) $(info ** Provisioning '$(@D)' with '$(@F)' **) @mkdir -p $(BUILD_DIR) @cp -r $(ANSIBLE_DIR) $(BUILD_DIR)/$(ANSIBLE_DIR) $(PACKER) build -only=$(BUILDER) \ $(PACKER_OPTS) \ -var='vm_name=rootfs-image' \ -var='output_directory=$(BUILD_DIR)/build' \ -var='base_image=$(@D)/base/rootfs-image' \ -var='playbook=setup-$(@F).yml' \ $(BUILD_DIR)/$(ANSIBLE_DIR)/run-playbook-only.json ## # Generating boot files ## # This should use provisioned image $(BOOTTARGETS): %/boot: % $(call check_rootpw) $(eval BUILD_DIR := $(@D).$(TIMESTAMP)) $(info ** Generating boot files for '$(BUILD_DIR)') $(PACKER) build -only=$(BUILDER) \ $(PACKER_OPTS) \ -var='vm_name=rootfs-image.tmp' \ -var='output_directory=$(BUILD_DIR)/build/tmp' \ -var='base_image=$(BUILD_DIR)/build/rootfs-image' \ -var='playbook=build-dracut-initramfs.yml' \ $(BUILD_DIR)/$(ANSIBLE_DIR)/run-playbook-only.json @mv $(BUILD_DIR)/$(ANSIBLE_DIR)/boot_files $(BUILD_DIR)/build/boot help: @printf "Usage:\n\tmake