(
service_name: str,
name_prefix: str,
meta: Dict[str, Any],
node_ips: Dict[str, str],
node_hostworkdir: Dict[str, str],
node_mounts: Dict[str, List[Tuple[str, str]]],
global_envs: Dict[str, Any],
svc_meta: Dict[str, Dict[str, Any]],
shared_host: str = "",
shared_mount: str = "",
)
| 471 | |
| 472 | |
| 473 | def _render_service_script( |
| 474 | service_name: str, |
| 475 | name_prefix: str, |
| 476 | meta: Dict[str, Any], |
| 477 | node_ips: Dict[str, str], |
| 478 | node_hostworkdir: Dict[str, str], |
| 479 | node_mounts: Dict[str, List[Tuple[str, str]]], |
| 480 | global_envs: Dict[str, Any], |
| 481 | svc_meta: Dict[str, Dict[str, Any]], |
| 482 | shared_host: str = "", |
| 483 | shared_mount: str = "", |
| 484 | ) -> str: |
| 485 | image = str(meta.get("image", "")).strip() |
| 486 | hostport = bool(meta.get("hostport", False)) |
| 487 | hostnetwork = bool(meta.get("hostnetwork", False)) |
| 488 | docker_networks_raw = meta.get("docker_networks", []) or [] |
| 489 | docker_networks: List[str] = [] |
| 490 | for n in _ensure_list(docker_networks_raw): |
| 491 | if isinstance(n, str) and n.strip(): |
| 492 | docker_networks.append(n.strip()) |
| 493 | port: Optional[int] = meta.get("port") |
| 494 | entrypoint: Optional[str] = meta.get("entrypoint") |
| 495 | entrypoint_mode: str = str(meta.get("entrypoint_mode", "bash")).strip().lower() |
| 496 | nodes: List[str] = _ensure_list(meta.get("nodes")) |
| 497 | |
| 498 | # Helper: convert names to ENV keys |
| 499 | def _to_env_key(x: str) -> str: |
| 500 | key = re.sub(r"[^A-Za-z0-9_]", "_", x) |
| 501 | key = re.sub(r"_+", "_", key).strip("_") |
| 502 | if not key: |
| 503 | key = "X" |
| 504 | if key[0].isdigit(): |
| 505 | key = "_" + key |
| 506 | return key.upper() |
| 507 | |
| 508 | # Precompute dynamic chunks |
| 509 | # Build case lines for indirect expansion of exported <NODE>__IP |
| 510 | ip_by_node_case_lines: List[str] = [] |
| 511 | for nid in node_ips.keys(): |
| 512 | env_key = _to_env_key(nid) + "__IP" |
| 513 | ip_by_node_case_lines.append(f" {nid}) _ip_n=\"${{{env_key}}}\" ;;") |
| 514 | |
| 515 | allowed_nodes_line = ( |
| 516 | f"ALLOWED_NODES=({' '.join(nodes)})" if nodes else "ALLOWED_NODES=() # no explicit binding" |
| 517 | ) |
| 518 | all_nodes_line = f"ALL_NODES=({' '.join(node_ips.keys())})" |
| 519 | |
| 520 | node_case_body = [] |
| 521 | for nid, ip in node_ips.items(): |
| 522 | hw = node_hostworkdir.get(nid, "") |
| 523 | hw_assign = f"HOSTWORKDIR={_shell_single_quote(hw)}" if hw else "# HOSTWORKDIR not set" |
| 524 | # Per-node mounts inline into DOCKER_RUN |
| 525 | mounts = node_mounts.get(nid, []) |
| 526 | mount_parts: List[str] = [] |
| 527 | if hw: |
| 528 | mount_parts.append(f"DOCKER_RUN+=( -v {_shell_single_quote(hw + ':/hostworkdir')} )") |
| 529 | for h, c in mounts: |
| 530 | mount_parts.append(f"DOCKER_RUN+=( -v {_shell_single_quote(f'{h}:{c}')} )") |
no test coverage detected