Skip to content

Commit 5909c0b

Browse files
committed
feat: [#236] extend DockerComposeContext with tracker port fields
- Add udp_tracker_ports, http_tracker_ports, http_api_port fields to DockerComposeContext - Update new_sqlite() and new_mysql() constructors to accept port parameters - Add getter methods for port fields - Implement extract_tracker_ports() helper in RenderDockerComposeTemplatesStep - Update all unit tests to provide port values - Phase 1 complete: Context extended, port extraction implemented
1 parent e575e74 commit 5909c0b

File tree

5 files changed

+119
-11
lines changed

5 files changed

+119
-11
lines changed

src/application/steps/rendering/docker_compose_templates.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use tracing::{info, instrument};
3131

3232
use crate::domain::environment::Environment;
3333
use crate::domain::template::TemplateManager;
34-
use crate::domain::tracker::DatabaseConfig;
34+
use crate::domain::tracker::{DatabaseConfig, TrackerConfig};
3535
use crate::infrastructure::templating::docker_compose::template::wrappers::docker_compose::DockerComposeContext;
3636
use crate::infrastructure::templating::docker_compose::template::wrappers::env::EnvContext;
3737
use crate::infrastructure::templating::docker_compose::{
@@ -70,6 +70,30 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
7070
}
7171
}
7272

73+
/// Extract port numbers from tracker configuration
74+
///
75+
/// Returns a tuple of (`udp_ports`, `http_ports`, `api_port`)
76+
fn extract_tracker_ports(tracker_config: &TrackerConfig) -> (Vec<u16>, Vec<u16>, u16) {
77+
// Extract UDP tracker ports
78+
let udp_ports: Vec<u16> = tracker_config
79+
.udp_trackers
80+
.iter()
81+
.map(|tracker| tracker.bind_address.port())
82+
.collect();
83+
84+
// Extract HTTP tracker ports
85+
let http_ports: Vec<u16> = tracker_config
86+
.http_trackers
87+
.iter()
88+
.map(|tracker| tracker.bind_address.port())
89+
.collect();
90+
91+
// Extract HTTP API port
92+
let api_port = tracker_config.http_api.bind_address.port();
93+
94+
(udp_ports, http_ports, api_port)
95+
}
96+
7397
/// Execute the template rendering step
7498
///
7599
/// This will render Docker Compose templates to the build directory.
@@ -113,12 +137,21 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
113137
.admin_token
114138
.clone();
115139

