- 用户决定仅用部署前手动轻量快照,不再推进对象存储、ARM/hyinda-20c 备份 - refresh-deployment-contract 新增 /etc/hyb-oa-backup-mode 显式模式: 无文件保持原自动模式;manual_snapshot 要求三个备份 timer 停用且备份 service 已退出,ops timer 仍须运行;内容/属主/符号链接异常 fail-closed - probe 部署前与 refresh 部署后均校验模式与 timer/service 一致性 - 新增 44 backup_mode_invalid / 45 backup_timer_not_disabled 分类及合同测试 - 记录 10-05 ARM 与 hyinda-20c 只读核验结果、远端切换顺序与回滚 - 远端切换未执行,需另行批准 Co-Authored-By: Claude Opus 5.5 <[email protected]>
89 行
2.7 KiB
Bash
可执行文件
89 行
2.7 KiB
Bash
可执行文件
#!/usr/bin/env bash
|
|
|
|
DEPLOY_CONTRACT_KEYS=(
|
|
REMOTE_DIR
|
|
REMOTE_ENV_FILE
|
|
COMPOSE_FILE
|
|
COMPOSE_PROJECT_NAME
|
|
POSTGRES_DATA_DIR
|
|
STORAGE_HOST_DIR
|
|
)
|
|
|
|
deployment_contract_safe_ssh_target() {
|
|
[[ "${1:-}" =~ ^([A-Za-z0-9._-]+@)?[A-Za-z0-9._-]+$ ]]
|
|
}
|
|
|
|
deployment_contract_safe_service() {
|
|
[[ "${1:-}" =~ ^[A-Za-z0-9_.@-]+\.service$ ]]
|
|
}
|
|
|
|
deployment_contract_safe_absolute_path() {
|
|
local value="${1:-}"
|
|
[[ -n "$value" && "$value" == /* && "$value" =~ ^/[A-Za-z0-9._/-]+$ \
|
|
&& "$value" != "/" && "$value" != */ && "$value" != *"//"* \
|
|
&& "/$value/" != *"/../"* && "/$value/" != *"/./"* ]]
|
|
}
|
|
|
|
deployment_contract_safe_compose_file() {
|
|
local value="${1:-}"
|
|
[[ -n "$value" && "$value" != /* && "$value" =~ ^[A-Za-z0-9._/-]+$ \
|
|
&& "/$value/" != *"/../"* && "/$value/" != *"/./"* ]]
|
|
}
|
|
|
|
deployment_contract_safe_project() {
|
|
[[ "${1:-}" =~ ^[a-z0-9][a-z0-9_-]*$ ]]
|
|
}
|
|
|
|
deployment_contract_load() {
|
|
local target="$1"
|
|
local unit="$2"
|
|
local destination_name="$3"
|
|
local unit_environment key value
|
|
local -n destination="$destination_name"
|
|
|
|
destination=()
|
|
deployment_contract_safe_ssh_target "$target" || return 1
|
|
deployment_contract_safe_service "$unit" || return 1
|
|
unit_environment="$(ssh "$target" "systemctl show '${unit}' -p Environment --value" 2>/dev/null)" \
|
|
|| return 1
|
|
[[ -n "$unit_environment" ]] || return 1
|
|
|
|
for entry in $unit_environment; do
|
|
key="${entry%%=*}"
|
|
value="${entry#*=}"
|
|
case "$key" in
|
|
REMOTE_DIR|REMOTE_ENV_FILE|COMPOSE_FILE|COMPOSE_PROJECT_NAME|POSTGRES_DATA_DIR|STORAGE_HOST_DIR)
|
|
destination["$key"]="$value"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
for key in "${DEPLOY_CONTRACT_KEYS[@]}"; do
|
|
[[ -n "${destination[$key]:-}" ]] || return 1
|
|
done
|
|
deployment_contract_safe_absolute_path "${destination[REMOTE_DIR]}" || return 1
|
|
deployment_contract_safe_absolute_path "${destination[REMOTE_ENV_FILE]}" || return 1
|
|
deployment_contract_safe_absolute_path "${destination[POSTGRES_DATA_DIR]}" || return 1
|
|
deployment_contract_safe_absolute_path "${destination[STORAGE_HOST_DIR]}" || return 1
|
|
deployment_contract_safe_compose_file "${destination[COMPOSE_FILE]}" || return 1
|
|
deployment_contract_safe_project "${destination[COMPOSE_PROJECT_NAME]}" || return 1
|
|
}
|
|
|
|
deployment_contract_refresh_category() {
|
|
local status="${1:-1}"
|
|
local output="${2:-}"
|
|
if [[ "$status" == "0" \
|
|
&& "$output" == "[deployment-contract-refresh][PASS] refreshed" ]]; then
|
|
printf 'success'
|
|
return 0
|
|
fi
|
|
case "$status" in
|
|
255) printf 'root_identity_unavailable' ;;
|
|
126|127) printf 'refresh_program_unavailable' ;;
|
|
43) printf 'timer_not_active' ;;
|
|
44) printf 'backup_mode_invalid' ;;
|
|
45) printf 'backup_timer_not_disabled' ;;
|
|
*) printf 'unit_build_not_refreshed' ;;
|
|
esac
|
|
}
|