mirror of
https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git
synced 2025-12-15 11:22:43 +03:00
Fixes for tiny-cloud Wrapper
* switch from phase functions to variables containing list of actions * init actions prefixed with 'init__' * refine output during init * add syslog entries * add --setup for putting init scripts in the right runlevel
This commit is contained in:
parent
3894cd9f8d
commit
58ac2108cd
@ -9,7 +9,7 @@
|
||||
: "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}"
|
||||
|
||||
log() {
|
||||
local facility="kern"
|
||||
local facility="local7"
|
||||
local stderr
|
||||
local tag=$(basename "$0")
|
||||
while [ "${1#-}" != "$1" ]; do
|
||||
|
||||
@ -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,38 @@ expand_root() {
|
||||
$MOCK resize2fs "$dev"
|
||||
}
|
||||
|
||||
install_hotplugs() {
|
||||
skip_action install_hotplugs && return
|
||||
init__install_hotplugs() {
|
||||
local level result rc=0
|
||||
|
||||
[ ! -n "$HOTPLUG_MODULES" ] && return
|
||||
|
||||
echo "Installing Cloud Hotplugs"
|
||||
|
||||
local result rc=0
|
||||
|
||||
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='?'
|
||||
level='err'
|
||||
printf "$module" >&2
|
||||
log info "$phase $ACTION $module"
|
||||
if type "mod__$module" | grep -q -w "function"; then
|
||||
"mod__$module" && result='+' || { result='!'; rc=1; }
|
||||
if "mod__$module"; then
|
||||
result='+'
|
||||
level='info'
|
||||
else
|
||||
result='!'
|
||||
rc=1
|
||||
fi
|
||||
fi
|
||||
printf "($result)"
|
||||
printf '(%s) ' $result >&2
|
||||
log "$level" "$phase $ACTION $module ($result)"
|
||||
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 +85,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 +103,62 @@ 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
|
||||
log info "$phase $ACTION - not exectutable"
|
||||
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 +168,6 @@ userdata_type() {
|
||||
echo missing
|
||||
fi
|
||||
}
|
||||
|
||||
# ...load user-data type-specific init functions / vars
|
||||
# TODO
|
||||
|
||||
@ -10,22 +10,19 @@ set -e
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${0##*/} [-h | --help] { early | main | final | --bootstrap {complete|incomplete} }
|
||||
Usage: ${0##*/} [-h | --help] { early | main | final | --bootstrap {complete|incomplete} | --setup }
|
||||
EOF
|
||||
}
|
||||
|
||||
bootstrap_complete() {
|
||||
echo "Marking Instance Bootstrap Complete"
|
||||
init__bootstrap_complete() {
|
||||
touch "$TINY_CLOUD_VAR/.bootstrap-complete"
|
||||
}
|
||||
|
||||
bootstrap_incomplete() {
|
||||
echo "Marking Instance Bootstrap Incomplete"
|
||||
rm -f "$TINY_CLOUD_VAR/.bootstrap-complete"
|
||||
}
|
||||
|
||||
args=$(getopt -o hb: --long help,bootstrap: -n ${0##*/} -- "$@")
|
||||
if [ $? -ne 0 ]; then
|
||||
args=$(getopt -o hsb: --long help,setup,bootstrap: -n ${0##*/} -- "$@")
|
||||
if [ $? -ne 0 ] || [ $# -eq 0 ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
@ -36,11 +33,22 @@ while true; do
|
||||
-b|--bootstrap) shift
|
||||
case "$1" in
|
||||
complete) # indicate bootstrap is done
|
||||
bootstrap_complete;;
|
||||
init__bootstrap_complete
|
||||
log warn 'bootstrap marked complete';;
|
||||
incomplete) # indicate bootstrap isn't done
|
||||
bootstrap_incomplete;;
|
||||
bootstrap_incomplete
|
||||
log 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 '' -final; do
|
||||
rc-update -a del "tiny-cloud$phase" || true
|
||||
done
|
||||
rc-update add tiny-cloud-early boot
|
||||
rc-update add tiny-cloud default
|
||||
rc-update add tiny-cloud-final default
|
||||
exit 0;;
|
||||
--) shift; break;;
|
||||
*) usage >&2; exit 1;;
|
||||
@ -58,32 +66,56 @@ esac
|
||||
|
||||
# is initial bootstrap already done?
|
||||
if [ -f "$TINY_CLOUD_VAR/.bootstrap-complete" ]; then
|
||||
log -s "Already bootstrapped"
|
||||
printf ' already bootstrapped\n' >&2
|
||||
log info "$phase - already bootstrapped"
|
||||
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
|
||||
[ "$i" = "$action" ] && return 0
|
||||
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
|
||||
log warn "$phase - $ACTION - SKIPPED"
|
||||
continue
|
||||
fi
|
||||
printf '\n ++ %s ' $ACTION >&2
|
||||
log info "$phase - $ACTION - START"
|
||||
RESULT="UNKNOWN"
|
||||
LEVEL="err"
|
||||
if type "init__$ACTION" | grep -q -w "function"; then
|
||||
if "init__$ACTION" "$@"; then
|
||||
RESULT="DONE"
|
||||
LEVEL="info"
|
||||
else
|
||||
RESULT="FAIL"
|
||||
fi
|
||||
fi
|
||||
printf ': [%s]' $RESULT >&2
|
||||
log "$LEVEL" "$phase - $ACTION - $RESULT"
|
||||
done
|
||||
echo >&2
|
||||
|
||||
@ -9,33 +9,21 @@ lib="$srcdir"/lib/tiny-cloud/init
|
||||
init_tests \
|
||||
expand_root \
|
||||
expand_root_partition \
|
||||
expand_root_skip \
|
||||
install_hotplugs_skip \
|
||||
install_hotplugs_fail
|
||||
|
||||
PROVIDERS="aws azure gcp nocloud oci"
|
||||
|
||||
expand_root_body() {
|
||||
fake_bin test-expand-root <<-EOF
|
||||
#!/bin/sh
|
||||
. "$lib"
|
||||
expand_root
|
||||
EOF
|
||||
mkdir proc
|
||||
echo "/dev/xvda / ext4 rw,noatime 0 0" > proc/mounts
|
||||
for provider in $PROVIDERS; do
|
||||
CLOUD="$provider" atf_check \
|
||||
-o match:"resize2fs /dev/xvda" \
|
||||
test-expand-root
|
||||
sh -c ". $lib; init__expand_root"
|
||||
done
|
||||
}
|
||||
|
||||
expand_root_partition_body() {
|
||||
fake_bin test-expand-root <<-EOF
|
||||
#!/bin/sh
|
||||
. "$lib"
|
||||
expand_root
|
||||
EOF
|
||||
mkdir -p proc sys/class/block \
|
||||
sys/devices/pci0000:00/0000:00:1b.0/0000:01:00.0/nvme/nvme0/nvme0n1/nvme0n1p2 \
|
||||
sys/devices/pci0000:00/0000:00:1b.0/0000:01:00.0/nvme/nvme0/nvme0n1/device
|
||||
@ -49,46 +37,12 @@ expand_root_partition_body() {
|
||||
-o match:"sfdisk .*/dev/nvme0n1" \
|
||||
-o match:"partx .*/dev/nvme0n1" \
|
||||
-o match:"resize2fs /dev/nvme0n1p2" \
|
||||
test-expand-root
|
||||
done
|
||||
}
|
||||
|
||||
expand_root_skip_body() {
|
||||
fake_bin test-expand-root <<-EOF
|
||||
#!/bin/sh
|
||||
SKIP_INIT_ACTIONS=expand_root
|
||||
. "$lib"
|
||||
expand_root
|
||||
EOF
|
||||
for provider in $PROVIDERS; do
|
||||
CLOUD="$provider" atf_check \
|
||||
-o match:'^ SKIPPING$' \
|
||||
test-expand-root
|
||||
done
|
||||
}
|
||||
|
||||
install_hotplugs_skip_body() {
|
||||
fake_bin test-install-hotplugs <<-EOF
|
||||
#!/bin/sh
|
||||
SKIP_INIT_ACTIONS=install_hotplugs
|
||||
. "$lib"
|
||||
install_hotplugs
|
||||
EOF
|
||||
for provider in $PROVIDERS; do
|
||||
CLOUD="$provider" atf_check \
|
||||
-o match:'^ SKIPPING$' \
|
||||
test-install-hotplugs
|
||||
sh -c ". $lib; init__expand_root"
|
||||
done
|
||||
}
|
||||
|
||||
install_hotplugs_fail_body() {
|
||||
fake_bin test-install-hotplugs <<-EOF
|
||||
#!/bin/sh
|
||||
HOTPLUG_MODULES="vnic_eth_hotplug"
|
||||
. "$lib"
|
||||
install_hotplugs
|
||||
EOF
|
||||
CLOUD=aws atf_check -s not-exit:0 \
|
||||
-o match:"^ vnic_eth_hotplug\(!\)$" \
|
||||
test-install-hotplugs
|
||||
-e match:"vnic_eth_hotplug\(!\)" \
|
||||
sh -c ". $lib; HOTPLUG_MODULES='vnic_eth_hotplug'; init__install_hotplugs"
|
||||
}
|
||||
|
||||
@ -38,10 +38,10 @@ run_userdata_body() {
|
||||
echo "hello from user-data"
|
||||
EOF
|
||||
CLOUD="nocloud" atf_check \
|
||||
sh -c ". \"$lib\"; save_userdata"
|
||||
sh -c ". \"$lib\"; init__save_userdata"
|
||||
CLOUD="nocloud" atf_check \
|
||||
-o match:"hello from user-data" \
|
||||
sh -c ". \"$lib\"; run_userdata"
|
||||
sh -c ". \"$lib\"; init__run_userdata"
|
||||
grep "hello from user-data" var/log/user-data.log || atf_fail "user-data.log failed"
|
||||
grep -w "0" var/log/user-data.exit || atf_fail "user-data.exit failed"
|
||||
}
|
||||
|
||||
@ -42,16 +42,8 @@ set_hostname_body() {
|
||||
|
||||
CLOUD="nocloud" atf_check \
|
||||
-o match:"hostname.*-F $PWD/etc/hostname" \
|
||||
sh -c ". \"$lib\"; set_hostname"
|
||||
sh -c ". \"$lib\"; init__set_hostname"
|
||||
atf_check -o match:"^myhostname$" cat etc/hostname
|
||||
|
||||
rm etc/hostname
|
||||
CLOUD="nocloud" atf_check \
|
||||
-o not-match:"hostname.*-F $PWD/etc/hostname" \
|
||||
sh -c "SKIP_INIT_ACTIONS=set_hostname ; . \"$lib\"; set_hostname"
|
||||
if test -f etc/hostname; then
|
||||
atf_fail "etc/hostname should not exist"
|
||||
fi
|
||||
}
|
||||
|
||||
set_ssh_keys_body() {
|
||||
@ -66,7 +58,7 @@ set_ssh_keys_body() {
|
||||
EOF
|
||||
CLOUD="nocloud" atf_check \
|
||||
-o match:"chown.*/\.ssh" \
|
||||
sh -c ". \"$lib\"; set_ssh_keys"
|
||||
sh -c ". \"$lib\"; init__set_ssh_keys"
|
||||
atf_check -o match:"^ssh-ed25519 keydata" \
|
||||
-o match:"^ssh-rsa foobar" \
|
||||
cat home/alpine/.ssh/authorized_keys
|
||||
@ -77,7 +69,7 @@ save_userdata_plain_body() {
|
||||
#userdata
|
||||
EOF
|
||||
CLOUD="nocloud" atf_check \
|
||||
sh -c ". \"$lib\"; save_userdata"
|
||||
sh -c ". \"$lib\"; init__save_userdata"
|
||||
atf_check -o match:"^#userdata" cat var/lib/cloud/user-data
|
||||
}
|
||||
|
||||
@ -88,7 +80,7 @@ save_userdata_compressed_body() {
|
||||
fake_userdata_nocloud < tmpfile
|
||||
|
||||
CLOUD="nocloud" atf_check \
|
||||
sh -c ". \"$lib\"; save_userdata"
|
||||
sh -c ". \"$lib\"; init__save_userdata"
|
||||
|
||||
if ! grep "^#userdata" var/lib/cloud/user-data; then
|
||||
atf_fail "$comp failed"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user