Skip to content

Commit b219a24

Browse files
committed
docs: add issue specification for #412
1 parent 9fdb9e8 commit b219a24

1 file changed

Lines changed: 188 additions & 0 deletions

File tree

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Bug: UDP Tracker Domains Missing from `provision` Output
2+
3+
**Issue**: #412
4+
**Parent Epic**: None
5+
**Related**: #405 - Deploy Hetzner Demo Tracker and Document the Process
6+
7+
## Overview
8+
9+
The `provision` command output includes a `domains` array listing the configured domain
10+
names for the deployed environment. When UDP trackers have domains configured (via the
11+
`domain` field of `udp_trackers[].domain` in the environment JSON), those domains are
12+
absent from the list. Only HTTP-based service domains appear.
13+
14+
Example observed output (Hetzner demo deployment #405):
15+
16+
```json
17+
{
18+
"domains": [
19+
"http1.torrust-tracker-demo.com",
20+
"http2.torrust-tracker-demo.com",
21+
"api.torrust-tracker-demo.com",
22+
"grafana.torrust-tracker-demo.com"
23+
]
24+
}
25+
```
26+
27+
Expected — UDP domains should also appear:
28+
29+
```json
30+
{
31+
"domains": [
32+
"http1.torrust-tracker-demo.com",
33+
"http2.torrust-tracker-demo.com",
34+
"udp1.torrust-tracker-demo.com",
35+
"udp2.torrust-tracker-demo.com",
36+
"api.torrust-tracker-demo.com",
37+
"grafana.torrust-tracker-demo.com"
38+
]
39+
}
40+
```
41+
42+
The `domains` list is used as a DNS-setup reminder — it tells the operator which
43+
`A`/`AAAA` records need to point at the server IP. A missing UDP domain means the
44+
operator does not know they need to create that DNS record.
45+
46+
## Goals
47+
48+
- [ ] Include UDP tracker domain names in the `domains` list of the `provision` output
49+
- [ ] Ensure the `dns_reminder` view also includes UDP domains
50+
- [ ] Add or update tests to cover UDP domains appearing in both views
51+
52+
## Specifications
53+
54+
### Root Cause
55+
56+
The `domains` field in `ProvisionDetailsData` is populated in
57+
`src/presentation/cli/views/commands/provision/view_data/provision_details.rs` by
58+
calling `services.tls_domain_names()`:
59+
60+
```rust
61+
let domains = if let Some(ip) = environment.instance_ip() {
62+
let tracker_config = environment.tracker_config();
63+
let grafana_config = environment.grafana_config();
64+
let services = ServiceInfo::from_tracker_config(tracker_config, ip, grafana_config);
65+
services
66+
.tls_domain_names() // ← only returns TLS service domains
67+
.iter()
68+
.map(|s| (*s).to_string())
69+
.collect()
70+
} else {
71+
vec![]
72+
};
73+
```
74+
75+
`tls_domain_names()` in
76+
`src/application/command_handlers/show/info/tracker.rs` returns only the `tls_domains`
77+
vector — domains associated with HTTPS services (HTTP trackers with TLS proxy, API with
78+
TLS proxy, Grafana). UDP trackers are not TLS services and are never added to
79+
`tls_domains`.
80+
81+
`ServiceInfo` already stores UDP tracker URLs in `udp_trackers: Vec<String>` (built by
82+
`build_udp_tracker_urls`), but these are full announce URLs
83+
(`udp://udp1.example.com:6969/announce`), not bare domain names. The domain name needs
84+
to be extracted from those URLs, or a separate accessor for UDP domains needs to be
85+
added.
86+
87+
The same issue exists in `dns_reminder.rs` which also calls `tls_domain_names()` to
88+
build the DNS setup hint.
89+
90+
### Solution
91+
92+
Add a method `all_domain_names() -> Vec<&str>` (or rename the existing one) to
93+
`ServiceInfo` that returns:
94+
95+
1. All TLS service domain names (HTTP trackers, API, Grafana) — currently in `tls_domains`
96+
2. All UDP tracker domain names — extracted from `UdpTrackerConfig::domain()` (if set)
97+
98+
The `provision_details.rs` and `dns_reminder.rs` callers are then updated to call the
99+
new method instead of `tls_domain_names()`.
100+
101+
An alternative is to keep `tls_domain_names()` unchanged (it is used for the HTTPS
102+
hint that reads "configure these domains in /etc/hosts or your DNS before enabling TLS")
103+
and introduce a separate `all_domain_names()` accessor used only for the DNS reminder
104+
and provision output `domains` field. This keeps the TLS-specific semantic intact while
105+
fixing the provision output.
106+
107+
### Affected Modules and Types
108+
109+
#### `src/application/command_handlers/show/info/tracker.rs`
110+
111+
- `ServiceInfo`: add `all_domain_names() -> Vec<&str>` that returns TLS domains plus
112+
UDP tracker domains that have a `domain` configured.
113+
- `build_udp_tracker_urls`: no change needed; UDP domains are read directly from
114+
`UdpTrackerConfig::domain()`.
115+
116+
#### `src/presentation/cli/views/commands/provision/view_data/provision_details.rs`
117+
118+
- `From<&Environment<Provisioned>>` implementation: replace the `tls_domain_names()`
119+
call with `all_domain_names()`.
120+
121+
#### `src/presentation/cli/views/commands/provision/view_data/dns_reminder.rs`
122+
123+
- Replace the `tls_domain_names()` call with `all_domain_names()`.
124+
125+
### What Does Not Change
126+
127+
- `tls_domain_names()` is kept as-is for the `show` command's HTTPS/TLS hint, which
128+
should only list TLS domains (the hint is about configuring reverse proxy, not DNS).
129+
- The UDP tracker URLs in `ServiceInfo.udp_trackers` are unchanged.
130+
- The domain name in a UDP tracker config is optional; UDP trackers without a configured
131+
domain produce no entry in `all_domain_names()`.
132+
133+
## Implementation Plan
134+
135+
### Phase 1: Add `all_domain_names()` to `ServiceInfo`
136+
137+
- [ ] In `ServiceInfo` (`tracker.rs`): implement `all_domain_names() -> Vec<&str>` that
138+
returns the union of TLS domain names and UDP tracker domain names (where
139+
`udp.domain()` is `Some`)
140+
- [ ] Keep `tls_domain_names()` unchanged
141+
142+
### Phase 2: Update callers
143+
144+
- [ ] `provision_details.rs`: replace `tls_domain_names()` call with `all_domain_names()`
145+
- [ ] `dns_reminder.rs`: replace `tls_domain_names()` call with `all_domain_names()`
146+
147+
### Phase 3: Tests
148+
149+
- [ ] `tracker.rs`: add test `it_should_return_all_domain_names_including_udp` that
150+
asserts UDP tracker domains appear in `all_domain_names()` when a UDP domain is set
151+
- [ ] `tracker.rs`: add test `it_should_exclude_udp_trackers_without_domain_from_all_domain_names`
152+
that asserts UDP trackers without a `domain` do not appear
153+
- [ ] `provision_details.rs` or `text_view.rs`/`json_view.rs`: update or add test
154+
covering UDP domains in the rendered provision output
155+
- [ ] Run `cargo test` to verify all tests pass
156+
157+
### Phase 4: Linting and pre-commit
158+
159+
- [ ] Run linters: `cargo run --bin linter all`
160+
- [ ] Run pre-commit: `./scripts/pre-commit.sh`
161+
162+
## Acceptance Criteria
163+
164+
> **Note for Contributors**: These criteria define what the PR reviewer will check.
165+
> Use this as your pre-review checklist before submitting the PR to minimize
166+
> back-and-forth iterations.
167+
168+
**Quality Checks**:
169+
170+
- [ ] Pre-commit checks pass: `./scripts/pre-commit.sh`
171+
172+
**Task-Specific Criteria**:
173+
174+
- [ ] `provision` output `domains` array includes UDP tracker domain names when the
175+
environment config supplies a `domain` for UDP trackers
176+
- [ ] `provision` output `domains` array does **not** include entries for UDP trackers
177+
that have no `domain` configured (IP-only UDP trackers)
178+
- [ ] The DNS setup reminder shown after `provision` also includes UDP tracker domains
179+
- [ ] `tls_domain_names()` is unchanged — the HTTPS-specific TLS hint is not affected
180+
- [ ] Unit tests for `all_domain_names()` pass for both the UDP-with-domain and
181+
UDP-without-domain cases
182+
183+
## Related Documentation
184+
185+
- [docs/deployments/hetzner-demo-tracker/commands/provision/bugs.md](../deployments/hetzner-demo-tracker/commands/provision/bugs.md) — original bug report
186+
- [src/application/command_handlers/show/info/tracker.rs](../../src/application/command_handlers/show/info/tracker.rs)`ServiceInfo`, `tls_domain_names()`
187+
- [src/presentation/cli/views/commands/provision/view_data/provision_details.rs](../../src/presentation/cli/views/commands/provision/view_data/provision_details.rs)`ProvisionDetailsData` and its `From` impl
188+
- [src/presentation/cli/views/commands/provision/view_data/dns_reminder.rs](../../src/presentation/cli/views/commands/provision/view_data/dns_reminder.rs) — DNS reminder view

0 commit comments

Comments
 (0)