# IMDS document queries
# vim:set filetype=sh:
# shellcheck shell=sh

. "$LIBDIR/tiny-cloud/document"

# Print an optional member beneath a required document path.
_imds_optional_value() {
	local file="$1" key="$2" keys value
	shift 2
	keys=$(yx -f "$file" -- "$@") || return 1
	printf '%s\n' "$keys" | grep -qxF "$key" || return 0
	value=$(yx -f "$file" -- "$@" "$key") || return 1
	case "$value" in ''|null) return 0;; esac
	printf '%s\n' "$value"
}

# Validate before using a document name in a cache path or fetching its contents.
imds_document_name() {
	local path="$1" document
	case "$path" in
		''|/*) echo "imds: invalid document path '$path'" >&2; return 1;;
	esac
	case "/$path/" in
		*/../*|*/./*)
			echo "imds: invalid document path '$path'" >&2; return 1;;
	esac
	document="${path%%/*}"
	case "$document" in
		*[!A-Za-z0-9_.-]*)
			echo "imds: invalid document name '$document'" >&2; return 1;;
	esac
	printf '%s\n' "$document"
}

imds_document() {
	local directory="$1" path="$2" document file value

	document=$(imds_document_name "$path") || return
	file="$directory/$document"
	[ -f "$file" ] || return 1
	if [ "$directory" = "$TINY_CLOUD_RUN/metadata" ]; then
		_perms_safe "$file" || return
	fi
	if [ "$path" = "$document" ]; then
		cat "$file"
		return
	fi

	value=$(document_select "$file" "${path#*/}") || return
	case "$value" in
		''|null) echo "imds: empty metadata value '$path'" >&2; return 1;;
	esac
	printf '%s\n' "$value"
}
