5
NAME="ubuntu-cloudimg-query"
7
CACHE_D="$HOME/.cache/$NAME"
10
error() { echo "$@" 1>&2; }
11
errorp() { printf "$@" 1>&2; }
12
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
13
failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }
17
Usage: ${0##*/} [ options ] criteria
19
Get the latest Ubuntu ami meeting certain criteria
22
-o | --output FILE output to file rather than stdout
23
-f | --format format change output to 'format'.
27
- get the latest ami matching default criteria for release 'n'
29
us-east-1/ebs/ubuntu-natty-11.04-amd64-server-20110426
31
- get an instance-store image in i386 image in us-west-1
32
$ ${0##*/} lucid i386 instance us-west-1
34
- get the latest daily build of the devel release in eu-west-1
35
$ EC2_REGION=eu-west-1 ${0##*/} daily amd64 ebs o
40
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
42
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
46
local file="$1" date="$2"
47
[ -n "$file" -a -e "$file" ] || return 1
48
touch --date "${date}" "${TEMP_D}/ts"
49
[ "$file" -nt "$TEMP_D/ts" ]
53
local url="$1" out="$2" cfilename="$3" age="$4"
54
local cachef="${CACHE_D}/$cfilename"
55
local timeout="now - $age seconds"
56
[ -n "$cfilename" ] || cachef=""
57
if cache_valid "$cachef" "$timeout"; then
58
cp -a "$cachef" "$out"
61
wget -q "${url}" -O "${out}" || return 1
62
{ [ -z "$cachef" ] || cp "${out}" "${cachef}"; } ||
67
local level=${1}; shift;
68
[ "${level}" -gt "${VERBOSITY}" ] && return
73
local cand="$1" url="$2" out="$3" cache="$4" age="$5"
75
for f in "$out" "$CACHE_D/$cache"; do
77
o=$(awk '-F\t' '$1 ~ r { print $1; exit(0); }' "r=^$cand" "$f") &&
78
[ -n "$o" ] && _RET="$o" && return 0
80
dlcache "$url" "$out" "$cache" "$age" &&
81
o=$(awk '-F\t' '$1 ~ r { print $1; exit(0); }' "r=^$cand" "$out") &&
82
[ -n "$o" ] && _RET="$o" && return 0
86
local cur="$1"; shift;
87
while [ $# -ne 0 ]; do
88
while [ "${cur#*${1}}" != "${cur}" ]; do
89
cur="${cur%%${1}*}${2}${cur#*${1}}"
97
local needle="$1" hay=""
100
[ "$hay" = "$needle" ] && return 0
106
# get the list of releases, return it in _RET
107
local releases="" r=""
108
releases="hardy karmic lucid maverick natty oneiric precise";
109
if command -v "ubuntu-distro-info" >/dev/null; then
110
local all_rels="" seen_lucid=false
111
all_rels=$(ubuntu-distro-info --all) ||
112
{ error "'ubuntu-distro-info --all' failed"; return 1; }
114
for r in $all_rels; do
115
if $seen_lucid || [ "$r" = "lucid" ]; then
117
releases="${releases} $r"
125
long_opts="format:,help,no-cache,output:,verbose"
126
getopt_out=$(getopt --name "${0##*/}" \
127
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
128
eval set -- "${getopt_out}" ||
131
## <<insert default variables here>>
134
burl="${UBUNTU_CLOUDIMG_QUERY_BASEURL:-https://cloud-images.ubuntu.com/query}"
136
region_default="${EC2_REGION:-us-east-1}"
146
while [ $# -ne 0 ]; do
149
-h|--help) Usage ; exit 0;;
150
-f|--format) format=${2}; shift;;
151
-o|--output) output=${2}; shift;;
152
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
153
--no-cache) cachelife=0;;
159
getreleases || fail "failed to get releases"
163
in_args "$i" $releases && r_rel=$i && continue
165
rel*) stream="released";;
167
server|desktop) bname=${i};;
168
i386|amd64|x86_64) arch=${i}; [ "${i}" = "x86_64" ] && arch="amd64";;
169
*-*-[0-9]) region=${i};;
171
instance|instance-store) store="instance-store";;
173
para|paravirtual) ptype="paravirtual";;
178
[a-z][1-9].[0-9a-z]*|c[cg][1-9].*)
181
t1.micro) store=ebs;; # t1.micro does not imply arch
182
m1.small|c1.medium) arch=i386;;
186
http://*|https://*) burl=${i};;
188
[ -z "$p_rel" ] || fail "found 2 unknown args: $p_rel, $i";
190
*) fail "confused by argument: ${i}";;
194
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
195
fail "failed to make tempdir"
198
{ [ -d "${CACHE_D}" ] || mkdir -p "${CACHE_D}"; } ||
199
fail "failed to create ${CACHE_D}"
201
daily_latest="${TEMP_D}/daily.latest.txt"
202
release_latest="${TEMP_D}/released.latest.txt"
204
if [ -n "$p_rel" ]; then
205
[ -z "$r_rel" ] || fail "unknown arg ${p_rel}"
206
url="${burl}/daily.latest.txt"
207
isrel "$p_rel" "$url" "${daily_latest}" "daily.latest.txt" $cachelife &&
208
r_rel="${_RET}" || fail "bad input $p_rel"
210
[ -n "$r_rel" ] && release=$r_rel
212
if [ -z "${region}" ]; then
213
if [ -n "${EC2_URL}" ]; then
214
case "${EC2_URL#*://}" in
215
*-*-[0-9].ec2.amazonaws.com*)
216
region=${EC2_URL#*://};
217
region=${region%%.*};;
218
ec2.amazonaws.com/*) region=us-east-1;;
219
*) region=${region_default};;
222
region="${region_default}"
226
ec2_curf="${TEMP_D}/${release}.${bname}.${stream}.current.txt"
227
ec2_url="${burl}/${release}/${bname}/${stream}.current.txt"
228
dl_curf="${TEMP_D}/${release}.${bname}.${stream}-dl.current.txt"
229
dl_url="${burl}/${release}/${bname}/${stream}-dl.current.txt"
231
dlcache "${dl_url}" "${dl_curf}" "${dl_curf##*/}" $cachelife ||
232
fail "failed to get ${dl_url}"
235
'$1 == release && $2 == bname && $5 == arch { print $4, $6, $7 }' \
236
"release=$release" "bname=$bname" "arch=$arch" "${dl_curf}") &&
237
[ -n "$out" ] || fail "failed find entry in ${dl_url}"
238
set -- ${out}; serial=$1; dlpath=$2; pubname=$3
239
url="${burl%/query}/${dlpath}"
242
[ "${ptype}" = "hvm" ] && prefix="hvm"
243
dlcache "${ec2_url}" "${ec2_curf}" "${ec2_curf##*/}" $cachelife ||
244
fail "failed to get ${ec2_url}"
246
'$1 == release && $2 == bname && $5 == store &&
247
$6 == arch && $7 == region && $11 == ptype { print $8 }' \
248
"release=$release" "bname=${bname}" \
249
"store=$store" "arch=$arch" "region=$region" "ptype=$ptype" \
250
"${ec2_curf}") && [ -n "$ami" ] || fail "failed to find ami"
252
case "$arch:$store:$ptype" in
253
*:hvm) itypes_all="cc1.4xlarge cg1.4xlarge cc2.8xlarge";;
254
i386:*) itypes_all="m1.small c1.medium";;
255
amd64:*) itypes_all="m1.large m1.xlarge m2.xlarge m2.2xlarge m2.4xlarge c1.xlarge";;
257
[ "$store" = "ebs" -a "$ptype" != "hvm" ] && itypes_all="t1.micro $itypes_all"
259
for x in ${itype} ${itypes_all}; do
263
itypes="${itypes},${x}"
269
[ "$xarch" = "amd64" ] && xarch="x86_64"
275
'\\n' "$CR" '\\t' "$TAB" \
277
'%{arch}' "$arch" '%{bname}' "$bname" '%{dlpath}' "$dlpath" \
278
'%{ptype}' "$ptype" '%{pubname}' "$pubname" '%{region}' "$region" \
279
'%{release}' "$release" '%{store}' "$store" '%{stream}' "$stream" \
281
'%{xarch}' "$xarch" '%{itype}' "${itype}" '%{itypes}' "$itypes" \
282
'%{summary}' "${region}/${prefix}/${pubname}"
285
[ -n "${out}" ] || fail "no ami found matching criteria"
287
debug 1 "${region}/${prefix}/${pubname}"
288
if [ -n "${output}" -a "${output}" != "-" ]; then
289
echo -n "$out" > "$output"
294
# vi: ts=4 noexpandtab