packer-arch/wrapacker
Mike Appleby e54e34cda1 Check for existence of packer-io command before setting PACKER_BIN
In older versions of arch linux, the hashicorp packer package (and
binary) was named packer-io to avoid clashing with a pre-existing AUR
helper called packer. Recently, the AUR helper package was renamed to
packer-aur and the old packer-io (and corresponding binary) was
renamed to packer.

https://www.archlinux.org/packages/community/x86_64/packer/

Previously, the wrapacker script would unconditionally set PACKER_BIN
to "packer-io" if the file /etc/arch-release existed. We now instead
the check for the existence of a packer-io command, and fall back to
the default "packer" in case that doesn't exist.
2018-10-30 16:43:35 -06:00

285 lines
6.2 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# wrapacker - https://github.com/elasticdog/packer-arch
#
# A script to automatically ensure the latest ISO download URL and optionally
# use a mirror from the provided country in order to build an Arch Linux box
# using Packer.
#
# Copyright (c) 2015 Aaron Bull Schaefer <aaron@elasticdog.com>
# This source code is provided under the terms of the ICS License
# that can be be found in the LICENSE file.
#
##### Constants
# country codes supported by https://www.archlinux.org/mirrorlist/
readonly VALID_COUNTRIES=(AT AU BD BE BG BR BY CA CH CL CN CO CZ DE DK EC ES FR GB GR HR HU ID IE IL IN IR IS IT JP KR KZ LT LU LV MK NC NL NO NZ PH PL PT RO RS RU SE SG SK TR TW UA US VN ZA)
if command -v packer-io > /dev/null 2>&1; then
# Older arch linux versions called the packer binary packer-io.
readonly PACKER_BIN='packer-io'
else
readonly PACKER_BIN='packer'
fi
VALID_TIME_UNITS=(ns us ms s m h)
##### Functions
# print a message to stderr
warn() {
local fmt="$1"
shift
printf "wrapacker: $fmt\n" "$@" >&2
}
# print a message to stderr and exit with either
# the given status or that of the most recent command
die() {
local st="$?"
if [[ "$1" != *[^0-9]* ]]; then
st="$1"
shift
fi
warn "$@"
exit "$st"
}
# test the VALID_COUNTRIES array for membership of the given value
validate_country() {
local haystack="VALID_COUNTRIES[@]"
local needle=$1
local found=1
for element in "${!haystack}"; do
if [[ $element == "$needle" ]]; then
found=0
break
fi
done
return $found
}
# print this script's usage message to stderr
usage() {
cat <<-EOF >&2
usage: wrapacker [-c COUNTRY] [-p PROVIDER] [-t TIMEOUT] [-d] [-h]
EOF
}
# print the list of valid countries to stderr
print_valid_countries() {
printf '\n*** VALID COUNTRY CODES ***\n\n' >&2
for country in "${VALID_COUNTRIES[@]}"; do
printf '%-6s\n' "$country"
done | column >&2
}
# print the list of valid providers to stderr
print_valid_providers() {
printf '\n*** VALID PROVIDERS ***\n\n' >&2
for provider in {parallels,virtualbox,vmware,libvirt}; do
printf '%-6s\n' "$provider"
done | column >&2
}
# print the list of valid time units to stderr
print_valid_time_units() {
printf '\n*** VALID TIME UNITS ***\n\n' >&2
for units in "${VALID_TIME_UNITS[@]}"; do
printf '%-6s\n' "$units"
done | column >&2
}
# print this script's help message to stdout
help() {
cat <<-EOF
NAME
wrapacker -- wrap packer to build arch with custom mirror settings
SYNOPSIS
wrapacker [options...]
DESCRIPTION
wrapacker will automatically ensure the latest ISO download URL and
will optionally use a mirror from the provided country in order to
build an Arch Linux box using Packer.
OPTIONS
-c, --country=COUNTRY
the country code to download from;
defaults to the kernel.org US mirror
-p, --provider=PROVIDER
the packer provider to build with;
defaults to virtualbox
-t, --timeout=TIMEOUT
sets the amount of time packer will wait for trying ssh login;
defaults to 20m
-d, --dry-run
do not actually perform the build, just show what would run
-h, --help
view this help message
-e, --headless
do not run the build in the GUI
only works with --provider=virtualbox
AUTHOR
Aaron Bull Schaefer <aaron@elasticdog.com>
EOF
}
##### Main
# check for dependencies
for cmd in {awk,curl,sed,tr}; do
command -v $cmd > /dev/null || die "required command \"$cmd\" was not found"
done
# reset all variables that might be set
country=''
provider=''
dry_run=''
timeout=''
headless=false
# parse command line options
while [[ $1 != '' ]]; do
case $1 in
-c | --country)
country=$(echo "$2" | tr '[:lower:]' '[:upper:]')
shift
;;
--country=*)
country=$(echo "${1#*=}" | tr '[:lower:]' '[:upper:]')
;;
-p | --provider)
provider=$2
shift
;;
--provider=*)
provider=${1#*=}
;;
-t | --timeout)
timeout=$2
shift
;;
--timeout=*)
timeout=${1#*=}
;;
-d| --dry-run)
dry_run=true
;;
-h | --help | -\?)
help
print_valid_countries
print_valid_providers
print_valid_time_units
exit 0
;;
-e| --headless)
headless=true
;;
--*)
warn "unknown option -- ${1#--}"
usage
exit 1
;;
*)
warn "unknown option -- ${1#-}"
usage
exit 1
;;
esac
shift
done
if [[ $provider ]]; then
case $(echo "$provider" | tr '[:upper:]' '[:lower:]') in
parallels | parallels-iso)
PACKER_PROVIDER='parallels-iso'
;;
virtualbox | virtualbox-iso)
PACKER_PROVIDER='virtualbox-iso'
;;
vmware | vmware-iso)
PACKER_PROVIDER='vmware-iso'
;;
libvirt | qemu)
PACKER_PROVIDER='qemu'
;;
*)
warn "unknown provider -- ${provider}"
usage
print_valid_providers
exit 1
;;
esac
else
PACKER_PROVIDER='virtualbox-iso'
fi
if [[ $country ]]; then
if validate_country "$country"; then
MIRRORLIST="https://www.archlinux.org/mirrorlist/?country=${country}&protocol=http&protocol=https&ip_version=4&use_mirror_status=on"
MIRROR=$(curl -s "$MIRRORLIST" | awk '/#Server/{ print $3; exit }' | sed 's|/$repo.*||')
else
warn 'INVALID COUNTRY SPECIFIED - %s' "$country"
usage
print_valid_countries
exit 1
fi
else
MIRROR='https://mirrors.kernel.org/archlinux'
country='US'
fi
ISO_CHECKSUM_URL="${MIRROR}/iso/latest/sha1sums.txt"
ISO_NAME=$(curl -sL "$ISO_CHECKSUM_URL" | awk '/-x86_64.iso/{ print $2 }')
ISO_URL="${MIRROR}/iso/latest/${ISO_NAME}"
if [[ $timeout ]]; then
if [[ "$timeout" =~ ^[0-9]+(ns|us|ms|s|m|h)$ ]]; then
SSH_TIMEOUT=$timeout
else
warn 'INVALID TIME UNITS SPECIFIED or MISSING UNIT - %s' "$timeout"
usage
print_valid_time_units
exit 1
fi
else
SSH_TIMEOUT='20m'
fi
if [[ $dry_run ]]; then
cat <<-EOF
$PACKER_BIN build \\
-only=$PACKER_PROVIDER \\
-var "iso_url=$ISO_URL" \\
-var "iso_checksum_url=$ISO_CHECKSUM_URL" \\
-var "ssh_timeout=$SSH_TIMEOUT" \\
-var "country=$country" \\
-var "headless=$headless" \\
arch-template.json
EOF
else
$PACKER_BIN build \
-only=$PACKER_PROVIDER \
-var "iso_url=$ISO_URL" \
-var "iso_checksum_url=$ISO_CHECKSUM_URL" \
-var "ssh_timeout=$SSH_TIMEOUT" \
-var "country=$country" \
-var "headless=$headless" \
arch-template.json
fi
exit $?