mod docker;
mod filesystem;
mod podman;
use docker::DockerSource;
use filesystem::FilesystemSource;
use crate::Config;
use crate::config::ImageSource;
use crate::image_source::podman::PodmanSource;
use crate::parser::Image;
trait ImageSourcer {
fn get_image(&self, image: &str) -> anyhow::Result<Image>;
fn name(&self) -> &'static str;
}
pub fn resolve_image_from_config(config: &Config) -> anyhow::Result<Image> {
let image_sources: Vec<&dyn ImageSourcer> = match config.image_source() {
ImageSource::Default => {
vec![&FilesystemSource, &DockerSource, &PodmanSource]
}
ImageSource::ForceDocker => vec![&DockerSource],
ImageSource::ForceFS => vec![&FilesystemSource],
ImageSource::ForcePodman => vec![&PodmanSource],
};
if image_sources.is_empty() {
anyhow::bail!("No image sources configured")
}
let mut errors = Vec::new();
for source in &image_sources {
match source.get_image(config.image()) {
Ok(image) => return Ok(image),
Err(e) => {
tracing::debug!(
"Failed to resolve the image using the {} resolver: {}",
source.name(),
e
);
let error_with_context = e
.chain()
.map(|e| format!("{e}"))
.collect::<Vec<_>>()
.join(": ");
errors.push((source.name(), error_with_context));
}
}
}
let joined_errors = errors
.iter()
.map(|(source, error)| format!("- {source}: {error}"))
.collect::<Vec<_>>()
.join("\n");
anyhow::bail!(
"Failed to resolve the image using the configured resolvers:\n{}",
joined_errors
)
}