diff --git a/Makefile b/Makefile index b0aaef2..37296b7 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,10 @@ core: lib/tiny-cloud/init \ lib/tiny-cloud/mdev \ lib/tiny-cloud/tiny-cloud.conf + install -Dm644 -t "$(PREFIX)"/lib/tiny-cloud/user-data" \ + lib/tiny-cloud/user-data/missing \ + lib/tiny-cloud/user-data/script \ + lib/tiny-cloud/user-data/unknown install -Dm644 lib/tiny-cloud/tiny-cloud.conf \ "$(PREFIX)"/etc/tiny-cloud.conf install -Dm755 -t "$(PREFIX)"/sbin \ @@ -60,6 +64,8 @@ alpine: install -Dm644 -t $(PREFIX)/lib/tiny-cloud/cloud/alpine \ lib/tiny-cloud/cloud/alpine/init ln -s ../nocloud/imds $(PREFIX)/lib/tiny-cloud/cloud/alpine/imds + install -Dm644 -t "$(PREFIX)"/lib/tiny-cloud/user-data" \ + lib/tiny-cloud/user-data/alpine-config check: tests/Kyuafile Kyuafile kyua test || (kyua report --verbose && exit 1) diff --git a/lib/mdev/nvme-ebs-links b/lib/mdev/nvme-ebs-links index 7005c5f..1eee876 100755 --- a/lib/mdev/nvme-ebs-links +++ b/lib/mdev/nvme-ebs-links @@ -1,6 +1,9 @@ #!/bin/sh # vim:set ts=2 et: +# NOTE: The mdev-conf APK handles this now, but only for xvd or sd links (not +# both) + : "${LIBDIR:=$PREFIX/lib}" . "$LIBDIR/tiny-cloud/common" diff --git a/lib/tiny-cloud/common b/lib/tiny-cloud/common index ce0dd1a..51256af 100644 --- a/lib/tiny-cloud/common +++ b/lib/tiny-cloud/common @@ -10,10 +10,11 @@ log() { local facility="local7" - local stderr + local stderr init local tag=$(basename "$0") while [ "${1#-}" != "$1" ]; do case "$1" in + -i) init=1 ;; # TODO: value = indent? -f) facility="$2"; shift ;; -s) stderr=-s ;; -t) tag="$tag/$2"; shift ;; @@ -24,6 +25,7 @@ log() { [ -z "$DEBUG" ] && [ "$level" = debug ] && return shift + [ -n "$init" ] && echo "$@" >&2 logger $stderr -p "$facility.$level" -t "$tag[$$]" "$@" case "$level" in crit|alert|emerg) exit 1 ;; diff --git a/lib/tiny-cloud/init b/lib/tiny-cloud/init index 8f37744..6e8d2fa 100644 --- a/lib/tiny-cloud/init +++ b/lib/tiny-cloud/init @@ -68,23 +68,22 @@ init__install_hotplugs() { . "$LIBDIR/tiny-cloud/$HOTPLUG_TYPE" fi - printf ': ' >&2 for module in $HOTPLUG_MODULES; do - result='?' + result='unknown' level='err' - printf "$module" >&2 - log info "$phase $ACTION $module" + printf " >> " >&2 + log -i -t "$phase/$ACTION" info "$module: installing" if type "mod__$module" | grep -q -w "function"; then if "mod__$module"; then - result='+' + result='installed' level='info' else - result='!' + result='failed' rc=1 fi fi - printf '(%s) ' $result >&2 - log "$level" "$phase $ACTION $module ($result)" + printf " >> " >&2 + log -i -t "$phase/$ACTION" info "$module: $result" done return $rc } @@ -145,8 +144,7 @@ auto_detect_ethernet_interface() { init__set_default_interfaces() { if [ -f "$ROOT"/etc/network/interfaces ]; then - echo "already set up" >&2 - log info "$phase $ACTION - already set up" + log -i -t "$phase" info "$ACTION: already set up" return fi @@ -171,8 +169,7 @@ init__create_default_user() { local user="$CLOUD_USER" # don't do anything if it already exists if getent passwd "$user" >/dev/null; then - echo "already exists" >&2 - log info "$phase $ACTION - already exists" + log -i -t "$phase" info "$ACTION: already exists" return fi @@ -202,15 +199,13 @@ init__enable_sshd() { init__set_hostname() { local fqdn=$(imds @hostname) if [ -z "$fqdn" ]; then - echo "no hostname set" >&2 - log info "No hostname set" + log -i -t "$phase" info "$ACTION: no hostname set" return fi local host="${fqdn%%\.*}" if [ -z "$host" ]; then - echo "$hostname is not a valid FQDN" >&2 - log err "$fqdn is not a valid FQDN" + log -i -t "$phase" warn "$ACTION: invalid hostname '$fqdn'" return 1 fi @@ -224,8 +219,7 @@ init__set_ssh_keys() { local user="$CLOUD_USER" local pwent="$(getent passwd "$user")" if [ -z "$pwent" ]; then - echo "failed to find $user" >&2 - log err "Failed to find user $user" + log -i -t "$phase" err "$ACTION: failed to find user $user" return 1 fi local group=$(echo "$pwent" | cut -d: -f4) @@ -246,7 +240,7 @@ init__set_ssh_keys() { init__save_userdata() { local userdata="$TINY_CLOUD_VAR/user-data" if [ -f "$userdata" ]; then - log info "user-data already saved" + log -i -t "$phase" info "$ACTION: user-data already saved" return fi local tmpfile=$(mktemp "$userdata.XXXXXX") @@ -285,7 +279,6 @@ fi ### load user-data type-specific init functions / vars (potentially overriding) -# this should be non-overrideable, but need this before we... userdata_type() { if [ ! -f "$TINY_CLOUD_VAR/user-data" ]; then echo missing @@ -303,4 +296,3 @@ USERDATA_TYPE="$(userdata_type)" if [ -f "$LIBDIR/tiny-cloud/user-data/$USERDATA_TYPE" ]; then . "$LIBDIR/tiny-cloud/user-data/$USERDATA_TYPE" fi -# TODO: some indication that the user-data type is unsupported? diff --git a/lib/tiny-cloud/user-data/missing b/lib/tiny-cloud/user-data/missing index 1fd1556..cbb9c2c 100644 --- a/lib/tiny-cloud/user-data/missing +++ b/lib/tiny-cloud/user-data/missing @@ -1,4 +1,8 @@ # Missing UserData Functions # vim:set ts=4 et ft=sh: -# TODO: what to do if we have NO user-data yet +init__missing_userdata() { + log -i -t "$phase" notice "$ACTION: no user-data found" +} + +INIT_ACTIONS_MAIN="missing_userdata ${INIT_ACTIONS_MAIN}" diff --git a/lib/tiny-cloud/user-data/unknown b/lib/tiny-cloud/user-data/unknown index 4d1be1a..14ed827 100644 --- a/lib/tiny-cloud/user-data/unknown +++ b/lib/tiny-cloud/user-data/unknown @@ -1,4 +1,9 @@ # Unknown UserData Functions # vim:set ts=4 et ft=sh: -# TODO: this would probably be mostly NOOPs +init__unknown_userdata() { + local type="$(userdata_type)" + log -i -t "$phase" warn "$ACTION: unable to process '$type' user-data" +} + +INIT_ACTIONS_MAIN="unknown_userdata ${INIT_ACTIONS_MAIN}" diff --git a/sbin/tiny-cloud b/sbin/tiny-cloud index 822611b..1938d8c 100755 --- a/sbin/tiny-cloud +++ b/sbin/tiny-cloud @@ -34,13 +34,12 @@ while true; do case "$1" in complete) # indicate bootstrap is done init__bootstrap_complete - log warn 'bootstrap marked complete';; + log -i notice 'bootstrap marked complete';; incomplete) # indicate bootstrap isn't done bootstrap_incomplete - log warn 'bootstrap marked incomplete';; + log -i warn 'bootstrap marked incomplete';; *) usage >&2; exit 1;; esac - printf ' bootstrap marked "%s"\n' "$1" >&2 exit 0;; -s|--setup) # just openrc for now for phase in -early -net '' -final; do @@ -67,8 +66,7 @@ esac # is initial bootstrap already done? if [ -f "$TINY_CLOUD_VAR/.bootstrap-complete" ]; then - printf ' already bootstrapped\n' >&2 - log info "$phase - already bootstrapped" + log -i -t "$phase" info "already bootstrapped" exit 0; fi @@ -93,7 +91,7 @@ INIT_ACTIONS_FINAL="${INIT_ACTIONS_FINAL} bootstrap_complete" case "$phase" in early) INIT_ACTIONS="$INIT_ACTIONS_EARLY";; - net) INIT_ACTIONS="$INIT_ACTIONS_NET";; + net) INIT_ACTIONS="$INIT_ACTIONS_NET";; main) INIT_ACTIONS="$INIT_ACTIONS_MAIN";; final) INIT_ACTIONS="$INIT_ACTIONS_FINAL";; *) usage >&2; exit 1 @@ -101,23 +99,23 @@ esac for ACTION in $INIT_ACTIONS; do if skip_action "$ACTION"; then - printf '\n -- %s : [SKIP]' $ACTION >&2 - log warn "$phase - $ACTION - SKIPPED" + printf '\n -- ' >&2 + log -i -t "$phase" notice "$ACTION: skipped" continue fi - printf '\n ++ %s ' $ACTION >&2 - log info "$phase - $ACTION - START" - RESULT="UNKNOWN" + printf '\n ++ ' >&2 + log -i -t "$phase" info "$ACTION" + RESULT="unknown" LEVEL="err" if type "init__$ACTION" | grep -q -w "function"; then if "init__$ACTION" "$@"; then - RESULT="DONE" + RESULT="done" LEVEL="info" else - RESULT="FAIL" + RESULT="failed" fi fi - printf ': [%s]' $RESULT >&2 - log "$LEVEL" "$phase - $ACTION - $RESULT" + printf ' ++ ' >&2 + log -i -t "$phase" "$LEVEL" "$ACTION: $RESULT" done echo >&2 diff --git a/tests/init-early.test b/tests/init-early.test index b3b1302..43c0fe5 100755 --- a/tests/init-early.test +++ b/tests/init-early.test @@ -49,7 +49,7 @@ expand_root_partition_body() { install_hotplugs_fail_body() { CLOUD=aws atf_check -s not-exit:0 \ - -e match:"vnic_eth_hotplug\(!\)" \ + -e match:"vnic_eth_hotplug: failed" \ sh -c ". $lib; HOTPLUG_MODULES='vnic_eth_hotplug'; init__install_hotplugs" } diff --git a/tests/init-final.test b/tests/init-final.test index d75cf6c..8b8a514 100755 --- a/tests/init-final.test +++ b/tests/init-final.test @@ -30,6 +30,11 @@ userdata_type_body() { -o match:"unknown" \ sh -c ". \"$lib\"; userdata_type" + echo "#alpine-config" > var/lib/cloud/user-data + CLOUD="$c" atf_check \ + -o match:"alpine-config" \ + sh -c ". \"$lib\"; userdata_type" + echo "#!/bin/sh" > var/lib/cloud/user-data CLOUD="$c" atf_check -s exit:0 \ -o match:"script" \ diff --git a/tests/init-main.test b/tests/init-main.test index 0cfe770..ed5c012 100755 --- a/tests/init-main.test +++ b/tests/init-main.test @@ -80,6 +80,7 @@ save_userdata_compressed_body() { fake_userdata_nocloud < tmpfile CLOUD="nocloud" atf_check \ + -e 'ignore' \ sh -c ". \"$lib\"; init__save_userdata" if ! grep "^#userdata" var/lib/cloud/user-data; then diff --git a/tests/tiny-cloud-alpine.test b/tests/tiny-cloud-alpine.test index 0229381..0ef1437 100755 --- a/tests/tiny-cloud-alpine.test +++ b/tests/tiny-cloud-alpine.test @@ -38,7 +38,7 @@ set_network_config_network_interfaces_body() { atf_check \ -o match:"rc-update" \ - -e match:"set_network_interfaces .*DONE" \ + -e match:"set_network_interfaces: done" \ tiny-cloud early atf_check \ -o match:"auto eth1" \ @@ -64,7 +64,7 @@ set_network_config_auto_body() { atf_check \ -o match:"rc-update" \ - -e match:"set_network_interfaces .*DONE" \ + -e match:"set_network_interfaces: done" \ tiny-cloud early atf_check \ -o match:"auto eth1" \ @@ -86,7 +86,7 @@ userdata_bootcmd_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_bootcmd .*DONE" \ + -e match:"userdata_bootcmd: done" \ -o match:"^foo$" -o match:"^bar$" \ tiny-cloud main } @@ -99,7 +99,7 @@ userdata_ntp_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_ntp .*DONE" \ + -e match:"userdata_ntp: done" \ -o match:"apk add.*chrony" \ -o match:"rc-update .*chronyd" \ -o match:"rc-service .*chronyd" \ @@ -115,7 +115,7 @@ userdata_ntp_busybox_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_ntp .*DONE" \ + -e match:"userdata_ntp: done" \ -o not-match:"apk add" \ -o match:"rc-update .*ntpd" \ -o match:"rc-service .*ntpd" \ @@ -131,7 +131,7 @@ userdata_ntp_openntpd_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_ntp .*DONE" \ + -e match:"userdata_ntp: done" \ -o match:"apk add.*openntpd" \ -o match:"rc-update .*openntpd" \ -o match:"rc-service .*openntpd" \ @@ -146,7 +146,7 @@ userdata_apk_cache_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_apk_cache .*DONE" \ + -e match:"userdata_apk_cache: done" \ -o ignore \ tiny-cloud main atf_check -o match:"$PWD/var/cache/apk" readlink -f etc/apk/cache @@ -162,7 +162,7 @@ userdata_apk_repositories_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_apk_repositories .*DONE" \ + -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^/srv/packages/main$" \ @@ -181,7 +181,7 @@ userdata_apk_repositories_version_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_apk_repositories .*DONE" \ + -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^https://cdn.alpinelinux.org/edge/main$" \ @@ -202,7 +202,7 @@ userdata_apk_repositories_version_auto_edge_body() { atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_apk_repositories .*DONE" \ + -e match:"userdata_apk_repositories: done" \ -o ignore \ tiny-cloud main atf_check -o match:"^https://cdn.alpinelinux.org/edge/main$" \ @@ -219,7 +219,7 @@ userdata_packages_body() { EOF atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_packages .*DONE" \ + -e match:"userdata_packages: done" \ -o match:"apk add .*tmux" \ -o match:"apk add .*vim" \ tiny-cloud main @@ -235,7 +235,7 @@ userdata_runcmd_body() { # run net phase to extract the user data atf_check -e ignore -o ignore tiny-cloud net atf_check \ - -e match:"userdata_runcmd .*DONE" \ + -e match:"userdata_runcmd: done" \ -o match:"^foo$" -o match:"^bar$" \ tiny-cloud final } diff --git a/tests/tiny-cloud.test b/tests/tiny-cloud.test index 157c97d..f48e2af 100755 --- a/tests/tiny-cloud.test +++ b/tests/tiny-cloud.test @@ -29,7 +29,7 @@ no_metadata_early_body() { fake_netcat for provider in $PROVIDERS; do CLOUD="$provider" atf_check \ - -e not-match:"UNKNOWN" \ + -e not-match:"unknown" \ -e not-match:"not found" \ -e not-match:"o such file" \ -o match:"rc-update add.*sshd" \ @@ -41,8 +41,8 @@ no_userdata_net_body() { fake_netcat for provider in $PROVIDERS; do CLOUD="$provider" atf_check \ - -e not-match:"UNKNOWN" \ - -e match:"save_userdata.*DONE" \ + -e not-match:"unknown" \ + -e match:"save_userdata.*done" \ tiny-cloud net done } @@ -53,7 +53,7 @@ no_userdata_main_body() { # we should not set empty hostname # we should not create .ssh dir for non-existing user CLOUD="$provider" atf_check \ - -e not-match:"UNKNOWN" \ + -e not-match:"unknown" \ -o not-match:"hostname.*-F" \ -o not-match:"chown.*/\.ssh" \ tiny-cloud main @@ -69,11 +69,11 @@ no_userdata_final_body() { fake_netcat for provider in $PROVIDERS; do CLOUD="$provider" atf_check \ - -e not-match:"UNKNOWN" \ - -e match:"bootstrap_complete .*" \ + -e not-match:"unknown" \ + -e match:"bootstrap_complete: done" \ tiny-cloud final CLOUD="$provider" atf_check \ - -e match:"bootstrap marked.*incomplete" \ + -e match:"bootstrap marked incomplete" \ tiny-cloud --bootstrap incomplete done }