use bollard::query_parameters::InspectContainerOptions;
use crate::{
client::Client,
docker::{DockerError, DockerInspectContainer},
models::{Deployment, IntoDeploymentError},
};
#[derive(Debug, thiserror::Error)]
pub enum GetDeploymentError {
#[error("Failed to inspect container: {0}")]
ContainerInspect(#[from] DockerError),
#[error("The container is not a local Atlas deployment: {0}")]
IntoDeployment(#[from] IntoDeploymentError),
}
impl<D: DockerInspectContainer> Client<D> {
pub async fn get_deployment(
&self,
container_id_or_name: &str,
) -> Result<Deployment, GetDeploymentError> {
let container_inspect_response = self
.docker
.inspect_container(container_id_or_name, None::<InspectContainerOptions>)
.await?;
Ok(container_inspect_response.try_into()?)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
docker::DockerError,
models::{CreationSource, MongodbType, State},
};
use bollard::models::{
ContainerConfig, ContainerInspectResponse, ContainerState, ContainerStateStatusEnum,
};
use maplit::hashmap;
use mockall::mock;
use pretty_assertions::assert_eq;
use semver::Version;
mock! {
Docker {}
impl DockerInspectContainer for Docker {
async fn inspect_container(
&self,
container_id: &str,
options: Option<InspectContainerOptions>,
) -> Result<ContainerInspectResponse, DockerError>;
}
}
#[tokio::test]
async fn test_get_deployment() {
let mut mock_docker = MockDocker::new();
let container_inspect_response = ContainerInspectResponse {
id: Some("test_container_id".to_string()),
name: Some("/test-deployment".to_string()),
config: Some(ContainerConfig {
labels: Some(hashmap! {
"mongodb-atlas-local".to_string() => "container".to_string(),
"version".to_string() => "8.0.0".to_string(),
"mongodb-type".to_string() => "community".to_string(),
}),
env: Some(vec!["TOOL=ATLASCLI".to_string()]),
..Default::default()
}),
state: Some(ContainerState {
status: Some(ContainerStateStatusEnum::RUNNING),
..Default::default()
}),
..Default::default()
};
mock_docker
.expect_inspect_container()
.with(
mockall::predicate::eq("test-deployment"),
mockall::predicate::eq(None::<InspectContainerOptions>),
)
.times(1)
.returning(move |_, _| Ok(container_inspect_response.clone()));
let client = Client::new(mock_docker);
let result = client.get_deployment("test-deployment").await;
assert!(result.is_ok());
assert_eq!(
result.unwrap(),
Deployment {
container_id: "test_container_id".to_string(),
name: Some("test-deployment".to_string()),
state: State::Running,
mongodb_type: MongodbType::Community,
mongodb_version: Version::new(8, 0, 0),
port_bindings: None,
creation_source: Some(CreationSource::AtlasCLI),
local_seed_location: None,
mongodb_initdb_database: None,
mongodb_initdb_root_password_file: None,
mongodb_initdb_root_password: None,
mongodb_initdb_root_username_file: None,
mongodb_initdb_root_username: None,
mongodb_load_sample_data: None,
voyage_api_key: None,
mongot_log_file: None,
runner_log_file: None,
do_not_track: false,
telemetry_base_url: None,
}
);
}
#[tokio::test]
async fn test_get_deployment_container_inspect_error() {
let mut mock_docker = MockDocker::new();
mock_docker
.expect_inspect_container()
.with(
mockall::predicate::eq("nonexistent-deployment"),
mockall::predicate::eq(None::<InspectContainerOptions>),
)
.times(1)
.returning(|_, _| Err(DockerError::NotFound));
let client = Client::new(mock_docker);
let result = client.get_deployment("nonexistent-deployment").await;
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
GetDeploymentError::ContainerInspect(_)
));
}
#[tokio::test]
async fn test_get_deployment_into_deployment_error() {
let mut mock_docker = MockDocker::new();
let container_inspect_response = ContainerInspectResponse {
id: Some("test_container_id".to_string()),
name: Some("/test-deployment".to_string()),
config: Some(ContainerConfig {
labels: None, ..Default::default()
}),
..Default::default()
};
mock_docker
.expect_inspect_container()
.with(
mockall::predicate::eq("invalid-deployment"),
mockall::predicate::eq(None::<InspectContainerOptions>),
)
.times(1)
.returning(move |_, _| Ok(container_inspect_response.clone()));
let client = Client::new(mock_docker);
let result = client.get_deployment("invalid-deployment").await;
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
GetDeploymentError::IntoDeployment(_)
));
}
}