140+
// Extract tracker ports from configuration
141+
let tracker_config = &self.environment.context().user_inputs.tracker;
142+
let (udp_tracker_ports, http_tracker_ports, http_api_port) =
143+
Self::extract_tracker_ports(tracker_config);
144+
116145
// Create contexts based on database configuration
117146
let database_config = &self.environment.context().user_inputs.tracker.core.database;
118147
let (env_context, docker_compose_context) = match database_config {
119148
DatabaseConfig::Sqlite { .. } => {
120149
let env_context = EnvContext::new(admin_token);
121-
let docker_compose_context = DockerComposeContext::new_sqlite();
150+
let docker_compose_context = DockerComposeContext::new_sqlite(
151+
udp_tracker_ports,
152+
http_tracker_ports,
153+
http_api_port,
154+
);
122155
(env_context, docker_compose_context)
123156
}
124157
DatabaseConfig::Mysql {
@@ -145,6 +178,9 @@ impl<S> RenderDockerComposeTemplatesStep<S> {
145178
username.clone(),
146179
password.clone(),
147180
*port,
181+
udp_tracker_ports,
182+
http_tracker_ports,
183+
http_api_port,
148184
);
149185

150186
(env_context, docker_compose_context)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ mod tests {
218218
"tracker_user".to_string(),
219219
"userpass123".to_string(),
220220
3306,
221+
vec![6868, 6969],
222+
vec![7070],
223+
1212,
221224
);
222225

223226
let renderer = DockerComposeRenderer::new(template_manager);
@@ -294,7 +297,7 @@ mod tests {
294297
let temp_dir = TempDir::new().unwrap();
295298
let template_manager = Arc::new(TemplateManager::new(temp_dir.path()));
296299

297-
let sqlite_context = DockerComposeContext::new_sqlite();
300+
let sqlite_context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
298301

299302
let renderer = DockerComposeRenderer::new(template_manager);
300303
let output_dir = TempDir::new().unwrap();

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ mod tests {
205205

206206
/// Helper function to create a test docker-compose context with `SQLite`
207207
fn create_test_docker_compose_context_sqlite() -> DockerComposeContext {
208-
DockerComposeContext::new_sqlite()
208+
// Use default test ports (matching TrackerConfig::default())
209+
DockerComposeContext::new_sqlite(vec![6969], vec![7070], 1212)
209210
}
210211

211212
#[tokio::test]

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

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,45 @@ pub struct MysqlConfig {
3737
pub struct DockerComposeContext {
3838
/// Database configuration
3939
pub database: DatabaseConfig,
40+
/// UDP tracker ports
41+
pub udp_tracker_ports: Vec<u16>,
42+
/// HTTP tracker ports
43+
pub http_tracker_ports: Vec<u16>,
44+
/// HTTP API port
45+
pub http_api_port: u16,
4046
}
4147

4248
impl DockerComposeContext {
4349
/// Creates a new `DockerComposeContext` with `SQLite` configuration (default)
4450
///
51+
/// # Arguments
52+
///
53+
/// * `udp_tracker_ports` - UDP tracker ports to expose
54+
/// * `http_tracker_ports` - HTTP tracker ports to expose
55+
/// * `http_api_port` - HTTP API port to expose
56+
///
4557
/// # Examples
4658
///
4759
/// ```rust
4860
/// use torrust_tracker_deployer_lib::infrastructure::templating::docker_compose::template::wrappers::docker_compose::DockerComposeContext;
4961
///
50-
/// let context = DockerComposeContext::new_sqlite();
62+
/// let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
5163
/// assert_eq!(context.database().driver(), "sqlite3");
5264
/// ```
5365
#[must_use]
54-
pub fn new_sqlite() -> Self {
66+
pub fn new_sqlite(
67+
udp_tracker_ports: Vec<u16>,
68+
http_tracker_ports: Vec<u16>,
69+
http_api_port: u16,
70+
) -> Self {
5571
Self {
5672
database: DatabaseConfig {
5773
driver: "sqlite3".to_string(),
5874
mysql: None,
5975
},
76+
udp_tracker_ports,
77+
http_tracker_ports,
78+
http_api_port,
6079
}
6180
}
6281

@@ -69,6 +88,9 @@ impl DockerComposeContext {
6988
/// * `user` - `MySQL` user
7089
/// * `password` - `MySQL` password
7190
/// * `port` - `MySQL` port
91+
/// * `udp_tracker_ports` - UDP tracker ports to expose
92+
/// * `http_tracker_ports` - HTTP tracker ports to expose
93+
/// * `http_api_port` - HTTP API port to expose
7294
///
7395
/// # Examples
7496
///
@@ -81,6 +103,9 @@ impl DockerComposeContext {
81103
/// "tracker_user".to_string(),
82104
/// "user_pass".to_string(),
83105
/// 3306,
106+
/// vec![6868, 6969],
107+
/// vec![7070],
108+
/// 1212,
84109
/// );
85110
/// assert_eq!(context.database().driver(), "mysql");
86111
/// ```
@@ -91,6 +116,9 @@ impl DockerComposeContext {
91116
user: String,
92117
password: String,
93118
port: u16,
119+
udp_tracker_ports: Vec<u16>,
120+
http_tracker_ports: Vec<u16>,
121+
http_api_port: u16,
94122
) -> Self {
95123
Self {
96124
database: DatabaseConfig {
@@ -103,6 +131,9 @@ impl DockerComposeContext {
103131
port,
104132
}),
105133
},
134+
udp_tracker_ports,
135+
http_tracker_ports,
136+
http_api_port,
106137
}
107138
}
108139

@@ -111,6 +142,24 @@ impl DockerComposeContext {
111142
pub fn database(&self) -> &DatabaseConfig {
112143
&self.database
113144
}
145+
146+
/// Get the UDP tracker ports
147+
#[must_use]
148+
pub fn udp_tracker_ports(&self) -> &[u16] {
149+
&self.udp_tracker_ports
150+
}
151+
152+
/// Get the HTTP tracker ports
153+
#[must_use]
154+
pub fn http_tracker_ports(&self) -> &[u16] {
155+
&self.http_tracker_ports
156+
}
157+
158+
/// Get the HTTP API port
159+
#[must_use]
160+
pub fn http_api_port(&self) -> u16 {
161+
self.http_api_port
162+
}
114163
}
115164

116165
impl DatabaseConfig {
@@ -133,10 +182,13 @@ mod tests {
133182

134183
#[test]
135184
fn it_should_create_context_with_sqlite_configuration() {
136-
let context = DockerComposeContext::new_sqlite();
185+
let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
137186

138187
assert_eq!(context.database().driver(), "sqlite3");
139188
assert!(context.database().mysql().is_none());
189+
assert_eq!(context.udp_tracker_ports(), &[6868, 6969]);
190+
assert_eq!(context.http_tracker_ports(), &[7070]);
191+
assert_eq!(context.http_api_port(), 1212);
140192
}
141193

142194
#[test]
@@ -147,6 +199,9 @@ mod tests {
147199
"tracker_user".to_string(),
148200
"pass456".to_string(),
149201
3306,
202+
vec![6868, 6969],
203+
vec![7070],
204+
1212,
150205
);
151206

152207
assert_eq!(context.database().driver(), "mysql");
@@ -158,11 +213,15 @@ mod tests {
158213
assert_eq!(mysql.user, "tracker_user");
159214
assert_eq!(mysql.password, "pass456");
160215
assert_eq!(mysql.port, 3306);
216+
217+
assert_eq!(context.udp_tracker_ports(), &[6868, 6969]);
218+
assert_eq!(context.http_tracker_ports(), &[7070]);
219+
assert_eq!(context.http_api_port(), 1212);
161220
}
162221

163222
#[test]
164223
fn it_should_be_serializable_with_sqlite() {
165-
let context = DockerComposeContext::new_sqlite();
224+
let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
166225

167226
let serialized = serde_json::to_string(&context).unwrap();
168227
assert!(serialized.contains("sqlite3"));
@@ -177,6 +236,9 @@ mod tests {
177236
"user".to_string(),
178237
"pass".to_string(),
179238
3306,
239+
vec![6868, 6969],
240+
vec![7070],
241+
1212,
180242
);
181243

182244
let serialized = serde_json::to_string(&context).unwrap();
@@ -196,6 +258,9 @@ mod tests {
196258
"user".to_string(),
197259
"pass".to_string(),
198260
3306,
261+
vec![6868, 6969],
262+
vec![7070],
263+
1212,
199264
);
200265

201266
let cloned = context.clone();

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ services:
9898
let template_file =
9999
File::new("docker-compose.yml.tera", template_content.to_string()).unwrap();
100100

101-
let context = DockerComposeContext::new_sqlite();
101+
let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
102102
let template = DockerComposeTemplate::new(&template_file, context).unwrap();
103103

104104
assert_eq!(template.database().driver(), "sqlite3");
@@ -129,6 +129,9 @@ services:
129129
"user".to_string(),
130130
"pass".to_string(),
131131
3306,
132+
vec![6868, 6969],
133+
vec![7070],
134+
1212,
132135
);
133136
let template = DockerComposeTemplate::new(&template_file, context).unwrap();
134137

@@ -150,7 +153,7 @@ services:
150153
let template_file =
151154
File::new("docker-compose.yml.tera", template_content.to_string()).unwrap();
152155

153-
let context = DockerComposeContext::new_sqlite();
156+
let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
154157
let template = DockerComposeTemplate::new(&template_file, context).unwrap();
155158

156159
// Create temp directory for output
@@ -173,7 +176,7 @@ services:
173176
let template_file =
174177
File::new("docker-compose.yml.tera", template_content.to_string()).unwrap();
175178

176-
let context = DockerComposeContext::new_sqlite();
179+
let context = DockerComposeContext::new_sqlite(vec![6868, 6969], vec![7070], 1212);
177180
let result = DockerComposeTemplate::new(&template_file, context);
178181

179182
assert!(result.is_err());

0 commit comments

Comments
 (0)