(service_name: str, name_prefix: str, meta: Dict[str, Any])
| 714 | |
| 715 | |
| 716 | def _render_stop_script(service_name: str, name_prefix: str, meta: Dict[str, Any]) -> str: |
| 717 | nodes: List[str] = _ensure_list(meta.get("nodes")) |
| 718 | allowed_line = f"ALLOWED_NODES=({' '.join(nodes)})" if nodes else "ALLOWED_NODES=()" |
| 719 | script = """#!/usr/bin/env bash |
| 720 | set -euo pipefail |
| 721 | |
| 722 | # === Dry-Run Mode === |
| 723 | # Usage: ./stop_and_rm_"$SERVICE".sh --dry-run | -n |
| 724 | DRY_RUN="${DRY_RUN:-0}" |
| 725 | if [ "${1:-}" = "--dry-run" ] || [ "${1:-}" = "-n" ]; then DRY_RUN=1; shift; fi |
| 726 | run_cmd() { |
| 727 | if [ "${DRY_RUN}" = "1" ]; then |
| 728 | printf '[dry-run] ' |
| 729 | printf '%q ' "$@" |
| 730 | echo |
| 731 | else |
| 732 | "$@" |
| 733 | fi |
| 734 | } |
| 735 | |
| 736 | """ |
| 737 | script += f"SERVICE={_shell_single_quote(service_name)}\n" |
| 738 | script += f"NAME_PREFIX={_shell_single_quote(name_prefix)}\n" |
| 739 | script += allowed_line + "\n" |
| 740 | script += """ |
| 741 | LOCAL_HOSTNAME=$(hostname -s 2>/dev/null || hostname 2>/dev/null || echo unknown) |
| 742 | LOCAL_FQDN=$(hostname -f 2>/dev/null || echo "$LOCAL_HOSTNAME") |
| 743 | NODE_ID="$LOCAL_HOSTNAME" |
| 744 | # If service has explicit binding and current node not allowed, skip |
| 745 | if [ ${#ALLOWED_NODES[@]} -gt 0 ]; then |
| 746 | _ok=false |
| 747 | for n in "${ALLOWED_NODES[@]}"; do if [ "$n" = "$NODE_ID" ] || [ "$n" = "$LOCAL_FQDN" ]; then _ok=true; fi; done |
| 748 | if [ "$_ok" != true ]; then echo "Service '$SERVICE' not scheduled on this node ($NODE_ID). Allowed: ${ALLOWED_NODES[*]}"; exit 0; fi |
| 749 | fi |
| 750 | |
| 751 | CONTAINER_NAME="${NAME_PREFIX}-${SERVICE}-${NODE_ID}" |
| 752 | echo "Stopping $CONTAINER_NAME" |
| 753 | run_cmd docker stop "$CONTAINER_NAME" || true |
| 754 | run_cmd docker rm "$CONTAINER_NAME" || true |
| 755 | """ |
| 756 | return script |
| 757 | |
| 758 | |
| 759 | def _render_remove_all_script( |
no test coverage detected