Skip to content

Commit 1b69af4

Browse files
committed
refactor: [#272] move tracker networks logic from template to Rust
Move conditional network selection from Tera template to pre-computed Rust values. This follows the project pattern of keeping templates simple by computing all logic in Rust. Changes: - Rename TrackerPorts to TrackerServiceConfig (more descriptive) - Add networks: Vec<String> field to TrackerServiceConfig - Add compute_networks() method for metrics/database/proxy networks - Add has_prometheus, has_mysql, has_caddy parameters to constructor - Update template to iterate over tracker.networks list - Rename context field from 'ports' to 'tracker' - Keep TrackerPorts type alias for backward compatibility - Update all tests to use new 7-argument constructor
1 parent 180f364 commit 1b69af4

9 files changed

Lines changed: 187 additions & 99 deletions

File tree

src/application/steps/rendering/docker_compose_templates.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::domain::template::TemplateManager;
3535
use crate::domain::tracker::{DatabaseConfig, TrackerConfig};
3636
use crate::infrastructure::templating::caddy::{CaddyContext, CaddyService};
3737
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::{
38-
DockerComposeContext, DockerComposeContextBuilder, MysqlSetupConfig, TrackerPorts,
38+
DockerComposeContext, DockerComposeContextBuilder, MysqlSetupConfig, TrackerServiceConfig,
3939
};
4040
use crate::infrastructure::templating::docker_compose::template::wrappers::env::EnvContext;
4141
use crate::infrastructure::templating::docker_compose::{
@@ -109,15 +109,15 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
109109
let generator = DockerComposeProjectGenerator::new(&self.build_dir, &self.template_manager);
110110

111111
let admin_token = self.extract_admin_token();
112-
let ports = self.build_tracker_ports();
112+
let tracker = self.build_tracker_config();
113113

114114
// Create contexts based on database configuration
115115
let database_config = self.environment.database_config();
116116
let (env_context, builder) = match database_config {
117-
DatabaseConfig::Sqlite(..) => Self::create_sqlite_contexts(admin_token, ports),
117+
DatabaseConfig::Sqlite(..) => Self::create_sqlite_contexts(admin_token, tracker),
118118
DatabaseConfig::Mysql(mysql_config) => Self::create_mysql_contexts(
119119
admin_token,
120-
ports,
120+
tracker,
121121
mysql_config.port,
122122
mysql_config.database_name.clone(),
123123
mysql_config.username.clone(),
@@ -156,34 +156,68 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
156156
self.environment.admin_token().to_string()
157157
}
158158

159-
fn build_tracker_ports(&self) -> TrackerPorts {
159+
fn build_tracker_config(&self) -> TrackerServiceConfig {
160160
let tracker_config = self.environment.tracker_config();
161161
let user_inputs = &self.environment.context().user_inputs;
162162

163163
let (udp_tracker_ports, http_tracker_ports_without_tls, http_api_port, http_api_has_tls) =
164164
Self::extract_tracker_ports(tracker_config, user_inputs);
165165

166-
TrackerPorts::new(
166+
// Determine which features are enabled (affects tracker networks)
167+
let has_prometheus = self.environment.prometheus_config().is_some();
168+
let has_mysql = matches!(
169+
self.environment.database_config(),
170+
DatabaseConfig::Mysql(..)
171+
);
172+
let has_caddy = self.has_caddy_enabled();
173+
174+
TrackerServiceConfig::new(
167175
udp_tracker_ports,
168176
http_tracker_ports_without_tls,
169177
http_api_port,
170178
http_api_has_tls,
179+
has_prometheus,
180+
has_mysql,
181+
has_caddy,
171182
)
172183
}
173184

185+
/// Check if Caddy is enabled (HTTPS with at least one TLS-configured service)
186+
fn has_caddy_enabled(&self) -> bool {
187+
let user_inputs = &self.environment.context().user_inputs;
188+
189+
// Check if HTTPS is configured
190+
if user_inputs.https.is_none() {
191+
return false;
192+
}
193+
194+
let tracker = &user_inputs.tracker;
195+
196+
// Check if any service has TLS configured
197+
let tracker_api_has_tls = tracker.http_api_tls_domain().is_some();
198+
let http_trackers_have_tls = !tracker.http_trackers_with_tls().is_empty();
199+
let grafana_has_tls = user_inputs
200+
.grafana
201+
.as_ref()
202+
.is_some_and(|g| g.tls_domain().is_some());
203+
204+
// Caddy is enabled if HTTPS is configured AND at least one service has TLS
205+
tracker_api_has_tls || http_trackers_have_tls || grafana_has_tls
206+
}
207+
174208
fn create_sqlite_contexts(
175209
admin_token: String,
176-
ports: TrackerPorts,
210+
tracker: TrackerServiceConfig,
177211
) -> (EnvContext, DockerComposeContextBuilder) {
178212
let env_context = EnvContext::new(admin_token);
179-
let builder = DockerComposeContext::builder(ports);
213+
let builder = DockerComposeContext::builder(tracker);
180214

181215
(env_context, builder)
182216
}
183217

184218
fn create_mysql_contexts(
185219
admin_token: String,
186-
ports: TrackerPorts,
220+
tracker: TrackerServiceConfig,
187221
port: u16,
188222
database_name: String,
189223
username: String,
@@ -208,7 +242,7 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
208242
port,
209243
};
210244

211-
let builder = DockerComposeContext::builder(ports).with_mysql(mysql_config);
245+
let builder = DockerComposeContext::builder(tracker).with_mysql(mysql_config);
212246

213247
(env_context, builder)
214248
}

src/infrastructure/templating/docker_compose/template/renderer/docker_compose.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,19 @@ mod tests {
189189
use tempfile::TempDir;
190190

191191
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::{
192-
DockerComposeContext, MysqlSetupConfig, TrackerPorts,
192+
DockerComposeContext, MysqlSetupConfig, TrackerServiceConfig,
193193
};
194194

195-
/// Helper to create `TrackerPorts` for tests (no TLS)
196-
fn test_tracker_ports() -> TrackerPorts {
197-
TrackerPorts::new(
195+
/// Helper to create `TrackerServiceConfig` for tests (no TLS, no networks)
196+
fn test_tracker_config() -> TrackerServiceConfig {
197+
TrackerServiceConfig::new(
198198
vec![6868, 6969], // UDP ports
199199
vec![7070], // HTTP ports without TLS
200200
1212, // API port
201201
false, // API has no TLS
202+
false, // has_prometheus
203+
false, // has_mysql
204+
false, // has_caddy
202205
)
203206
}
204207

@@ -224,15 +227,15 @@ mod tests {
224227
let temp_dir = TempDir::new().unwrap();
225228
let template_manager = Arc::new(TemplateManager::new(temp_dir.path()));
226229

227-
let ports = test_tracker_ports();
230+
let tracker = test_tracker_config();
228231
let mysql_config = MysqlSetupConfig {
229232
root_password: "rootpass123".to_string(),
230233
database: "tracker_db".to_string(),
231234
user: "tracker_user".to_string(),
232235
password: "userpass123".to_string(),
233236
port: 3306,
234237
};
235-
let mysql_context = DockerComposeContext::builder(ports)
238+
let mysql_context = DockerComposeContext::builder(tracker)
236239
.with_mysql(mysql_config)
237240
.build();
238241

@@ -310,8 +313,8 @@ mod tests {
310313
let temp_dir = TempDir::new().unwrap();
311314
let template_manager = Arc::new(TemplateManager::new(temp_dir.path()));
312315

313-
let ports = test_tracker_ports();
314-
let sqlite_context = DockerComposeContext::builder(ports).build();
316+
let tracker = test_tracker_config();
317+
let sqlite_context = DockerComposeContext::builder(tracker).build();
315318

316319
let renderer = DockerComposeRenderer::new(template_manager);
317320
let output_dir = TempDir::new().unwrap();
@@ -349,10 +352,19 @@ mod tests {
349352
let temp_dir = TempDir::new().unwrap();
350353
let template_manager = Arc::new(TemplateManager::new(temp_dir.path()));
351354

352-
let ports = test_tracker_ports();
355+
// Create tracker config with prometheus enabled
356+
let tracker = TrackerServiceConfig::new(
357+
vec![6868, 6969], // UDP ports
358+
vec![7070], // HTTP ports without TLS
359+
1212, // API port
360+
false, // API has no TLS
361+
true, // has_prometheus
362+
false, // has_mysql
363+
false, // has_caddy
364+
);
353365
let prometheus_config =
354366
PrometheusConfig::new(std::num::NonZeroU32::new(15).expect("15 is non-zero"));
355-
let context = DockerComposeContext::builder(ports)
367+
let context = DockerComposeContext::builder(tracker)
356368
.with_prometheus(prometheus_config)
357369
.build();
358370

@@ -417,7 +429,7 @@ mod tests {
417429
let temp_dir = TempDir::new().unwrap();
418430
let template_manager = Arc::new(TemplateManager::new(temp_dir.path()));
419431

420-
let context = DockerComposeContext::builder(test_tracker_ports()).build();
432+
let context = DockerComposeContext::builder(test_tracker_config()).build();
421433

422434
let renderer = DockerComposeRenderer::new(template_manager);
423435
let output_dir = TempDir::new().unwrap();

src/infrastructure/templating/docker_compose/template/renderer/project_generator.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ mod tests {
185185
use tempfile::TempDir;
186186

187187
use super::*;
188-
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::TrackerPorts;
188+
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::TrackerServiceConfig;
189189
use crate::infrastructure::templating::docker_compose::DOCKER_COMPOSE_SUBFOLDER;
190190

191191
/// Creates a `TemplateManager` that uses the embedded templates
@@ -207,13 +207,16 @@ mod tests {
207207
/// Helper function to create a test docker-compose context with `SQLite`
208208
fn create_test_docker_compose_context_sqlite() -> DockerComposeContext {
209209
// Use default test ports (matching TrackerConfig::default())
210-
let ports = TrackerPorts::new(
210+
let tracker = TrackerServiceConfig::new(
211211
vec![6969], // UDP ports
212212
vec![7070], // HTTP ports without TLS
213213
1212, // API port
214214
false, // API has no TLS
215+
false, // has_prometheus
216+
false, // has_mysql
217+
false, // has_caddy
215218
);
216-
DockerComposeContext::builder(ports).build()
219+
DockerComposeContext::builder(tracker).build()
217220
}
218221

219222
#[tokio::test]

src/infrastructure/templating/docker_compose/template/wrappers/docker_compose/context/builder.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ use crate::domain::prometheus::PrometheusConfig;
66
use crate::infrastructure::templating::caddy::CaddyContext;
77

88
use super::database::{DatabaseConfig, MysqlSetupConfig, DRIVER_MYSQL, DRIVER_SQLITE};
9-
use super::{DockerComposeContext, TrackerPorts};
9+
use super::{DockerComposeContext, TrackerServiceConfig};
1010

1111
/// Builder for `DockerComposeContext`
1212
///
1313
/// Provides a fluent API for constructing Docker Compose contexts with optional features.
1414
/// Defaults to `SQLite` database configuration.
1515
pub struct DockerComposeContextBuilder {
16-
ports: TrackerPorts,
16+
tracker: TrackerServiceConfig,
1717
database: DatabaseConfig,
1818
prometheus_config: Option<PrometheusConfig>,
1919
grafana_config: Option<GrafanaConfig>,
@@ -23,9 +23,9 @@ pub struct DockerComposeContextBuilder {
2323

2424
impl DockerComposeContextBuilder {
2525
/// Creates a new builder with default `SQLite` configuration
26-
pub(super) fn new(ports: TrackerPorts) -> Self {
26+
pub(super) fn new(tracker: TrackerServiceConfig) -> Self {
2727
Self {
28-
ports,
28+
tracker,
2929
database: DatabaseConfig {
3030
driver: DRIVER_SQLITE.to_string(),
3131
mysql: None,
@@ -102,7 +102,7 @@ impl DockerComposeContextBuilder {
102102
pub fn build(self) -> DockerComposeContext {
103103
DockerComposeContext {
104104
database: self.database,
105-
ports: self.ports,
105+
tracker: self.tracker,
106106
prometheus_config: self.prometheus_config,
107107
grafana_config: self.grafana_config,
108108
caddy_config: self.caddy_config,

0 commit comments

Comments
 (0)