Skip to content

Commit 56ad1dc

Browse files
committed
refactor: [#272] add MysqlServiceConfig for MySQL service network configuration
- Create MysqlServiceConfig in docker-compose context module - Follow same pattern as CaddyServiceConfig (networks field only) - Update docker-compose template to use mysql variable for network iteration - Ensures consistency across all service configurations
1 parent d508cc7 commit 56ad1dc

4 files changed

Lines changed: 122 additions & 6 deletions

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::domain::prometheus::PrometheusConfig;
77
use super::caddy::CaddyServiceConfig;
88
use super::database::{DatabaseConfig, MysqlSetupConfig, DRIVER_MYSQL, DRIVER_SQLITE};
99
use super::grafana::GrafanaServiceConfig;
10+
use super::mysql::MysqlServiceConfig;
1011
use super::prometheus::PrometheusServiceConfig;
1112
use super::{DockerComposeContext, TrackerServiceConfig};
1213

@@ -118,12 +119,20 @@ impl DockerComposeContextBuilder {
118119
None
119120
};
120121

122+
// Build MySQL service config if enabled
123+
let mysql = if self.database.driver == DRIVER_MYSQL {
124+
Some(MysqlServiceConfig::new())
125+
} else {
126+
None
127+
};
128+
121129
DockerComposeContext {
122130
database: self.database,
123131
tracker: self.tracker,
124132
prometheus,
125133
grafana,
126134
caddy,
135+
mysql,
127136
}
128137
}
129138
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod builder;
1111
mod caddy;
1212
mod database;
1313
mod grafana;
14+
mod mysql;
1415
mod prometheus;
1516
mod tracker;
1617

@@ -19,6 +20,7 @@ pub use builder::DockerComposeContextBuilder;
1920
pub use caddy::CaddyServiceConfig;
2021
pub use database::{DatabaseConfig, MysqlSetupConfig};
2122
pub use grafana::GrafanaServiceConfig;
23+
pub use mysql::MysqlServiceConfig;
2224
pub use prometheus::PrometheusServiceConfig;
2325
pub use tracker::{TrackerPorts, TrackerServiceConfig};
2426

@@ -46,6 +48,12 @@ pub struct DockerComposeContext {
4648
/// This type only contains the docker-compose service definition data.
4749
#[serde(skip_serializing_if = "Option::is_none")]
4850
pub caddy: Option<CaddyServiceConfig>,
51+
/// `MySQL` service configuration (optional)
52+
///
53+
/// Contains network configuration for the `MySQL` service.
54+
/// This is separate from `MysqlSetupConfig` which contains credentials.
55+
#[serde(skip_serializing_if = "Option::is_none")]
56+
pub mysql: Option<MysqlServiceConfig>,
4957
}
5058

