Skip to main content

rightsize_modules/
spring_cloud_config.rs

1//! A Spring Cloud Config Server container, ready-checked via its actuator health
2//! endpoint.
3//!
4//! Callers wanting the classpath/filesystem-backed environment repository (no
5//! external git remote required — the default, git-backed repository needs a
6//! configured URI to boot at all) should chain
7//! `.with_env("SPRING_PROFILES_ACTIVE", "native")` before `start()`. That decision
8//! belongs to the caller/test, not this module: the module itself does not set this
9//! profile.
10
11use rightsize::{Container, ContainerGuard, Result, Wait};
12
13/// A Spring Cloud Config Server container.
14pub struct SpringCloudConfigContainer(Container);
15
16impl SpringCloudConfigContainer {
17    const PORT: u16 = 8888;
18
19    /// Builds a container from the pinned default image
20    /// (`hyness/spring-cloud-config-server:latest`).
21    pub fn new() -> Self {
22        Self::with_image("hyness/spring-cloud-config-server:latest")
23    }
24
25    /// Builds a container from a caller-chosen image.
26    pub fn with_image(image: &str) -> Self {
27        Self(
28            Container::new(image)
29                .with_exposed_ports(&[Self::PORT])
30                .waiting_for(Wait::for_http("/actuator/health").for_port(Self::PORT))
31                // Paketo's memory calculator sizes this JVM image's fixed regions
32                // (~688M) above microsandbox's default microVM RAM (~450M);
33                // this is the reason with_memory_limit exists on the module.
34                .with_memory_limit(1024),
35        )
36    }
37
38    /// Sets a single environment variable for the container process — a thin
39    /// passthrough to [`Container::with_env`], since this newtype wraps `Container`
40    /// rather than exposing it directly, so this passthrough is how a caller reaches
41    /// the same builder surface. Callers needing the classpath-backed `native`
42    /// profile call this before `start()` — see the module doc.
43    pub fn with_env(mut self, key: &str, value: &str) -> Self {
44        self.0 = self.0.with_env(key, value);
45        self
46    }
47
48    /// Boots the container.
49    pub async fn start(self) -> Result<SpringCloudConfigGuard> {
50        Ok(SpringCloudConfigGuard(self.0.start().await?))
51    }
52}
53
54impl Default for SpringCloudConfigContainer {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60/// The running guard for a [`SpringCloudConfigContainer`].
61pub struct SpringCloudConfigGuard(ContainerGuard);
62
63impl SpringCloudConfigGuard {
64    /// The config server's base URI for the running container.
65    pub fn uri(&self) -> String {
66        format!(
67            "http://{}:{}",
68            self.0.host(),
69            self.0
70                .get_mapped_port(SpringCloudConfigContainer::PORT)
71                .unwrap()
72        )
73    }
74
75    /// Stops and removes the container, releasing its host port.
76    pub async fn stop(self) -> Result<()> {
77        self.0.stop().await
78    }
79}
80
81impl std::ops::Deref for SpringCloudConfigGuard {
82    type Target = ContainerGuard;
83    fn deref(&self) -> &ContainerGuard {
84        &self.0
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn with_image_smoke() {
94        let _ = SpringCloudConfigContainer::new();
95    }
96}