origins.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. from harness import * # noqa: F401,F403 — the shared wire helpers
  2. """Goal 8 task 6 (web side): the register handshake stores the daemon's
  3. reported `workspace_root`, and assignment project paths are addressed on
  4. the ASKING saddle's filesystem — the saddle row's root first, then the
  5. SADDLE_PROJECTS_ROOT environment override, then the historical
  6. "/workspace" default. The web app needs NO access to saddle workspaces:
  7. paths are advisory and multi-saddle goals coordinate through origin."""
  8. def run(ctx):
  9. auth, fake, fake_id, fake_token = ctx.auth, ctx.fake, ctx.fake_id, ctx.fake_token
  10. print("== origin decoupling: the handshake stores the reported root ==")
  11. # The primary fake reports /workspace by default; the row carries it
  12. # once registration completes (the stacks bundle's demo project is
  13. # project 1 in every shard).
  14. def saddle_row(name):
  15. return next((s for s in slot_public(auth, "/saddles", "saddles")["saddles"]
  16. if s["name"] == name), None)
  17. primary = saddle_row("fake-saddle")
  18. check(primary is not None, "the primary fake saddle is registered")
  19. if primary is not None:
  20. check(primary.get("workspace_root") == "/workspace",
  21. "the register handshake stores the daemon-reported workspace_root (%r)"
  22. % primary.get("workspace_root"))
  23. print("== origin decoupling: assignment paths follow the ASKING saddle ==")
  24. # A second saddle on its own volume: its daemon reports a DIFFERENT
  25. # workspace root — the fleet's separate-mount deployment shape.
  26. other = FakeSaddle()
  27. other.workspace_root = "/volumes/saddle-b"
  28. other.serve(port=free_port())
  29. saddles_state = slot_public(auth, "/saddles", "saddles")
  30. act(auth, saddles_state["register"], {"name": "volume-b",
  31. "host": "127.0.0.1:%d" % other.port})
  32. check(wait_for(lambda: len(other.register_log) > 0 or False,
  33. timeout=15, what="volume-b /register delivery") is not None,
  34. "the second saddle received /register")
  35. row_b = saddle_row("volume-b")
  36. check(row_b is not None and row_b.get("workspace_root") == "/volumes/saddle-b",
  37. "the second saddle's reported root lands on its row (%r)"
  38. % ((row_b or {}).get("workspace_root")))
  39. # One task on the demo project, dispatched to EACH saddle in turn:
  40. # the assignment's project `path` must sit under the ASKING saddle's
  41. # root, not a shared default.
  42. def path_of(saddle_fake, title):
  43. payloads = [p for p in saddle_fake.start_payloads
  44. if (p.get("task") or {}).get("title") == title]
  45. if not payloads:
  46. return None
  47. co = payloads[-1]["task"].get("co_developed") or []
  48. return co[0].get("path") if co else None
  49. # deterministic routing: a capability each saddle alone carries
  50. saddles_state = slot_public(auth, "/saddles", "saddles")
  51. act(auth, saddles_state["create_capability"], {"name": "primary-vol"})
  52. act(auth, slot_public(auth, "/saddles", "saddles")["create_capability"],
  53. {"name": "volume-b-vol"})
  54. caps = {c["name"]: int(c["id"])
  55. for c in slot_public(auth, "/saddles", "saddles")["capabilities"]}
  56. act(auth, saddle_card(auth, "fake-saddle")["attach_capability"],
  57. {"capability_id": str(caps["primary-vol"])})
  58. act(auth, saddle_card(auth, "volume-b")["attach_capability"],
  59. {"capability_id": str(caps["volume-b-vol"])})
  60. def create_routed(title, cap_name, description):
  61. task_id = create_queued(auth, {"project_id": "1", "title": title,
  62. "description": description, "priority": "2"})
  63. act(auth, task_state(auth, task_id)["attach_capability"],
  64. {"capability_id": str(caps[cap_name])})
  65. wait_for(lambda: [c["name"] for c in
  66. task_state(auth, task_id)["capabilities"]] == [cap_name]
  67. or False, timeout=30, what="%s attached" % cap_name)
  68. return task_id
  69. first = create_routed("Path probe A", "primary-vol",
  70. "Dispatch to the primary volume.")
  71. check(wait_for(lambda: path_of(fake, "Path probe A") is not None,
  72. timeout=40, what="primary-saddle assignment") is not None,
  73. "the primary saddle receives the task")
  74. path_a = path_of(fake, "Path probe A")
  75. check(path_a is not None and path_a.startswith("/workspace/task-"),
  76. "the primary saddle's paths sit under its reported /workspace (%r)" % path_a)
  77. second = create_routed("Path probe B", "volume-b-vol",
  78. "Dispatch to the second volume.")
  79. check(wait_for(lambda: path_of(other, "Path probe B") is not None,
  80. timeout=40, what="volume-b assignment") is not None,
  81. "the volume-b saddle receives the task")
  82. path_b = path_of(other, "Path probe B")
  83. check(path_b is not None and path_b.startswith("/volumes/saddle-b/task-"),
  84. "the volume-b saddle's paths sit under ITS OWN reported root (%r)" % path_b)
  85. check(path_a is not None and path_b is not None
  86. and path_a.split("/task-")[0] != path_b.split("/task-")[0],
  87. "the two saddles' assignments address different volumes")
  88. print("== origin decoupling: the compat fallback chain ==")
  89. # A daemon that does NOT report a workspace_root (pre-task-6 daemon)
  90. # keeps a null root; its paths fall back to SADDLE_PROJECTS_ROOT
  91. # (the harness runs the app with it pointed at the scratch dir).
  92. # The probe task REQUIRES a capability only this saddle carries, so
  93. # the dispatcher deterministically targets it (tag routing).
  94. legacy = FakeSaddle()
  95. legacy.workspace_root = ""
  96. legacy.serve(port=free_port())
  97. saddles_state = slot_public(auth, "/saddles", "saddles")
  98. act(auth, saddles_state["register"],
  99. {"name": "legacy-daemon", "host": "127.0.0.1:%d" % legacy.port})
  100. check(wait_for(lambda: len(legacy.register_log) > 0 or False,
  101. timeout=15, what="legacy /register delivery") is not None,
  102. "the legacy daemon received /register")
  103. row_legacy = saddle_row("legacy-daemon")
  104. check(row_legacy is not None and not row_legacy.get("workspace_root"),
  105. "a daemon reporting no root keeps the column empty (%r)"
  106. % ((row_legacy or {}).get("workspace_root")))
  107. act(auth, slot_public(auth, "/saddles", "saddles")["create_capability"],
  108. {"name": "legacy-only"})
  109. saddles_state = slot_public(auth, "/saddles", "saddles")
  110. legacy_cap = int([c["id"] for c in saddles_state["capabilities"]
  111. if c["name"] == "legacy-only"][0])
  112. legacy_card = saddle_card(auth, "legacy-daemon")
  113. act(auth, legacy_card["attach_capability"], {"capability_id": str(legacy_cap)})
  114. # Create as a DRAFT, attach the capability, THEN enqueue: a queued
  115. # task races the idle-awake primary fake's ask (the dispatch can
  116. # win before the attach lands, and the routed probe then completes
  117. # unrouted — a flake the parking-guard timing shifts exposed).
  118. act(auth, slot_public(auth, "/tasks", "tasks")["create"],
  119. {"project_id": "1", "title": "Path probe C",
  120. "description": "Dispatch to the legacy daemon.", "priority": "4"})
  121. third = int([t["id"] for t in slot_public(auth, "/tasks", "tasks")["tasks"]
  122. if t["title"] == "Path probe C"][0])
  123. act(auth, task_state(auth, third)["attach_capability"],
  124. {"capability_id": str(legacy_cap)})
  125. check(wait_for(lambda: [c["name"] for c in
  126. task_state(auth, third)["capabilities"]] == ["legacy-only"]
  127. or False, timeout=30, what="capability attached") is not None,
  128. "the probe task requires the legacy-only capability")
  129. enqueue_task(auth, third)
  130. check(wait_for(lambda: path_of(legacy, "Path probe C") is not None,
  131. timeout=60, what="legacy-saddle assignment") is not None,
  132. "the legacy saddle receives the task")
  133. path_c = path_of(legacy, "Path probe C")
  134. harness_root = os.path.join(WORK, "workspace")
  135. check(path_c is not None and path_c.startswith(harness_root + "/task-"),
  136. "a null root falls back to SADDLE_PROJECTS_ROOT, not /workspace (%r)" % path_c)