use super::BlueprintSourceHandler;
use super::{BlueprintArgs, BlueprintEnvVars};
use crate::config::BlueprintManagerContext;
use crate::error::{Error, Result};
use crate::rt::ResourceLimits;
use crate::rt::service::Service;
use crate::sources::types::ImageRegistryFetcher;
use blueprint_client_tangle::ConfidentialityPolicy;
use blueprint_core::info;
use blueprint_runner::config::BlueprintEnvironment;
use std::path::{Path, PathBuf};
use tokio::process::Command;
pub struct ContainerSource {
pub fetcher: ImageRegistryFetcher,
pub blueprint_id: u64,
pub blueprint_name: String,
resolved_image: Option<String>,
}
impl ContainerSource {
#[must_use]
pub fn new(fetcher: ImageRegistryFetcher, blueprint_id: u64, blueprint_name: String) -> Self {
Self {
fetcher,
blueprint_id,
blueprint_name,
resolved_image: None,
}
}
}
impl BlueprintSourceHandler for ContainerSource {
async fn fetch(&mut self, _cache_dir: &Path) -> Result<PathBuf> {
if let Some(resolved_image) = &self.resolved_image {
return Ok(PathBuf::from(resolved_image));
}
let registry = self.fetcher.registry.clone();
let image = self.fetcher.image.clone();
let tag = self.fetcher.tag.clone();
let full = format!("{registry}/{image}:{tag}");
info!("Pulling image {full}");
let status = Command::new("docker")
.arg("pull")
.arg(&full)
.status()
.await
.map_err(|e| Error::Other(e.to_string()))?;
if !status.success() {
return Err(Error::Other(format!(
"Docker pull failed for image {full} with exit code: {:?}",
status.code()
)));
}
let ret = PathBuf::from(&full);
self.resolved_image = Some(full);
Ok(ret)
}
async fn spawn(
&mut self,
ctx: &BlueprintManagerContext,
limits: ResourceLimits,
_blueprint_config: &BlueprintEnvironment,
_id: u32,
env: BlueprintEnvVars,
args: BlueprintArgs,
confidentiality_policy: ConfidentialityPolicy,
sub_service_str: &str,
cache_dir: &Path,
runtime_dir: &Path,
) -> Result<Service> {
let image = self.fetch(cache_dir).await?;
Service::new_container(
ctx,
limits,
runtime_dir,
sub_service_str,
image.to_string_lossy().to_string(),
env,
args,
confidentiality_policy,
false,
)
.await
}
fn blueprint_id(&self) -> u64 {
self.blueprint_id
}
fn name(&self) -> String {
self.blueprint_name.clone()
}
}