atlas_local/client/
get_deployment.rs1use bollard::query_parameters::InspectContainerOptions;
2
3use crate::{
4 client::Client,
5 docker::DockerInspectContainer,
6 models::{Deployment, IntoDeploymentError},
7};
8
9#[derive(Debug, thiserror::Error)]
10pub enum GetDeploymentError {
11 #[error("Failed to inspect container: {0}")]
12 ContainerInspect(#[from] bollard::errors::Error),
13 #[error("The container is not a local Atlas deployment: {0}")]
14 IntoDeployment(#[from] IntoDeploymentError),
15}
16
17impl<D: DockerInspectContainer> Client<D> {
18 pub async fn get_deployment(
24 &self,
25 container_id_or_name: &str,
26 ) -> Result<Deployment, GetDeploymentError> {
27 let container_inspect_response = self
29 .docker
30 .inspect_container(container_id_or_name, None::<InspectContainerOptions>)
31 .await?;
32
33 Ok(container_inspect_response.try_into()?)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use crate::models::{CreationSource, MongodbType, State};
42 use bollard::{
43 errors::Error as BollardError,
44 secret::{
45 ContainerConfig, ContainerInspectResponse, ContainerState, ContainerStateStatusEnum,
46 },
47 };
48 use maplit::hashmap;
49 use mockall::mock;
50 use pretty_assertions::assert_eq;
51 use semver::Version;
52
53 mock! {
54 Docker {}
55
56 impl DockerInspectContainer for Docker {
57 async fn inspect_container(
58 &self,
59 container_id: &str,
60 options: Option<InspectContainerOptions>,
61 ) -> Result<ContainerInspectResponse, BollardError>;
62 }
63 }
64
65 #[tokio::test]
66 async fn test_get_deployment() {
67 let mut mock_docker = MockDocker::new();
69 let container_inspect_response = ContainerInspectResponse {
70 id: Some("test_container_id".to_string()),
71 name: Some("/test-deployment".to_string()),
72 config: Some(ContainerConfig {
73 labels: Some(hashmap! {
74 "mongodb-atlas-local".to_string() => "container".to_string(),
75 "version".to_string() => "8.0.0".to_string(),
76 "mongodb-type".to_string() => "community".to_string(),
77 }),
78 env: Some(vec!["TOOL=ATLASCLI".to_string()]),
79 ..Default::default()
80 }),
81 state: Some(ContainerState {
82 status: Some(ContainerStateStatusEnum::RUNNING),
83 ..Default::default()
84 }),
85 ..Default::default()
86 };
87
88 mock_docker
90 .expect_inspect_container()
91 .with(
92 mockall::predicate::eq("test-deployment"),
93 mockall::predicate::eq(None::<InspectContainerOptions>),
94 )
95 .times(1)
96 .returning(move |_, _| Ok(container_inspect_response.clone()));
97
98 let client = Client::new(mock_docker);
99
100 let result = client.get_deployment("test-deployment").await;
102
103 assert!(result.is_ok());
105
106 assert_eq!(
107 result.unwrap(),
108 Deployment {
109 container_id: "test_container_id".to_string(),
110 name: Some("test-deployment".to_string()),
111 state: State::Running,
112 mongodb_type: MongodbType::Community,
113 mongodb_version: Version::new(8, 0, 0),
114 port_bindings: None,
115 creation_source: Some(CreationSource::AtlasCLI),
116 local_seed_location: None,
117 mongodb_initdb_database: None,
118 mongodb_initdb_root_password_file: None,
119 mongodb_initdb_root_password: None,
120 mongodb_initdb_root_username_file: None,
121 mongodb_initdb_root_username: None,
122 mongodb_load_sample_data: None,
123 voyage_api_key: None,
124 mongot_log_file: None,
125 runner_log_file: None,
126 do_not_track: false,
127 telemetry_base_url: None,
128 }
129 );
130 }
131
132 #[tokio::test]
133 async fn test_get_deployment_container_inspect_error() {
134 let mut mock_docker = MockDocker::new();
136
137 mock_docker
139 .expect_inspect_container()
140 .with(
141 mockall::predicate::eq("nonexistent-deployment"),
142 mockall::predicate::eq(None::<InspectContainerOptions>),
143 )
144 .times(1)
145 .returning(|_, _| {
146 Err(BollardError::DockerResponseServerError {
147 status_code: 404,
148 message: "No such container".to_string(),
149 })
150 });
151
152 let client = Client::new(mock_docker);
153
154 let result = client.get_deployment("nonexistent-deployment").await;
156
157 assert!(result.is_err());
159 assert!(matches!(
160 result.unwrap_err(),
161 GetDeploymentError::ContainerInspect(_)
162 ));
163 }
164
165 #[tokio::test]
166 async fn test_get_deployment_into_deployment_error() {
167 let mut mock_docker = MockDocker::new();
169 let container_inspect_response = ContainerInspectResponse {
170 id: Some("test_container_id".to_string()),
171 name: Some("/test-deployment".to_string()),
172 config: Some(ContainerConfig {
173 labels: None, ..Default::default()
175 }),
176 ..Default::default()
177 };
178
179 mock_docker
181 .expect_inspect_container()
182 .with(
183 mockall::predicate::eq("invalid-deployment"),
184 mockall::predicate::eq(None::<InspectContainerOptions>),
185 )
186 .times(1)
187 .returning(move |_, _| Ok(container_inspect_response.clone()));
188
189 let client = Client::new(mock_docker);
190
191 let result = client.get_deployment("invalid-deployment").await;
193
194 assert!(result.is_err());
196 assert!(matches!(
197 result.unwrap_err(),
198 GetDeploymentError::IntoDeployment(_)
199 ));
200 }
201}