Skip to content

Commit c44df0c

Browse files
committed
Merge #282: refactor: [#281] strengthen domain invariant enforcement
2ce6c6b refactor: [#281] encapsulate RuntimeOutputs with semantic setters (Jose Celano) 90bc914 refactor: [#281] move EnvironmentParams to domain layer (Jose Celano) f7e342a refactor: [#281] rename Environment constructor to create (Jose Celano) eae2ba6 refactor: [#281] replace to_environment_params with ValidatedEnvironmentParams TryFrom (Jose Celano) 5a28068 docs: [#281] update config README to reflect TryFrom pattern (Jose Celano) 886f2a5 refactor: [#281] replace to_* methods with TryFrom trait for DTO conversions (Jose Celano) 4dd3e37 refactor: [#281] split TrackerServicesView::render into helper methods (Jose Celano) 17903f0 refactor: [#281] simplify ServiceInfo by always computing from tracker config (Jose Celano) 891c818 docs: [#281] mark issue as completed (Jose Celano) 040c38f refactor: [#281] HttpsConfig validated constructor (Proposal #5) (Jose Celano) 07d64de refactor: [#281] UserInputs validated constructor (Proposal #4) (Jose Celano) 7e8174a refactor: [#281] TrackerCoreConfig and DatabaseConfig validation (Proposal #3) (Jose Celano) d8f8b60 refactor: [#281] TrackerConfig validates at construction (Phase 1, Proposal #2) (Jose Celano) 5b2faf3 refactor: [#281] apply validated constructor pattern to tracker config types (Jose Celano) Pull request description: ## Summary Implements the DDD validated constructor pattern for domain types, ensuring invariants are enforced at construction time rather than relying on separate validation calls. Also improves encapsulation across key domain structs. ## Changes ### Phase 0, Proposal 1 (Completed) - Tracker Config Validation Applied the validated constructor pattern to: - **`UdpTrackerConfig`**: Port must be non-zero - **`HttpTrackerConfig`**: Port must be non-zero, TLS requires domain, localhost cannot use TLS - **`HealthCheckApiConfig`**: Port must be non-zero, TLS requires domain, localhost cannot use TLS **Pattern Applied:** - Private fields with getter methods - `::new()` constructors with domain validation - Custom `Deserialize` via serde `deserialize_with` - Domain error types with `help()` method for actionable error messages - `TryFrom<DtoConfig> for DomainConfig` for DTO→Domain conversions ### Phase 0, Proposals 2-6 (Completed) - Core Domain Improvements - **Proposal 2**: `HttpApiConfig` - validated constructor pattern with TLS validation - **Proposal 3**: `HttpApiSection` - `TryFrom` DTO conversion with error propagation - **Proposal 4**: `TrackerSection` - comprehensive `TryFrom` implementation for all nested configs - **Proposal 5**: `ValidatedEnvironmentParams` - replaced 9-element tuple with named struct - **Proposal 6**: `EnvironmentParams` - moved from Application to Domain layer ### Additional Encapsulation (Completed) - **`RuntimeOutputs`**: Made all fields private with semantic setters - `record_provisioning(ip)` - after `provision` command - `record_registration(ip)` - after `register` command - `record_services_started(endpoints)` - after `run` command - Getter methods: `instance_ip()`, `provision_method()`, `service_endpoints()` - Implements `Default` trait ### Files Modified **Domain Layer:** - `src/domain/tracker/config/udp.rs` - Validated constructor pattern - `src/domain/tracker/config/http.rs` - Validated constructor pattern - `src/domain/tracker/config/health_check_api.rs` - Validated constructor pattern - `src/domain/tracker/config/http_api.rs` - Validated constructor pattern - `src/domain/tracker/config/mod.rs` - Updated defaults, tests, helper functions - `src/domain/environment/params.rs` - **NEW** - Moved from Application layer - `src/domain/environment/runtime_outputs.rs` - Encapsulated with semantic setters **Application Layer:** - `*_section.rs` files - Added `TryFrom` implementations - `validated_params.rs` - **NEW** - Named struct replacing tuple - `errors.rs` - Added error variants for invalid configs **Infrastructure Layer:** - Test files updated to use `::new()` constructors and getter methods ## Remaining Work All proposals from Issue #281 are now complete. Additional improvements may include: - [ ] `TrackerConfig` validates at construction (Phase 1) - [ ] `TrackerCoreConfig` database validation (Phase 2) - [ ] `UserInputs` validated constructor (Phase 2) ## Testing - ✅ All lib tests pass - ✅ All doc tests pass - ✅ Pre-commit checks pass (linting, formatting, E2E tests) ## Related Closes #281 ACKs for top commit: josecelano: ACK 2ce6c6b Tree-SHA512: 52453eb56e0082f0f801d801920910e05edb7689df1424c7c442fce304af24ed29f78a642b5bdeba46df63da4e6fbd34325972fa8f5d88bd038551bb05b5db60
2 parents 69c25c3 + 2ce6c6b commit c44df0c

File tree

54 files changed

+4917
-2485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+4917
-2485
lines changed

docs/e2e-testing/manual/grafana-verification.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,8 @@ docker exec <grafana_container_id> env | grep GF_SECURITY_ADMIN_PASSWORD
641641
This was a bug where the configured password wasn't being passed from the environment config to the `.env` file. It was fixed by updating:
642642

643643
- `UserInputs::with_tracker()` to accept optional Prometheus/Grafana configs
644-
- `EnvironmentContext::with_working_dir_and_tracker()` to pass configs through
645-
- `Environment::with_working_dir_and_tracker()` to accept configs
644+
- `EnvironmentContext::create()` to pass configs through
645+
- `Environment::create()` to accept configs
646646
- Create handler to pass configs instead of using defaults
647647

648648
**Solution:**

docs/issues/281-strengthen-domain-invariant-enforcement.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
**Issue**: [#281](https://github.com/torrust/torrust-tracker-deployer/issues/281)
44
**Type**: Refactor
5-
**Status**: In Progress
5+
**Status**: ✅ Completed
66

77
## Overview
88

@@ -34,27 +34,28 @@ See: [`docs/refactors/plans/strengthen-domain-invariant-enforcement.md`](../refa
3434
- [x] `TryFrom<HttpApiSection> for HttpApiConfig`
3535
- [x] Documentation and ADRs
3636

37-
### Phase 1: Tracker Configuration Types
37+
### Phase 1: Tracker Configuration Types
3838

39-
- [ ] `UdpTrackerConfig` - validated constructor, private fields, getters
40-
- [ ] `HttpTrackerConfig` - validated constructor, private fields, getters
41-
- [ ] `HealthCheckApiConfig` - validated constructor, private fields, getters
42-
- [ ] `TryFrom` implementations for each DTO section
39+
- [x] `UdpTrackerConfig` - validated constructor, private fields, getters
40+
- [x] `HttpTrackerConfig` - validated constructor, private fields, getters
41+
- [x] `HealthCheckApiConfig` - validated constructor, private fields, getters
42+
- [x] `TryFrom` implementations for each DTO section
4343

44-
### Phase 2: Cross-Cutting Invariants
44+
### Phase 2: Cross-Cutting Invariants
4545

46-
- [ ] `TrackerCoreConfig` - database configuration validation
47-
- [ ] `TrackerConfig` - validates at construction (socket conflicts)
48-
- [ ] `UserInputs` - validated constructor (Grafana requires Prometheus)
46+
- [x] `TrackerCoreConfig` - database configuration validation
47+
- [x] `TrackerConfig` - validates at construction (socket conflicts)
48+
- [x] `UserInputs` - validated constructor (Grafana requires Prometheus)
49+
- [x] `HttpsConfig` - validated constructor (email validation)
4950

5051
## Acceptance Criteria
5152

52-
- [ ] All domain configuration types use validated constructors
53-
- [ ] All fields are private with getter methods
54-
- [ ] All types implement custom `Deserialize` with validation
55-
- [ ] All DTO→Domain conversions use `TryFrom` trait
56-
- [ ] Validation logic moved from application to domain layer
57-
- [ ] Pre-commit checks pass: `./scripts/pre-commit.sh`
53+
- [x] All domain configuration types use validated constructors
54+
- [x] All fields are private with getter methods
55+
- [x] All types implement custom `Deserialize` with validation
56+
- [x] All DTO→Domain conversions use `TryFrom` trait
57+
- [x] Validation logic moved from application to domain layer
58+
- [x] Pre-commit checks pass: `./scripts/pre-commit.sh`
5859

5960
## Contributing Guide
6061

0 commit comments

Comments
 (0)