Skip to main content

dockertest_server/
server.rs

1/// Contains traits and helper functions for creating servers
2use std::collections::HashMap;
3
4use dockertest::{waitfor::WaitFor, Composition, Image, RunningContainer, Source};
5
6/// A configuration capable of configuring a [Server].
7///
8/// Types that implement this trait are intended to have a one-to-one
9/// relationship with a [Server] as specified by [Server::Config]. The
10/// implementation is left intentionally sparse in order to maximize the process
11/// of creating a container [Composition]. The [generate_composition] helper
12/// function is provided for creating a [Composition] from the usual required
13/// configuration options.
14///
15/// See also [Test][crate::test::Test].
16pub trait Config: Clone + Send + Sync {
17    fn into_composition(self) -> Composition;
18    fn handle(&self) -> &str;
19}
20
21/// A running instance of a specific container generated by a [Config].
22///
23/// Types that implement this trait are intended to have a one-to-one
24/// relationship with a [Config] as specified by [Server::Config]. When a
25/// [Test][crate::test::Test] is created it is passed one or more
26/// [Configs][Config] which determine what containers are brought up during the
27/// test. A [Server] represents a running container within the context of a
28/// single test. This is reflected by the fact that a [Server] is created using
29/// a [Config] as well as the runtime data provided by a [RunningContainer].
30///
31/// Types implementing this trait should provide as much utility to the end-user
32/// as possible for interacting with the running container. For example, if the
33/// container is a web server, this trait should provide functionality for
34/// obtaining it's URL.
35pub trait Server {
36    type Config: Config + 'static;
37
38    fn new(config: &Self::Config, container: &RunningContainer) -> Self;
39}
40
41/// A helper struct for creating [Compositions][Composition] from a set of
42/// common configuration parameters.
43///
44/// This type can be freely cast into a [Composition]. It is only intended for
45/// basic use-cases where limited control over how the [Composition] is
46/// configured is acceptable.
47pub struct ContainerConfig {
48    pub args: Vec<String>,
49    pub env: HashMap<String, String>,
50    pub handle: String,
51    pub name: String,
52    pub source: Source,
53    pub version: String,
54    pub ports: Option<Vec<(u32, u32)>>,
55    pub wait: Option<Box<dyn WaitFor>>,
56    pub bind_mounts: HashMap<String, String>,
57}
58
59#[allow(clippy::from_over_into)] // Only supports one-way casting
60impl Into<Composition> for ContainerConfig {
61    fn into(self) -> Composition {
62        let image = Image::with_repository(self.name)
63            .source(self.source)
64            .tag(self.version);
65        let mut comp = Composition::with_image(image);
66
67        if let Some(p) = self.ports {
68            for pair in p {
69                comp.port_map(pair.0, pair.1);
70            }
71        };
72
73        let mut composition = match self.wait {
74            Some(w) => comp
75                .with_cmd(self.args)
76                .with_env(self.env)
77                .with_wait_for(w)
78                .with_container_name(self.handle),
79            None => comp
80                .with_cmd(self.args)
81                .with_env(self.env)
82                .with_container_name(self.handle),
83        };
84
85        for (container_path, host_path) in &self.bind_mounts {
86            composition.bind_mount(host_path, container_path);
87        }
88        composition
89    }
90}
91
92/// A helper function for generating random handles.
93///
94/// The returned handle is a combination of the given name and a random 10
95/// character string.
96pub fn new_handle(name: &str) -> String {
97    format!("{}{}", name, crate::common::rand_string(10))
98}
99
100#[cfg(test)]
101mod tests {
102    #[test]
103    fn test_new_handle() {
104        let result = super::new_handle("test");
105        assert_eq!(result.len(), 14);
106    }
107}