mirror of
https://github.com/elasticdog/packer-arch.git
synced 2026-01-23 18:25:06 +00:00
382 lines
8.8 KiB
Bash
Executable file
382 lines
8.8 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] [-w] [-o ON-ERROR ACTION] [-f] [-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 the list of valid on-error actions to stderr
|
|
print_valid_on_error_actions() {
|
|
printf '\n*** VALID ON-ERROR ACTIONS ***\n\n' >&2
|
|
for action in {cleanup,abort,ask}; do
|
|
printf '%-6s\n' "$action"
|
|
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
|
|
|
|
-w, --skip-write-zeros
|
|
don't inflate the disk to improve virtual disk compaction
|
|
|
|
-o, --on-error=ACTION
|
|
error handling if the build fails;
|
|
defaults to cleanup
|
|
|
|
-f, --force
|
|
force a build to continue if artifacts exist; deletes existing artifacts
|
|
|
|
-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=false
|
|
timeout=''
|
|
skip_write_zeros=false
|
|
on_error=''
|
|
force=false
|
|
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#*=}
|
|
;;
|
|
-w | --skip-write-zeros)
|
|
skip_write_zeros=true
|
|
;;
|
|
-o | --on-error)
|
|
on_error=$2
|
|
shift
|
|
;;
|
|
--on-error=*)
|
|
on_error=${1#*=}
|
|
;;
|
|
-f | --force)
|
|
force=true
|
|
;;
|
|
-d| --dry-run)
|
|
dry_run=true
|
|
;;
|
|
-h | --help | -\?)
|
|
help
|
|
print_valid_countries
|
|
print_valid_providers
|
|
print_valid_time_units
|
|
print_valid_on_error_actions
|
|
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://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/sha256sums.txt"
|
|
ISO_NAME=$(curl -sL "$ISO_CHECKSUM_URL" | awk '/-x86_64.iso/{ print $2 }' | tail -n 1)
|
|
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 [[ $skip_write_zeros = true ]]; then
|
|
WRITE_ZEROS="false"
|
|
else
|
|
WRITE_ZEROS="true"
|
|
fi
|
|
|
|
if [[ $on_error ]]; then
|
|
case $(echo "$on_error" | tr '[:upper:]' '[:lower:]') in
|
|
cleanup)
|
|
ON_ERROR='cleanup'
|
|
;;
|
|
abort)
|
|
ON_ERROR='abort'
|
|
;;
|
|
ask)
|
|
ON_ERROR='ask'
|
|
;;
|
|
*)
|
|
warn "unknown on-error action -- ${on_error}"
|
|
usage
|
|
print_valid_on_error_actions
|
|
exit 1
|
|
;;
|
|
esac
|
|
else
|
|
ON_ERROR='cleanup'
|
|
fi
|
|
|
|
if [[ $dry_run = true ]]; then
|
|
if [[ $force = true ]]; 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" \\
|
|
-var "write_zeros=$WRITE_ZEROS" \\
|
|
-on-error=$ON_ERROR \\
|
|
-force \\
|
|
arch-template.json
|
|
EOF
|
|
else
|
|
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" \\
|
|
-var "write_zeros=$WRITE_ZEROS" \\
|
|
-on-error=$ON_ERROR \\
|
|
arch-template.json
|
|
EOF
|
|
fi
|
|
else
|
|
if [[ $force = true ]]; then
|
|
$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" \
|
|
-var "write_zeros=$WRITE_ZEROS" \
|
|
-on-error=$ON_ERROR \
|
|
-force \
|
|
arch-template.json
|
|
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" \
|
|
-var "write_zeros=$WRITE_ZEROS" \
|
|
-on-error=$ON_ERROR \
|
|
arch-template.json
|
|
fi
|
|
fi
|
|
|
|
exit $?
|