# ConfigDrive metadata source selection
# vim:set filetype=sh:
# shellcheck shell=sh

. "$LIBDIR/tiny-cloud/imds-document"
. "$LIBDIR/tiny-cloud/metadata"

# Return 1 for an absent/unusable drive, 2 for a failed load.
configdrive_load() (
	local provider="$1" version="$3" directory="$4"
	local mntdir stagedir mounted format data metadata value loaded rv

	[ "$(id -u)" = 0 ] || return 1
	case "$version" in ''|.*|*[!A-Za-z0-9_.-]*) return 1;; esac
	findfs LABEL=config-2 >/dev/null 2>&1 ||
		findfs LABEL=CONFIG-2 >/dev/null 2>&1 || return 1

	mntdir=$(mktemp -d "$IMDS_TMP_DIR/metadata-volume.XXXXXX") || return 2
	trap '
		rv=$?
		[ -z "$stagedir" ] || rm -rf "$stagedir"
		if [ -n "$mounted" ]; then
			metadata_volume_umount "$mntdir" || rv=2
		else
			rmdir "$mntdir" 2>/dev/null || :
		fi
		exit "$rv"
	' 0
	trap 'exit 2' HUP INT TERM
	metadata_volume_mount "$mntdir" "config-2 CONFIG-2" "vfat iso9660" || return 1
	mounted=1

	for format in native ec2; do
		case "$2" in
			auto|"$format") ;;
			*) continue;;
		esac
		case "$format" in
			native)
				data="$mntdir/openstack/$version"
				metadata=meta_data.json
				value=$(yx -f "$data/$metadata" -- uuid 2>/dev/null) || continue
				;;
			ec2)
				data="$mntdir/ec2/$version"
				metadata=meta-data.json
				value=$(yx -f "$data/$metadata" -- instance-id 2>/dev/null) || continue
				;;
		esac
		case "$value" in ''|null) continue;; esac
		loaded=1
		break
	done
	[ -n "$loaded" ] || return 1

	stagedir=$(mktemp -d "${directory%/*}/.volume.XXXXXX") || return 2
	case "$format" in
		native) set -- meta_data.json user_data network_data.json vendor_data.json vendor_data2.json;;
		ec2) set -- meta-data.json user-data;;
	esac
	for metadata; do
		[ -f "$data/$metadata" ] || continue
		(umask 077; cat "$data/$metadata" > "$stagedir/$metadata") || return 2
	done
	(umask 077; printf '%s configdrive %s %s\n' "$provider" "$format" "$version" > "$stagedir/.selection") || return 2
	metadata_volume_umount "$mntdir" || return 2
	mounted=
	mv "$stagedir" "$directory" || return 2
	stagedir=
)

# Native keys are document members; EC2 members contain an openssh-key field.
configdrive_ssh_keys() {
	local directory="$1" path="$2" format="$3" keys key value result=

	keys=$(imds_document "$directory" "$path") || return
	while IFS= read -r key; do
		[ "$format" != ec2 ] || key="$key/openssh-key"
		value=$(imds_document "$directory" "$path/$key") || return
		result="${result}${value}
"
	done <<-EOT
		$keys
	EOT
	printf '%s' "$result" | sort -u
}
