Skip to content

Conversation

@josecelano
Copy link
Member

Phase 2: Create DockerComposeTopology Aggregate

Issue: #296
Epic: #287 (Docker Compose Topology Domain Model Refactoring)

Summary

This PR implements Phase 2 of the Docker Compose Topology refactoring, introducing the DockerComposeTopology aggregate and establishing the single source of truth pattern for network derivation.

Changes

P2.1: Service Enum and Aggregate

  • Service enum (src/domain/topology/service.rs): Type-safe service identification with 5 variants:

    • Tracker - Core BitTorrent tracker
    • MySQL - Database service
    • Prometheus - Metrics collection
    • Grafana - Visualization
    • Caddy - TLS proxy
  • DockerComposeTopology aggregate (src/domain/topology/aggregate.rs):

    • Collects all ServiceTopology entries
    • Derives required_networks() from service configurations
    • Ensures deterministic ordering (alphabetical by name)
    • Enforces invariants: no orphan networks
  • ServiceTopology struct: Links services to their network assignments

P2.2: Network Derivation in Context and Template

  • NetworkDefinition type (context/network_definition.rs): Template-friendly network representation

  • Context updates (context/mod.rs, context/builder.rs):

    • Added required_networks field to DockerComposeContext
    • Added derive_required_networks() method in builder
    • Networks collected from all enabled services, deduplicated, sorted
  • Template update (docker-compose.yml.tera):

    • Replaced 4 conditional network blocks with single required_networks loop
    • Before: {%- if mysql %}\n database_network:\n driver: bridge\n{%- endif %}
    • After: {%- for net in required_networks %}\n {{ net.name }}:\n driver: {{ net.driver }}\n{%- endfor %}

Test Coverage

  • 14 new tests for DockerComposeTopology aggregate
  • 12 new tests for Service enum
  • 5 new tests for NetworkDefinition
  • 12 new tests for required_networks derivation in context
  • All 389 unit tests pass
  • All E2E tests pass (infrastructure lifecycle + deployment workflow)

Behavioral Equivalence

The generated docker-compose.yml output is functionally identical before and after this change. The only difference is implementation: networks are now derived from service configurations rather than duplicated in template conditionals.

Files Changed

File Change
src/domain/topology/service.rs NEW - Service enum
src/domain/topology/aggregate.rs NEW - DockerComposeTopology aggregate
src/domain/topology/mod.rs Modified - exports new types
src/domain/mod.rs Modified - re-exports new types
context/network_definition.rs NEW - NetworkDefinition type
context/mod.rs Modified - required_networks field + tests
context/builder.rs Modified - derive_required_networks()
docker-compose.yml.tera Modified - uses required_networks loop

Progress Update

After this PR:

…tworks

P2.1: Service enum and DockerComposeTopology aggregate
- Add Service enum with 5 variants (Tracker, MySQL, Prometheus, Grafana, Caddy)
- Add DockerComposeTopology aggregate with required_networks() derivation
- Add ServiceTopology struct linking services to their networks
- All types are in domain layer (domain/topology/)

P2.2: Network derivation in context and template update
- Add NetworkDefinition type for template context serialization
- Add required_networks field to DockerComposeContext
- Add derive_required_networks() in builder that collects from all services
- Replace conditional network blocks in docker-compose.yml.tera with
  required_networks loop for the global networks: section

This establishes the single source of truth pattern - networks are
derived from service configurations rather than duplicated in template
conditionals.

Links: #296, Epic #287
@josecelano josecelano self-assigned this Jan 25, 2026
@josecelano josecelano marked this pull request as draft January 25, 2026 10:30
The security documentation about three-network segmentation now lives
in src/domain/topology/network.rs where the network logic is defined.
The template now has a simple reference to the Rust module.
…mpose.yml

- Add description() method to Network enum with short purpose strings:
  - Database: "Database isolation: Tracker ↔ MySQL"
  - Metrics: "Metrics scraping: Tracker ↔ Prometheus"
  - Visualization: "Dashboard queries: Prometheus ↔ Grafana"
  - Proxy: "TLS termination: Caddy ↔ backend services"
- Add description field to NetworkDefinition context type
- Update docker-compose.yml.tera to render descriptions as YAML comments
- Add 4 unit tests for network description functionality
- Update draft issue with implementation details

This provides sysadmins with self-documenting configuration files
when they inspect deployed docker-compose.yml on production servers.
- Create draft issue for Phase 3: Port Topology Domain Model
- Update EPIC to include Phase 3 as extension to original 5-PR strategy
- Document that PORT-01 through PORT-11 rules from original plan
  were not included in initial scope but follow same pattern as networks
- Phase 3 will move port exposure logic from templates to domain layer
- Includes cross-service port conflict validation (different scope than
  TrackerConfig internal socket validation)
@josecelano josecelano marked this pull request as ready for review January 25, 2026 11:52
@josecelano
Copy link
Member Author

ACK d51857b

@josecelano josecelano merged commit f614d47 into main Jan 25, 2026
48 checks passed
@josecelano josecelano linked an issue Jan 25, 2026 that may be closed by this pull request
16 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] Phase 2: Create DockerComposeTopology Aggregate (P2.1, P2.2)

2 participants