Skip to content

Commit 32d31d7

Browse files
committed
docs: [#220] add ADR for infrastructure module organization
1 parent 901a817 commit 32d31d7

File tree

2 files changed

+163
-6
lines changed

2 files changed

+163
-6
lines changed

docs/codebase-architecture.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,13 +343,17 @@ Application-specific template rendering and configuration for external tools:
343343
-`src/infrastructure/external_tools/tofu/template/renderer/cloud_init.rs` - Cloud-init rendering
344344
-`src/infrastructure/external_tools/tofu/template/wrappers/lxd/` - LXD template wrappers
345345

346-
**Level 3: Remote System Operations:**
346+
**Level 3: Remote System Operations (SSH-based, inside VM):**
347347

348-
-`src/infrastructure/remote_actions/mod.rs` - Remote operations root
349-
-`src/infrastructure/remote_actions/validators/cloud_init.rs` - Validate cloud-init completion
350-
-`src/infrastructure/remote_actions/validators/docker.rs` - Verify Docker installation
351-
-`src/infrastructure/remote_actions/validators/docker_compose.rs` - Validate Docker Compose
352-
-`src/infrastructure/remote_actions/validators/running_services.rs` - Validate tracker services (validates all HTTP tracker instances)
348+
-`src/infrastructure/remote_actions/mod.rs` - Remote operations root (SSH-based validators)
349+
-`src/infrastructure/remote_actions/validators/cloud_init.rs` - Validate cloud-init completion (via SSH)
350+
-`src/infrastructure/remote_actions/validators/docker.rs` - Verify Docker installation (via SSH)
351+
-`src/infrastructure/remote_actions/validators/docker_compose.rs` - Validate Docker Compose (via SSH)
352+
353+
**Level 3: External Validators (E2E, outside VM):**
354+
355+
-`src/infrastructure/external_validators/mod.rs` - External validators root (HTTP-based E2E validation)
356+
-`src/infrastructure/external_validators/running_services.rs` - Validate tracker services externally (validates all HTTP tracker instances via HTTP health checks from test runner)
353357

354358
**Persistence Layer:**
355359

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Infrastructure Module Organization: Execution Context Separation
2+
3+
**Status**: Accepted
4+
**Date**: 2025-12-11
5+
**Deciders**: Development Team
6+
**Issue**: [#220](https://github.com/torrust/torrust-tracker-deployer/issues/220)
7+
8+
## Context
9+
10+
The infrastructure layer contains components that interact with external systems. However, there are two fundamentally different types of external interactions:
11+
12+
1. **SSH-based operations**: Commands executed **inside the VM** via SSH connection
13+
2. **External validation**: HTTP requests made **from outside the VM** to test end-to-end functionality
14+
15+
Previously, both types were mixed in `infrastructure/remote_actions/`, creating architectural confusion:
16+
17+
- `remote_actions/validators/docker.rs` - Executes `docker --version` inside VM via SSH
18+
- `remote_actions/validators/running_services.rs` - Makes HTTP requests to services from outside VM
19+
20+
This mixing obscured the critical distinction of **where the code executes** and **what it validates**.
21+
22+
## Decision
23+
24+
We separate infrastructure modules by execution context:
25+
26+
```text
27+
src/infrastructure/
28+
├── remote_actions/ # SSH-based operations executed INSIDE the VM
29+
│ └── validators/
30+
│ ├── cloud_init.rs
31+
│ ├── docker.rs
32+
│ └── docker_compose.rs
33+
└── external_validators/ # E2E validation from OUTSIDE the VM
34+
└── running_services.rs
35+
```
36+
37+
### Module Purposes
38+
39+
**`remote_actions/`** (SSH-based, inside VM):
40+
41+
- Execute commands via SSH connection inside the VM
42+
- Validate internal VM state and configuration
43+
- Examples: Check if Docker is installed, verify cloud-init completion
44+
- Scope: Internal system state
45+
46+
**`external_validators/`** (HTTP-based, outside VM):
47+
48+
- Make HTTP requests from test runner/deployment machine
49+
- Validate end-to-end service accessibility
50+
- Test network configuration and firewall rules
51+
- Examples: Health check endpoints, service availability tests
52+
- Scope: External accessibility and E2E functionality
53+
54+
## Rationale
55+
56+
### Why Both Remain in Infrastructure Layer (DDD)
57+
58+
Both modules are infrastructure concerns because they:
59+
60+
- Interact with external systems (VMs, networks, services)
61+
- Provide technical capabilities for application layer
62+
- Depend on adapters (SSH client, HTTP client)
63+
- Are not business logic or domain concepts
64+
65+
The distinction is **execution context**, not **DDD layer**.
66+
67+
### Why Separation Improves Architecture
68+
69+
1. **Clarity**: Developers immediately understand where code executes
70+
2. **Testability**: Different testing strategies for SSH vs HTTP operations
71+
3. **Documentation**: Module names self-document their purpose
72+
4. **Maintainability**: Related code grouped by execution context
73+
5. **Discoverability**: New validators know which module to use
74+
75+
### Comparison with Remote Actions Module
76+
77+
| Aspect | `remote_actions/` | `external_validators/` |
78+
| ------------------ | --------------------------------- | ----------------------------- |
79+
| Execution location | Inside VM via SSH | Outside VM (test runner) |
80+
| Connection type | SSH | HTTP/HTTPS |
81+
| Validates | Internal state | External accessibility |
82+
| Examples | Docker version, cloud-init status | Service health, API endpoints |
83+
| Firewall impact | Not validated | Implicitly validated |
84+
85+
## Consequences
86+
87+
### Positive
88+
89+
- **Clear architectural boundaries**: Execution context is explicit
90+
- **Better code organization**: Related validators grouped together
91+
- **Improved documentation**: Module purpose is self-evident
92+
- **Easier testing**: Different strategies for SSH vs HTTP
93+
- **Scalable**: Future validators know which module to use
94+
95+
### Neutral
96+
97+
- **Module proliferation**: More top-level infrastructure modules
98+
- **Import paths change**: Code needs import updates (one-time cost)
99+
100+
### Negative
101+
102+
- **None identified**: This is a pure improvement in organization
103+
104+
## Alternatives Considered
105+
106+
### Alternative 1: Keep Everything in `remote_actions/`
107+
108+
**Rejected because**:
109+
110+
- Mixes fundamentally different execution contexts
111+
- "Remote actions" implies SSH operations, confusing for HTTP validators
112+
- Harder to understand what code does without reading implementation
113+
114+
### Alternative 2: Move to Application Layer Services
115+
116+
**Rejected because**:
117+
118+
- Not business logic or use cases
119+
- Depends on infrastructure adapters (SSH, HTTP clients)
120+
- Violates DDD layer boundaries (application depends on infrastructure)
121+
- `RunningServicesValidator` performs infrastructure concerns (external system validation)
122+
123+
### Alternative 3: Create `e2e_validators/` Instead
124+
125+
**Rejected because**:
126+
127+
- "E2E" describes testing strategy, not execution context
128+
- Less clear than "external" for where code runs
129+
- Could be confused with test helpers
130+
131+
## Implementation
132+
133+
### File Reorganization
134+
135+
1. Create `src/infrastructure/external_validators/mod.rs`
136+
2. Move `running_services.rs` from `remote_actions/validators/` to `external_validators/`
137+
3. Update infrastructure module exports
138+
4. Update all import paths in application and testing code
139+
140+
### Documentation Updates
141+
142+
1. Update `docs/codebase-architecture.md` with new structure
143+
2. Add module-level documentation explaining execution context
144+
3. Update validator documentation to reference execution context
145+
146+
## Related Decisions
147+
148+
- [Port Zero Not Supported](port-zero-not-supported.md) - Validates port configuration
149+
- [DDD Layer Placement](../contributing/ddd-layer-placement.md) - Explains infrastructure layer
150+
151+
## Notes
152+
153+
This refactoring maintains all existing functionality while improving code organization and clarity. The change is purely structural - no behavior changes.

0 commit comments

Comments
 (0)