From bc75a721a243df55cd4cb869c94b5c99e36d56dd Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Mon, 5 Oct 2026 16:45:32 -0400 Subject: [PATCH] choices: a database option says which variable carries its host The option sets VIKUNJA_DATABASE_HOST=mariadb, right on any compose network but unresolvable when the stack is on host networking (no container DNS). Each database option now also carries hostnames: {mariadb: VIKUNJA_DATABASE_HOST} in x-fjord.choices, so a consumer can point it at 127.0.0.1 there. --- dbuild/choices.py | 8 ++++++++ tests/test_docs.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/dbuild/choices.py b/dbuild/choices.py index fd39882..75b10dc 100644 --- a/dbuild/choices.py +++ b/dbuild/choices.py @@ -122,6 +122,12 @@ class Option: # name), and a jail template file when the engine needs one. director_dep: dict[str, Any] = field(default_factory=dict) env_appjail: dict[str, str] = field(default_factory=dict) + # Service -> the variable that carries its host name (the app's own + # x-daemonless.hostnames, for a service the option adds). env sets the + # service's name, right on any compose network; a consumer that knows + # this map can say 127.0.0.1 instead when every service shares the + # host's network, where no container DNS answers that name. + hostnames: dict[str, str] = field(default_factory=dict) jail_template_file: str = "" jail_template: str = "" @@ -205,6 +211,7 @@ def _database_options(cid: str, c: dict[str, Any], services: dict[str, Any]) -> env_appjail = {v_host: jail.replace("-", "_")} if v_host else {} opts.append(Option(id=eid, label=e["label"], doc=e["doc"], env=env, service_yaml=service_yaml, env_lines=env_lines, director_dep=director_dep, env_appjail=env_appjail, + hostnames={e["service"]: v_host} if v_host else {}, jail_template_file=tpl_file, jail_template=e.get("jail_template", ""))) return opts, env_map @@ -553,6 +560,7 @@ def to_fjord(choices: list[Choice], compose_text: str, compose_data: dict[str, A "id": o.id, "label": o.label, "doc": o.doc, "env": dict(o.env), "defaults": defaults, "secrets": secrets, "services": add, "depends_on": depends, "drop": list(o.drop), + "hostnames": dict(o.hostnames), "ask": [{"name": a.name, "label": a.label, "default": a.default, "type": a.type, "values": dict(a.values)} for a in o.ask], }) out.append({"id": c.id, "kind": c.kind, "label": c.label, "doc": c.doc, "default": c.default, "options": opts}) diff --git a/tests/test_docs.py b/tests/test_docs.py index a2199da..cd9729e 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -733,5 +733,9 @@ def test_choices_for_fjord_database_kind(self): self.assertEqual(pg["depends_on"], {"todo": ["postgres"]}) self.assertEqual(pg["secrets"], ["TODO_DB_PASSWORD"]) self.assertEqual(pg["defaults"]["DATABASE_LOCATION"], "{{base}}/{{stack}}/postgres", "the folder follows the stack, not the app") + # The host variable names the service on a compose network; fjord + # needs the map to say 127.0.0.1 when the stack is on host networking. + self.assertEqual(pg["hostnames"], {"postgres": "TODO_DB_HOST"}) + self.assertEqual(pg["env"]["TODO_DB_HOST"], "postgres") ext = next(o for o in db["options"] if o["id"] == "external") self.assertEqual([a["name"] for a in ext["ask"]][:2], ["TODO_DB_TYPE", "TODO_DB_HOST"])