3e779be6f3
CI / lint (push) Failing after 13m4s
CI / test (3.11, ubuntu-latest) (push) Failing after 2m4s
CI / test (3.13, ubuntu-latest) (push) Successful in 13m30s
CI / test (3.14, ubuntu-latest) (push) Successful in 17m21s
CI / test (3.12, ubuntu-latest) (push) Successful in 17m55s
CI / discover-apps-ps (push) Successful in 1m56s
CI / test (3.9, ubuntu-latest) (push) Successful in 13m17s
CI / test (3.10, ubuntu-latest) (push) Successful in 26m21s
CI / audit (push) Successful in 13m38s
Deploy site / deploy (push) Has been cancelled
CI / test (3.14, ubuntu-24.04-arm) (push) Has been cancelled
57 lines
2.4 KiB
Python
57 lines
2.4 KiB
Python
# SPDX-License-Identifier: MIT
|
|
"""Lock the host-side agent port single source of truth.
|
|
|
|
`core/agent.AGENT_PORT` is the only Python literal for the guest agent
|
|
listener port; everything else (the compose template, the urlacl strings
|
|
we push into the guest, the AgentClient URL) must derive from it. These
|
|
tests fail loudly the moment someone re-introduces a literal copy."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from winpodx.core import guest_sync
|
|
from winpodx.core.agent import AGENT_PORT, AgentClient
|
|
from winpodx.core.guest_disk import GUEST_SMB_PORT, SMB_HOST_PORT
|
|
from winpodx.core.pod import compose
|
|
|
|
|
|
def test_agent_port_default_value() -> None:
|
|
# Pinning the actual value so a typo-rebind elsewhere can't silently
|
|
# change the port the guest binds vs. what the host probes.
|
|
assert AGENT_PORT == 8765
|
|
|
|
|
|
def test_agent_client_default_base_url_uses_constant() -> None:
|
|
assert AgentClient.DEFAULT_BASE_URL == f"http://127.0.0.1:{AGENT_PORT}"
|
|
|
|
|
|
def test_compose_template_port_mapping_uses_constant() -> None:
|
|
# USER_PORTS (dockur slirp hostfwd) + the loopback port mapping must
|
|
# both reference AGENT_PORT, not a separate literal. We assert the
|
|
# rendered template, not just the source, because the .format() call
|
|
# is where drift would actually break the container.
|
|
from winpodx.core.config import Config
|
|
|
|
cfg = Config()
|
|
rendered = compose._build_compose_content(cfg)
|
|
# USER_PORTS forwards both the agent port and the guest SMB port (#616).
|
|
assert f'USER_PORTS: "{AGENT_PORT},{GUEST_SMB_PORT}"' in rendered
|
|
assert f'"127.0.0.1:{AGENT_PORT}:{AGENT_PORT}/tcp"' in rendered
|
|
# Guest SMB share (reverse-open guest-disk) published on loopback only.
|
|
assert f'"127.0.0.1:{SMB_HOST_PORT}:{GUEST_SMB_PORT}/tcp"' in rendered
|
|
# Sanity: only the AGENT_PORT-derived occurrences appear (3 total:
|
|
# USER_PORTS env + the two halves of the loopback host:container map).
|
|
occurrences = re.findall(r"\b8765\b", rendered)
|
|
assert len(occurrences) == 3, f"unexpected literal 8765 occurrences: {occurrences}"
|
|
|
|
|
|
def test_urlacl_string_uses_constant() -> None:
|
|
# The urlacl block pushed into the guest gates which SID can bind the
|
|
# listener; if its port drifts from AGENT_PORT we get "address already
|
|
# in use" or a refused bind on the guest side.
|
|
src = guest_sync._URLACL_PS
|
|
assert f"127.0.0.1:{AGENT_PORT}/" in src
|
|
assert f"*:{AGENT_PORT}/" in src
|
|
assert f"+:{AGENT_PORT}/" in src
|