diff --git a/lib/tiny-cloud/init b/lib/tiny-cloud/init index 7e590ff..170e14a 100644 --- a/lib/tiny-cloud/init +++ b/lib/tiny-cloud/init @@ -8,19 +8,28 @@ : "${SKIP_INIT_ACTIONS:=}" : "${HOTPLUG_TYPE:=mdev}" -# TODO: default phase actions +### default phase actions (without leading 'init__') -# ensure existence of output directories -[ ! -d "$TINY_CLOUD_LOGS" ] && mkdir -p "$TINY_CLOUD_LOGS" -[ ! -d "$TINY_CLOUD_VAR" ] && mkdir -p "$TINY_CLOUD_VAR" +INIT_ACTIONS_EARLY=" + expand_root + install_hotplugs +" +INIT_ACTIONS_MAIN=" + save_userdata + set_hostname + set_ssh_keys +" +INIT_ACTIONS_FINAL=" + run_userdata +" -### NOTE: init-early functions... +# try to ensure existence of output directories, but otherwise don't panic +[ ! -d "$TINY_CLOUD_LOGS" ] && mkdir -p "$TINY_CLOUD_LOGS" || true +[ ! -d "$TINY_CLOUD_VAR" ] && mkdir -p "$TINY_CLOUD_VAR" || true -expand_root() { - skip_action expand_root && return - - echo "Expanding Root Volume/ Partition" +### init-early functions... +init__expand_root() { local dev=$(awk '$2 == "/" {print $1}' "$ROOT"/proc/mounts) local partition=$(cat "$ROOT/sys/class/block/${dev#/dev/}/partition" 2>/dev/null) @@ -35,36 +44,29 @@ expand_root() { $MOCK resize2fs "$dev" } -install_hotplugs() { - skip_action install_hotplugs && return - [ ! -n "$HOTPLUG_MODULES" ] && return - - echo "Installing Cloud Hotplugs" - +init__install_hotplugs() { local result rc=0 + [ ! -n "$HOTPLUG_MODULES" ] && return if [ -f "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" ]; then - . "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" + . "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" fi + printf ':' >&2 for module in $HOTPLUG_MODULES; do - result='-' - printf " $module" + result='?' + printf "$module" >&2 if type "mod__$module" | grep -q -w "function"; then "mod__$module" && result='+' || { result='!'; rc=1; } fi - printf "($result)" + printf '(%s) ' $result >&2 done return $rc } -### NOTE: init-main functions - -set_hostname() { - skip_action set_hostname && return - - echo "Setting Instance Hostname" +### init-main functions +init__set_hostname() { local fqdn=$(imds @hostname) local host="${fqdn%%\.*}" @@ -74,11 +76,7 @@ set_hostname() { echo -e "127.0.1.1\t$fqdn $host" >> "$ROOT"/etc/hosts } -set_ssh_keys() { - skip_action set_ssh_keys && return - - echo "Installing SSH Keys for $CLOUD_USER User" - +init__set_ssh_keys() { local user="$CLOUD_USER" local pwent="$(getent passwd "$user")" local group=$(echo "$pwent" | cut -d: -f4) @@ -96,87 +94,61 @@ set_ssh_keys() { imds @ssh-keys > "$keys_file" } -save_userdata() { - skip_action save_userdata && return - - # TODO: this trips save_userdata_* and run_userdata tests: "stdout not empty" - #echo "Saving Instance UserData" - +init__save_userdata() { local userdata="$TINY_CLOUD_VAR/user-data" local tmpfile=$(mktemp "$userdata.XXXXXX") - local cmd imds -e @userdata > "$tmpfile" - cmd="cat" - if ! skip_action decompress_userdata; then - if printf '\037\213\010' | cmp -s -n 3 "$tmpfile"; then - gzip -dc "$tmpfile" > "$userdata" - elif printf 'BZh' | cmp -s -n 3 "$tmpfile"; then - bzip2 -dc "$tmpfile" > "$userdata" - elif printf '\375\067\172\130\132\000' | cmp -s -n 6 "$tmpfile"; then - unxz -c "$tmpfile" > "$userdata" - elif printf '\135\000\000' | cmp -s -n 3 "$tmpfile"; then - lzma -dc "$tmpfile" > "$userdata" - elif printf '\211\114\132' | cmp -s -n 3 "$tmpfile"; then - lzop -dc "$tmpfile" > "$userdata" - elif printf '\004\042\115\030' | cmp -s -n 4 "$tmpfile"; then - lz4 -dc "$tmpfile" > "$userdata" - elif printf '(\265/\375' | cmp -s -n 4 "$tmpfile"; then - zstd -dc "$tmpfile" > "$userdata" - else - cp "$tmpfile" "$userdata" - fi + if printf '\037\213\010' | cmp -s -n 3 "$tmpfile"; then + gzip -dc "$tmpfile" > "$userdata" + elif printf 'BZh' | cmp -s -n 3 "$tmpfile"; then + bzip2 -dc "$tmpfile" > "$userdata" + elif printf '\375\067\172\130\132\000' | cmp -s -n 6 "$tmpfile"; then + unxz -c "$tmpfile" > "$userdata" + elif printf '\135\000\000' | cmp -s -n 3 "$tmpfile"; then + lzma -dc "$tmpfile" > "$userdata" + elif printf '\211\114\132' | cmp -s -n 3 "$tmpfile"; then + lzop -dc "$tmpfile" > "$userdata" + elif printf '\004\042\115\030' | cmp -s -n 4 "$tmpfile"; then + lz4 -dc "$tmpfile" > "$userdata" + elif printf '(\265/\375' | cmp -s -n 4 "$tmpfile"; then + zstd -dc "$tmpfile" > "$userdata" else cp "$tmpfile" "$userdata" fi rm "$tmpfile" } -### TODO: init-final functions - -run_userdata() { - skip_action run_userdata && return - if [ $(userdata_type) != "script" ]; then - echo "UserData is not executable" - return - fi - - echo "Executing UserData Script" +### init-final functions +init__run_userdata() { local log="$TINY_CLOUD_LOGS/user-data.log" local exit="$TINY_CLOUD_LOGS/user-data.exit" local userdata="$TINY_CLOUD_VAR/user-data" + if [ $(userdata_type) != "script" ]; then + printf '(Not Executable) ' >&2 + return + fi + chmod +x "$userdata" { "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log" return $(cat "$exit") } +### potentially override the above, per cloud + # load cloud-specific init functions / vars if [ -f "$LIBDIR/tiny-cloud/cloud/$CLOUD/init" ]; then - . "$LIBDIR/tiny-cloud/cloud/$CLOUD/init" + . "$LIBDIR/tiny-cloud/cloud/$CLOUD/init" fi -# TODO: load user-data type-specific init functions / vars - -### non-overrideable functions - -# should we skip this action? -skip_action() { - local action="$1" - for i in $SKIP_INIT_ACTIONS; do - if [ "$i" = "$action" ]; then - printf " SKIPPING" - return 0 - fi - done - return 1 -} +# this should be non-overrideable, but need this before we... userdata_type() { if [ -f "$TINY_CLOUD_VAR/user-data" ]; then - header=$(head -n1 "$TINY_CLOUD_VAR/user-data") + header=$(head -n1 "$TINY_CLOUD_VAR/user-data" | sed -e 's/[[:space:]].*//g') case "$header" in '#cloud-config') echo cloud-config;; '#!'*) echo script;; @@ -186,3 +158,6 @@ userdata_type() { echo missing fi } + +# ...load user-data type-specific init functions / vars +# TODO diff --git a/sbin/tiny-cloud b/sbin/tiny-cloud index aa6884a..6c0c01f 100755 --- a/sbin/tiny-cloud +++ b/sbin/tiny-cloud @@ -14,18 +14,15 @@ Usage: ${0##*/} [-h | --help] { early | main | final | --bootstrap {complete|inc EOF } -bootstrap_complete() { - echo "Marking Instance Bootstrap Complete" +init__bootstrap_complete() { touch "$TINY_CLOUD_VAR/.bootstrap-complete" } - -bootstrap_incomplete() { - echo "Marking Instance Bootstrap Incomplete" +init__bootstrap_incomplete() { rm -f "$TINY_CLOUD_VAR/.bootstrap-complete" } args=$(getopt -o hb: --long help,bootstrap: -n ${0##*/} -- "$@") -if [ $? -ne 0 ]; then +if [ $? -ne 0 ] || [ $# -eq 0 ]; then usage >&2 exit 1 fi @@ -36,11 +33,12 @@ while true; do -b|--bootstrap) shift case "$1" in complete) # indicate bootstrap is done - bootstrap_complete;; + init__bootstrap_complete;; incomplete) # indicate bootstrap isn't done - bootstrap_incomplete;; + init__bootstrap_incomplete;; *) usage >&2; exit 1;; esac + printf ' bootstrap marked "%s"\n' "$1" >&2 exit 0;; --) shift; break;; *) usage >&2; exit 1;; @@ -58,32 +56,48 @@ esac # is initial bootstrap already done? if [ -f "$TINY_CLOUD_VAR/.bootstrap-complete" ]; then - log -s "Already bootstrapped" + printf ' already bootstrapped\n' >&2 exit 0; fi -### default phase actions - -# TODO? represent as vars containing lists of funcs? - -early() { - expand_root - install_hotplugs -} - -main() { - save_userdata - set_hostname - set_ssh_keys -} - -final() { - run_userdata - bootstrap_complete -} - # load init functions . "$LIBDIR/tiny-cloud/init" -# TODO? for loop over list of funcs? -- better for ebegin/eend-ish output -echo $phase "$@" +### non-overrideable stuff + +# should we skip this action? +skip_action() { + local action="$1" + for i in $SKIP_INIT_ACTIONS; do + if [ "$i" = "$action" ]; then + return 0 + fi + done + return 1 +} + +# mandatory final action... +INIT_ACTIONS_FINAL="${INIT_ACTIONS_FINAL} bootstrap_complete" + +### let's do stuff! + +case "$phase" in + early) INIT_ACTIONS="$INIT_ACTIONS_EARLY";; + main) INIT_ACTIONS="$INIT_ACTIONS_MAIN";; + final) INIT_ACTIONS="$INIT_ACTIONS_FINAL";; + *) usage >&2; exit 1 +esac + +for ACTION in $INIT_ACTIONS; do + if skip_action "$ACTION"; then + printf '\n -- %s : [SKIP]' $ACTION >&2 + continue + fi + printf '\n ++ %s ' $ACTION >&2 + RESULT="UNKNOWN" + if type "init__$ACTION" | grep -q -w "function"; then + "init__$ACTION" "$@" && RESULT="DONE" || RESULT="FAIL" + fi + printf ': [%s]' $RESULT >&2 +done +echo >&2