5159
impl DockerComposeContext {
@@ -124,6 +132,12 @@ impl DockerComposeContext {
124132
pub fn caddy(&self) -> Option<&CaddyServiceConfig> {
125133
self.caddy.as_ref()
126134
}
135+
136+
/// Get the `MySQL` service configuration if present
137+
#[must_use]
138+
pub fn mysql(&self) -> Option<&MysqlServiceConfig> {
139+
self.mysql.as_ref()
140+
}
127141
}
128142

129143
#[cfg(test)]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//! `MySQL` service configuration for Docker Compose
2+
//!
3+
//! This module defines the `MySQL` service configuration for the docker-compose.yml template.
4+
//!
5+
//! ## Note on Configuration Separation
6+
//!
7+
//! There are two `MySQL`-related types in the docker-compose context:
8+
//!
9+
//! - `MysqlSetupConfig` (in database.rs): Contains credentials and initialization settings
10+
//! for Docker Compose environment variables (root password, database name, user, etc.)
11+
//!
12+
//! - `MysqlServiceConfig` (this module): Contains service definition settings like networks,
13+
//! following the same pattern as `CaddyServiceConfig`, `PrometheusServiceConfig`, etc.
14+
//!
15+
//! This separation keeps the pattern consistent across all services - each service
16+
//! has its own config type for networks and service-specific settings.
17+
18+
use serde::Serialize;
19+
20+
/// Network names used by the `MySQL` service
21+
const DATABASE_NETWORK: &str = "database_network";
22+
23+
/// `MySQL` service configuration for Docker Compose
24+
///
25+
/// Contains configuration for the `MySQL` service definition in docker-compose.yml.
26+
/// This is intentionally minimal - the actual `MySQL` setup configuration (credentials)
27+
/// is in `MysqlSetupConfig`.
28+
///
29+
/// # Example
30+
///
31+
/// ```rust
32+
/// use torrust_tracker_deployer_lib::infrastructure::templating::docker_compose::template::wrappers::docker_compose::context::MysqlServiceConfig;
33+
///
34+
/// let mysql = MysqlServiceConfig::new();
35+
/// assert_eq!(mysql.networks, vec!["database_network"]);
36+
/// ```
37+
#[derive(Debug, Clone, Serialize, PartialEq)]
38+
pub struct MysqlServiceConfig {
39+
/// Networks this service connects to
40+
///
41+
/// `MySQL` only connects to `database_network` for isolation.
42+
/// Only the tracker can access `MySQL` through this network.
43+
pub networks: Vec<String>,
44+
}
45+
46+
impl MysqlServiceConfig {
47+
/// Creates a new `MysqlServiceConfig` with default networks
48+
///
49+
/// `MySQL` connects to:
50+
/// - `database_network`: For database access by the tracker
51+
#[must_use]
52+
pub fn new() -> Self {
53+
Self {
54+
networks: vec![DATABASE_NETWORK.to_string()],
55+
}
56+
}
57+
}
58+
59+
impl Default for MysqlServiceConfig {
60+
fn default() -> Self {
61+
Self::new()
62+
}
63+
}
64+
65+
#[cfg(test)]
66+
mod tests {
67+
use super::*;
68+
69+
#[test]
70+
fn it_should_create_mysql_config_with_database_network() {
71+
let mysql = MysqlServiceConfig::new();
72+
73+
assert_eq!(mysql.networks, vec!["database_network"]);
74+
}
75+
76+
#[test]
77+
fn it_should_implement_default() {
78+
let mysql = MysqlServiceConfig::default();
79+
80+
assert_eq!(mysql.networks, vec!["database_network"]);
81+
}
82+
83+
#[test]
84+
fn it_should_serialize_to_json() {
85+
let mysql = MysqlServiceConfig::new();
86+
87+
let json = serde_json::to_value(&mysql).expect("serialization should succeed");
88+
89+
assert_eq!(json["networks"][0], "database_network");
90+
}
91+
}

templates/docker-compose/docker-compose.yml.tera

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ services:
6464
# Pinning to a stable release ensures predictable deployments and easier rollback.
6565
image: torrust/tracker:develop
6666
container_name: tracker
67-
{% if database.driver == "mysql" %}
67+
{% if mysql %}
6868
depends_on:
6969
mysql:
7070
condition: service_healthy
@@ -157,7 +157,7 @@ services:
157157
{% endif %}
158158
{% endif %}
159159

160-
{% if database.driver == "mysql" %}
160+
{% if mysql %}
161161
mysql:
162162
<<: *defaults
163163
image: mysql:8.4
@@ -168,7 +168,9 @@ services:
168168
- MYSQL_USER=${MYSQL_USER}
169169
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
170170
networks:
171-
- database_network # Only accessible by tracker
171+
{% for network in mysql.networks %}
172+
- {{ network }}
173+
{% endfor %}
172174
ports:
173175
- "3306:3306"
174176
volumes:
@@ -210,7 +212,7 @@ services:
210212
# See Analysis: docs/analysis/security/docker-network-segmentation-analysis.md
211213

212214
networks:
213-
{% if database.driver == "mysql" %}
215+
{% if mysql %}
214216
database_network:
215217
driver: bridge
216218
{% endif %}
@@ -227,9 +229,9 @@ networks:
227229
driver: bridge
228230
{% endif %}
229231

230-
{% if database.driver == "mysql" or grafana or caddy %}
232+
{% if mysql or grafana or caddy %}
231233
volumes:
232-
{%- if database.driver == "mysql" %}
234+
{%- if mysql %}
233235
mysql_data:
234236
driver: local
235237
{%- endif %}

0 commit comments

Comments
 (0)