132 lines
4.8 KiB
Bash
Executable file
132 lines
4.8 KiB
Bash
Executable file
#!/bin/bash
|
||
# VM 端权限请求提交助手 — 生成 .perm.json 到 outbox
|
||
# 用法: submit-request.sh --category <cat> --action <act> [选项]
|
||
# 示例:
|
||
# submit-request.sh --category status_query --action query_vm_status --target-vm fedora --reason "查看状态"
|
||
# submit-request.sh --category package_install --action install_package --packages "ripgrep fd-find" --reason "需要搜索工具"
|
||
# submit-request.sh --category service_restart --action restart_service --service keyd --reason "键盘映射失效"
|
||
set -euo pipefail
|
||
|
||
OUTBOX_DIR="$HOME/docs/ai-context/outbox"
|
||
# 优先使用 ~/.vm-name(inventory 名),回退到 hostname
|
||
if [[ -f "$HOME/.vm-name" ]]; then
|
||
HOSTNAME=$(cat "$HOME/.vm-name" | tr -d '[:space:]')
|
||
else
|
||
HOSTNAME=$(hostname -s 2>/dev/null || cat /etc/hostname 2>/dev/null || echo "unknown")
|
||
fi
|
||
|
||
# 颜色
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
用法: submit-request.sh --category <类别> --action <动作> [选项]
|
||
|
||
必需参数:
|
||
--category 请求类别 (status_query|package_install|service_restart|config_sync|
|
||
knowledge_contribution|message_send|run_playbook_safe|cron_change)
|
||
--action 具体动作 (query_vm_status|install_package|restart_service|sync_config|
|
||
run_playbook|list_vms)
|
||
--reason 请求原因
|
||
|
||
可选参数:
|
||
--target-vm 目标 VM 名称 (默认: fedora)
|
||
--packages 要安装的包列表 (空格分隔,引号包裹)
|
||
--service 要操作的服务名
|
||
--playbook 要运行的 playbook 名
|
||
--config-path 要同步的配置路径
|
||
--extra 额外 JSON 参数 (如 '{"key":"value"}')
|
||
EOF
|
||
exit 1
|
||
}
|
||
|
||
# 参数解析
|
||
CATEGORY="" ACTION="" REASON="" TARGET_VM="fedora"
|
||
PACKAGES="" SERVICE="" PLAYBOOK="" CONFIG_PATH="" EXTRA="{}"
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--category) CATEGORY="$2"; shift 2 ;;
|
||
--action) ACTION="$2"; shift 2 ;;
|
||
--reason) REASON="$2"; shift 2 ;;
|
||
--target-vm) TARGET_VM="$2"; shift 2 ;;
|
||
--packages) PACKAGES="$2"; shift 2 ;;
|
||
--service) SERVICE="$2"; shift 2 ;;
|
||
--playbook) PLAYBOOK="$2"; shift 2 ;;
|
||
--config-path) CONFIG_PATH="$2"; shift 2 ;;
|
||
--extra) EXTRA="$2"; shift 2 ;;
|
||
-h|--help) usage ;;
|
||
*) echo -e "${RED}未知参数: $1${NC}"; usage ;;
|
||
esac
|
||
done
|
||
|
||
[[ -z "$CATEGORY" ]] && { echo -e "${RED}缺少 --category${NC}"; usage; }
|
||
[[ -z "$ACTION" ]] && { echo -e "${RED}缺少 --action${NC}"; usage; }
|
||
[[ -z "$REASON" ]] && { echo -e "${RED}缺少 --reason${NC}"; usage; }
|
||
|
||
# 确保 outbox 目录存在
|
||
mkdir -p "$OUTBOX_DIR"
|
||
|
||
# 生成请求 ID 和时间戳
|
||
REQUEST_ID=$(date +%s)-$$
|
||
TIMESTAMP=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date '+%Y-%m-%dT%H:%M:%SZ')
|
||
FILENAME="$(date '+%Y-%m-%d-%H%M%S')-perm-${REQUEST_ID}.perm.json"
|
||
EXPIRES_AT=$(date -u -d "+60 minutes" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || \
|
||
date -u -v+60M '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || \
|
||
echo "")
|
||
|
||
# 分类提示
|
||
case "$CATEGORY" in
|
||
status_query|knowledge_contribution|message_send|run_playbook_safe)
|
||
TIER_HINT="L0" ;;
|
||
package_install|service_restart|config_sync|cron_change)
|
||
TIER_HINT="L1" ;;
|
||
*)
|
||
TIER_HINT="unknown" ;;
|
||
esac
|
||
|
||
# 构建 params 对象
|
||
PARAMS=$(jq -n \
|
||
--arg packages "$PACKAGES" \
|
||
--arg service "$SERVICE" \
|
||
--arg playbook "$PLAYBOOK" \
|
||
--arg config_path "$CONFIG_PATH" \
|
||
--argjson extra "$EXTRA" \
|
||
'{} +
|
||
(if $packages != "" then {packages: ($packages | split(" "))} else {} end) +
|
||
(if $service != "" then {service: $service} else {} end) +
|
||
(if $playbook != "" then {playbook: $playbook} else {} end) +
|
||
(if $config_path != "" then {config_path: $config_path} else {} end) +
|
||
$extra')
|
||
|
||
# 生成请求 JSON
|
||
jq -n \
|
||
--arg request_id "$REQUEST_ID" \
|
||
--arg source_vm "$HOSTNAME" \
|
||
--arg target_vm "$TARGET_VM" \
|
||
--arg category "$CATEGORY" \
|
||
--arg action "$ACTION" \
|
||
--arg reason "$REASON" \
|
||
--arg tier_hint "$TIER_HINT" \
|
||
--arg timestamp "$TIMESTAMP" \
|
||
--arg expires_at "$EXPIRES_AT" \
|
||
--argjson params "$PARAMS" \
|
||
'{
|
||
request_id: $request_id,
|
||
source_vm: $source_vm,
|
||
target_vm: $target_vm,
|
||
category: $category,
|
||
action: $action,
|
||
reason: $reason,
|
||
tier_hint: $tier_hint,
|
||
params: $params,
|
||
timestamp: $timestamp,
|
||
expires_at: $expires_at
|
||
}' > "$OUTBOX_DIR/$FILENAME"
|
||
|
||
echo -e "${GREEN}请求已提交:${NC} $OUTBOX_DIR/$FILENAME"
|
||
echo -e " 类别: ${YELLOW}${CATEGORY}${NC} (${TIER_HINT})"
|
||
echo -e " 动作: ${ACTION}"
|
||
echo -e " 目标: ${TARGET_VM}"
|
||
echo -e " 原因: ${REASON}"
|
||
echo -e "${GREEN}等待 fedora 处理(cron */5 或手动运行 process-permission-requests.sh)${NC}"
|