Files
openclaw/scripts/e2e/lib/parallels-macos-common.sh
2026-04-16 21:52:10 +01:00

143 lines
4.3 KiB
Bash

#!/usr/bin/env bash
parallels_macos_resolve_desktop_user() {
local vm_name="$1"
local user
user="$(prlctl exec "$vm_name" /usr/bin/stat -f '%Su' /dev/console 2>/dev/null | tr -d '\r' | tail -n 1 || true)"
if [[ "$user" =~ ^[A-Za-z0-9._-]+$ && "$user" != "root" && "$user" != "loginwindow" ]]; then
printf '%s\n' "$user"
return 0
fi
prlctl exec "$vm_name" /usr/bin/dscl . -list /Users NFSHomeDirectory 2>/dev/null \
| tr -d '\r' \
| awk '$2 ~ /^\/Users\// && $1 !~ /^_/ && $1 != "Shared" && $1 != ".localized" { print $1; exit }'
}
parallels_macos_resolve_desktop_home() {
local vm_name="$1"
local user="$2"
local home
home="$(
prlctl exec "$vm_name" /usr/bin/dscl . -read "/Users/$user" NFSHomeDirectory 2>/dev/null \
| tr -d '\r' \
| awk '/NFSHomeDirectory:/ { print $2; exit }'
)"
if [[ -n "$home" ]]; then
printf '%s\n' "$home"
else
printf '/Users/%s\n' "$user"
fi
}
parallels_macos_current_user_available() {
local vm_name="$1"
prlctl exec "$vm_name" --current-user /usr/bin/whoami >/dev/null 2>&1
}
parallels_macos_desktop_user_exec_with_secret_file() {
local vm_name="$1"
local user_flag="$2"
local user_name="$3"
local home="$4"
local path_value="$5"
local api_key_env="$6"
local api_key_value="$7"
shift 7
local secret_path
secret_path="/tmp/openclaw-secret-${api_key_env:-env}-$RANDOM-$RANDOM"
if [[ -n "$api_key_env" && -n "$api_key_value" ]]; then
if [[ "$user_flag" == "current-user" ]]; then
printf '%s' "$api_key_value" | /usr/bin/base64 | prlctl exec "$vm_name" \
--current-user /usr/bin/base64 -D -o "$secret_path"
else
printf '%s' "$api_key_value" | /usr/bin/base64 | prlctl exec "$vm_name" \
/usr/bin/sudo -H -u "$user_name" /usr/bin/base64 -D -o "$secret_path"
fi
fi
local wrapper
local wrapper_path
wrapper_path="/tmp/openclaw-secret-env-wrapper-$RANDOM-$RANDOM.sh"
wrapper='#!/bin/bash
set -e
cleanup() {
rm -f "${OPENCLAW_WRAPPER_FILE:-}"
}
trap cleanup EXIT
if [ -n "${OPENCLAW_SECRET_ENV_NAME:-}" ] && [ -n "${OPENCLAW_SECRET_FILE:-}" ] && [ -f "$OPENCLAW_SECRET_FILE" ]; then
secret_value="$(cat "$OPENCLAW_SECRET_FILE")"
rm -f "$OPENCLAW_SECRET_FILE"
export "${OPENCLAW_SECRET_ENV_NAME}=${secret_value}"
fi
"$@"
'
if [[ "$user_flag" == "current-user" ]]; then
printf '%s' "$wrapper" | /usr/bin/base64 | prlctl exec "$vm_name" \
--current-user /usr/bin/base64 -D -o "$wrapper_path"
else
printf '%s' "$wrapper" | /usr/bin/base64 | prlctl exec "$vm_name" \
/usr/bin/sudo -H -u "$user_name" /usr/bin/base64 -D -o "$wrapper_path"
fi
if [[ "$user_flag" == "current-user" ]]; then
prlctl exec "$vm_name" --current-user /usr/bin/env \
"PATH=$path_value" \
"OPENCLAW_SECRET_ENV_NAME=$api_key_env" \
"OPENCLAW_SECRET_FILE=$secret_path" \
"OPENCLAW_WRAPPER_FILE=$wrapper_path" \
/bin/bash "$wrapper_path" "$@"
return
fi
prlctl exec "$vm_name" /usr/bin/sudo -H -u "$user_name" /usr/bin/env \
"HOME=$home" \
"USER=$user_name" \
"LOGNAME=$user_name" \
"PATH=$path_value" \
"OPENCLAW_SECRET_ENV_NAME=$api_key_env" \
"OPENCLAW_SECRET_FILE=$secret_path" \
"OPENCLAW_WRAPPER_FILE=$wrapper_path" \
/bin/bash "$wrapper_path" "$@"
}
parallels_macos_desktop_user_exec() {
local vm_name="$1"
local api_key_env="$2"
local api_key_value="$3"
shift 3
if parallels_macos_current_user_available "$vm_name"; then
parallels_macos_desktop_user_exec_with_secret_file \
"$vm_name" \
"current-user" \
"" \
"" \
"/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin" \
"$api_key_env" \
"$api_key_value" \
"$@"
return
fi
local user home
user="$(parallels_macos_resolve_desktop_user "$vm_name")"
[[ -n "$user" ]] || {
printf 'unable to resolve macOS desktop user for sudo fallback\n' >&2
return 1
}
home="$(parallels_macos_resolve_desktop_home "$vm_name" "$user")"
printf 'warn: macOS --current-user unavailable; using root sudo fallback for %s\n' "$user" >&2
parallels_macos_desktop_user_exec_with_secret_file \
"$vm_name" \
"sudo" \
"$user" \
"$home" \
"/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin" \
"$api_key_env" \
"$api_key_value" \
"$@"
}