Created
September 24, 2014 20:59
-
-
Save smoser/cad7e91d03c9a8cc79c6 to your computer and use it in GitHub Desktop.
mini ec2 init
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -f | |
NAME="mini-ec2-init" | |
OIFS="$IFS" | |
CONSOLE="/dev/console" | |
LOG="/var/log/${NAME}.log" | |
MD_URL="http://169.254.169.254/2009-04-04/" | |
VERBOSITY=${VERBOSITY:-0} | |
HAS_USERDATA="" | |
USER="ubuntu" | |
MARKER_D="/var/lib/$NAME" | |
MARKER="" | |
ERRORS="" | |
RERUN=${RERUN:-false} | |
TIMEOUT=10 | |
CR=" | |
" | |
as_def_user() { | |
sudo -Hu "$USER" -- "$@" | |
} | |
log() { | |
local now=$(date -R) | |
set -- "$now:" "$@" | |
if [ -w "$CONSOLE" ] && ! [ "$CONSOLE" -ef /dev/stdout ]; then | |
echo "$@" >> "$CONSOLE" | |
fi | |
[ -w "$LOG" ] && echo "$@" >> "$LOG" | |
echo "$@" 1>&2 | |
} | |
debug() { | |
[ "${VERBOSITY:-0}" -ge "$1" ] || return 0; | |
local v="$1" | |
shift | |
log "debug[$v]:" "$@" | |
} | |
error() { log "ERROR:" "$@"; ERRORS=$(($ERRORS+1)); } | |
fail() { [ $# -eq 0 ] || log "FAIL:" "$@"; exit 1; } | |
warn() { log "WARN:" "$@"; } | |
caturl() { | |
debug 2 "getting ${1#${MD_URL}}" | |
curl --fail --silent --max-time "${TIMEOUT}" "$1" | |
} | |
mdget() { | |
local u="$1" t1="" t2="" out="" outf="$2" | |
case "$u" in | |
user-data) | |
has_userdata || { _RET=""; return; } | |
;; | |
public-keys|public-keys/) | |
out=$(caturl "$MD_URL/meta-data/${u%/}/") || | |
fail "failed to get $MD_URL/meta-data/$u"; | |
# output of public-keys is lines of 'X=keyname' | |
# so we return a carriage return list of the tokens before = | |
_RET="" | |
IFS="$CR" | |
for t1 in $out; do | |
t1="${t1%%=*}" | |
_RET="${_RET:+${_RET}${CR}}${t1%/}" | |
done | |
IFS="$OIFS" | |
return | |
;; | |
public-keys/*) | |
t1=${u#public-keys/[0-9]} | |
# t2 will now have 'public-keys/[0-9]' | |
t2=${u%${t1}} | |
# if t1 has a / (ie, u=public-keys/0=brickies/openssh-keys) | |
# then set t1 to just "/openssh-keys". if not, set it to "" | |
[ "${t1#*/}" = "${t1}" ] && t1="" || t1="/${t1#*/}" | |
u="meta-data/${t2}${t1}" | |
;; | |
_top) u="";; | |
*) u="meta-data/$u";; | |
esac | |
if [ -z "$outf" ]; then | |
_RET=$(caturl "$MD_URL/$u") | |
elif [ "$outf" = "-" ]; then | |
caturl "$MD_URL/$u" | |
else | |
caturl "$MD_URL/$u" > "$outf" | |
fi | |
[ $? -eq 0 ] || | |
fail "failed to get ${MD_URL}/$u" | |
} | |
has_userdata() { | |
local out="" | |
if [ -z "$HAS_USERDATA" ]; then | |
mdget "_top" || return 2 | |
HAS_USERDATA=false | |
case "${CR}$_RET${CR}" in | |
*"${CR}user-data${CR}"*) HAS_USERDATA=true;; | |
esac | |
fi | |
${HAS_USERDATA} | |
return | |
} | |
get_field_list() { | |
local under="$1" x="" out="" found="" | |
mdget "$under" | |
out="$_RET" | |
for x in $out; do | |
case "$x" in | |
*/) get_field_list "${under:+${under}/}${x}" | |
found="${found:+${found} }$_RET";; | |
*) found="${found:+${found} }${under:+$under}$x";; | |
esac | |
done | |
_RET="${found# }" | |
} | |
inargs() { | |
# inargs needle haystack | |
local needle="$1" hay="" | |
shift; | |
for hay in "$@"; do | |
[ "$needle" = "$hay" ] && return 0 | |
done | |
return 1 | |
} | |
cleanup() { | |
if [ "${ERRORS:-0}" != "0" ]; then | |
[ -n "$MARKER" -a -e "$MARKER" ] && { | |
error "cleaning $MARKER" | |
rm -Rf "$MARKER" | |
} | |
fi | |
} | |
errors=0 | |
get_field_list "" || fail "failed to get fields under $MD_URL" | |
available=${_RET} | |
has_userdata && available="${available} user-data" | |
mdget instance-id || fail "failed to get instance-id" | |
instance_id="$_RET" | |
[ -n "$instance_id" ] || fail "instance-id is empty!" | |
MARKER="${MARKER_D}/${instance_id}" | |
if [ -e "$MARKER" ]; then | |
if $RERUN; then | |
debug 1 "re-running for $instance_id" | |
else | |
debug 1 "already ran for $instance_id" | |
exit 0 | |
fi | |
else | |
debug 1 "running for $instance_id" | |
fi | |
if [ -d "$MARKER_D" ] || mkdir -p "$MARKER_D" >/dev/null 2>&1; then | |
MARKER="$MARKER_D/$instance_id" | |
msg=$(date --utc -R 2>/dev/null) || msg="sometime" | |
{ echo "$msg" > "$MARKER"; } >/dev/null 2>&1 || { | |
warn "unable to create marker $MARKER." | |
MARKER="" | |
} | |
else | |
warn "unable to create marker dir $MARKER_D" | |
fi | |
for ktype in rsa ecdsa dsa; do | |
f="/etc/ssh/ssh_host_${ktype}_key" | |
rm -f "$f" && out=$(ssh-keygen -t "$ktype" -N "" -f "$f" 2>&1) && | |
log "generated ssh host key '$ktype' in $f" || | |
error "Failed to generate ssh key $ktype: $out" | |
done | |
if inargs public-keys/0 ${available}; then | |
if mdget public-keys/0/openssh-key; then | |
pubkeys="$_RET" | |
as_def_user sh -ec ' | |
[ -d "$HOME/.ssh" ] || mkdir "$HOME/.ssh" | |
umask 044 | |
printf "%s\n" "$1" >> "$HOME/.ssh/authorized_keys"' -- \ | |
"$pubkeys" && | |
log "imported for $USER: $pubkeys" || | |
error "failed to write public-keys" | |
else | |
errors=$(($errors+1)); | |
error "failed to get public-keys" | |
fi | |
else | |
debug 1 "no public keys available" | |
fi | |
if has_userdata; then | |
if tmpf=$(mktemp 2>/dev/null); then | |
if ! mdget user-data "$tmpf"; then | |
error "failed to get user-data to temp file" | |
else | |
read line < "$tmpf" | |
shebang='#!' | |
case "$line" in | |
"${shebang}"*) | |
chmod 755 "$tmpf" && "$tmpf" && | |
log "executed user-data." || | |
error "executing user-data failed." | |
esac | |
fi | |
rm -f "$tmpf" | |
else | |
error "could not create temp file for user-data" | |
fi | |
fi | |
exit ${ERRORS} | |
# vi: ts=4 noexpandtab |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment