feature(oci): use local index as resolution cache when appropriate, fixes #289

This commit is contained in:
Alex Zenla 2024-07-31 15:59:02 -07:00
parent 146bda0810
commit f8d17e7473
No known key found for this signature in database
GPG Key ID: 067B238899B51269
9 changed files with 72 additions and 5 deletions

View File

@ -50,7 +50,7 @@ async fn main() -> Result<()> {
let (context, _) = OciProgressContext::create();
let service = OciPackerService::new(None, &cache_dir, platform).await?;
let packed = service
.request(image.clone(), OciPackedFormat::Tar, false, context)
.request(image.clone(), OciPackedFormat::Tar, false, true, context)
.await?;
let annotations = packed
.manifest

View File

@ -38,6 +38,7 @@ impl ImagePullCommand {
ImagePullImageFormat::Tar => OciImageFormat::Tar.into(),
},
overwrite_cache: self.overwrite_cache,
update: true,
})
.await?;
let reply = pull_interactive_progress(response.into_inner()).await?;

View File

@ -34,6 +34,8 @@ pub struct ZoneLaunchCommand {
image_format: LaunchImageFormat,
#[arg(long, help = "Overwrite image cache on pull")]
pull_overwrite_cache: bool,
#[arg(long, help = "Update image on pull")]
pull_update: bool,
#[arg(short, long, help = "Name of the zone")]
name: Option<String>,
#[arg(short, long, default_value_t = 1, help = "vCPUs available to the zone")]
@ -181,6 +183,7 @@ impl ZoneLaunchCommand {
image: image.to_string(),
format: format.into(),
overwrite_cache: self.pull_overwrite_cache,
update: self.pull_update,
})
.await?;
let reply = pull_interactive_progress(response.into_inner()).await?;

View File

@ -448,7 +448,7 @@ impl ControlService for DaemonControlService {
let output = try_stream! {
let mut task = tokio::task::spawn(async move {
our_packer.request(name, format, request.overwrite_cache, context).await
our_packer.request(name, format, request.overwrite_cache, request.update, context).await
});
let abort_handle = task.abort_handle();
let _task_cancel_guard = scopeguard::guard(abort_handle, |handle| {

View File

@ -184,6 +184,7 @@ message PullImageRequest {
string image = 1;
krata.v1.common.OciImageFormat format = 2;
bool overwrite_cache = 3;
bool update = 4;
}
message PullImageReply {

View File

@ -37,7 +37,13 @@ async fn main() -> Result<()> {
});
let service = OciPackerService::new(seed, &cache_dir, OciPlatform::current()).await?;
let packed = service
.request(image.clone(), OciPackedFormat::Squashfs, false, context)
.request(
image.clone(),
OciPackedFormat::Squashfs,
false,
true,
context,
)
.await?;
println!(
"generated squashfs of {} to {}",

View File

@ -4,6 +4,7 @@ use crate::{
schema::OciSchema,
};
use crate::fetch::OciResolvedImage;
use anyhow::Result;
use log::{debug, error};
use oci_spec::image::{
@ -50,6 +51,51 @@ impl OciPackerCache {
Ok(index.manifests().clone())
}
pub async fn resolve(
&self,
name: ImageName,
format: OciPackedFormat,
) -> Result<Option<OciResolvedImage>> {
if name.reference.as_deref() == Some("latest") {
return Ok(None);
}
let name_str = name.to_string();
let index = self.index.read().await;
let mut descriptor: Option<Descriptor> = None;
for manifest in index.manifests() {
let Some(name) = manifest
.annotations()
.clone()
.unwrap_or_default()
.get(ANNOTATION_IMAGE_NAME)
.cloned()
else {
continue;
};
if name == name_str {
descriptor = Some(manifest.clone());
}
}
let Some(descriptor) = descriptor else {
return Ok(None);
};
debug!("resolve hit name={} digest={}", name, descriptor.digest());
self.recall(name, descriptor.digest().as_ref(), format)
.await
.map(|image| {
image.map(|i| OciResolvedImage {
name: i.name,
digest: i.digest,
descriptor: i.descriptor,
manifest: i.manifest,
})
})
}
pub async fn recall(
&self,
name: ImageName,

View File

@ -75,13 +75,23 @@ impl OciPackerService {
name: ImageName,
format: OciPackedFormat,
overwrite: bool,
pull: bool,
progress_context: OciProgressContext,
) -> Result<OciPackedImage> {
let progress = OciProgress::new();
let progress = OciBoundProgress::new(progress_context.clone(), progress);
let mut resolved = None;
if !pull && !overwrite {
resolved = self.cache.resolve(name.clone(), format).await?;
}
let fetcher =
OciImageFetcher::new(self.seed.clone(), self.platform.clone(), progress.clone());
let resolved = fetcher.resolve(name.clone()).await?;
let resolved = if let Some(resolved) = resolved {
resolved
} else {
fetcher.resolve(name.clone()).await?
};
let key = OciPackerTaskKey {
digest: resolved.digest.clone(),
format,

View File

@ -138,7 +138,7 @@ impl VfsNode {
header.set_mode(self.mode);
if let Some(link_name) = self.link_name.as_ref() {
header.set_link_name(&PathBuf::from(link_name))?;
header.set_link_name(PathBuf::from(link_name))?;
}
header.set_size(self.size);
Ok(header)