hypha: cache image config

This commit is contained in:
Alex Zenla 2024-01-18 00:15:36 -08:00
parent 1c92ba54f3
commit e401a2cb2b
No known key found for this signature in database
GPG Key ID: 067B238899B51269
2 changed files with 52 additions and 21 deletions

View File

@ -1,6 +1,6 @@
use crate::image::{ImageInfo, Result}; use crate::image::{ImageInfo, Result};
use log::debug; use log::debug;
use oci_spec::image::ImageManifest; use oci_spec::image::{ImageConfiguration, ImageManifest};
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -17,35 +17,53 @@ impl ImageCache {
pub fn recall(&self, digest: &str) -> Result<Option<ImageInfo>> { pub fn recall(&self, digest: &str) -> Result<Option<ImageInfo>> {
let mut squashfs_path = self.cache_dir.clone(); let mut squashfs_path = self.cache_dir.clone();
let mut config_path = self.cache_dir.clone();
let mut manifest_path = self.cache_dir.clone(); let mut manifest_path = self.cache_dir.clone();
squashfs_path.push(format!("{}.squashfs", digest)); squashfs_path.push(format!("{}.squashfs", digest));
manifest_path.push(format!("{}.json", digest)); manifest_path.push(format!("{}.manifest.json", digest));
Ok(if squashfs_path.exists() && manifest_path.exists() { config_path.push(format!("{}.config.json", digest));
let squashfs_metadata = fs::metadata(&squashfs_path)?; Ok(
let manifest_metadata = fs::metadata(&manifest_path)?; if squashfs_path.exists() && manifest_path.exists() && config_path.exists() {
if squashfs_metadata.is_file() && manifest_metadata.is_file() { let squashfs_metadata = fs::metadata(&squashfs_path)?;
let manifest_text = fs::read_to_string(&manifest_path)?; let manifest_metadata = fs::metadata(&manifest_path)?;
let manifest: ImageManifest = serde_json::from_str(manifest_text.as_str())?; let config_metadata = fs::metadata(&config_path)?;
debug!("cache hit digest={}", digest); if squashfs_metadata.is_file()
Some(ImageInfo::new(squashfs_path.clone(), manifest)?) && manifest_metadata.is_file()
&& config_metadata.is_file()
{
let manifest_text = fs::read_to_string(&manifest_path)?;
let manifest: ImageManifest = serde_json::from_str(&manifest_text)?;
let config_text = fs::read_to_string(&manifest_path)?;
let config: ImageConfiguration = serde_json::from_str(&config_text)?;
debug!("cache hit digest={}", digest);
Some(ImageInfo::new(squashfs_path.clone(), manifest, config)?)
} else {
None
}
} else { } else {
debug!("cache miss digest={}", digest);
None None
} },
} else { )
debug!("cache miss digest={}", digest);
None
})
} }
pub fn store(&self, digest: &str, info: &ImageInfo) -> Result<ImageInfo> { pub fn store(&self, digest: &str, info: &ImageInfo) -> Result<ImageInfo> {
debug!("cache store digest={}", digest); debug!("cache store digest={}", digest);
let mut squashfs_path = self.cache_dir.clone(); let mut squashfs_path = self.cache_dir.clone();
let mut manifest_path = self.cache_dir.clone(); let mut manifest_path = self.cache_dir.clone();
let mut config_path = self.cache_dir.clone();
squashfs_path.push(format!("{}.squashfs", digest)); squashfs_path.push(format!("{}.squashfs", digest));
manifest_path.push(format!("{}.json", digest)); manifest_path.push(format!("{}.manifest.json", digest));
config_path.push(format!("{}.config.json", digest));
fs::copy(&info.squashfs, &squashfs_path)?; fs::copy(&info.squashfs, &squashfs_path)?;
let manifest_text = serde_json::to_string_pretty(&info.manifest)?; let manifest_text = serde_json::to_string_pretty(&info.manifest)?;
fs::write(&manifest_path, manifest_text)?; fs::write(&manifest_path, manifest_text)?;
ImageInfo::new(squashfs_path.clone(), info.manifest.clone()) let config_text = serde_json::to_string_pretty(&info.config)?;
fs::write(&config_path, config_text)?;
ImageInfo::new(
squashfs_path.clone(),
info.manifest.clone(),
info.config.clone(),
)
} }
} }

View File

@ -4,7 +4,7 @@ use crate::error::{HyphaError, Result};
use crate::image::cache::ImageCache; use crate::image::cache::ImageCache;
use backhand::{FilesystemWriter, NodeHeader}; use backhand::{FilesystemWriter, NodeHeader};
use log::{debug, trace}; use log::{debug, trace};
use oci_spec::image::{ImageManifest, MediaType}; use oci_spec::image::{ImageConfiguration, ImageManifest, MediaType};
use ocipkg::distribution::Client; use ocipkg::distribution::Client;
use ocipkg::error::Error; use ocipkg::error::Error;
use ocipkg::{Digest, ImageName}; use ocipkg::{Digest, ImageName};
@ -19,11 +19,20 @@ use walkdir::WalkDir;
pub struct ImageInfo { pub struct ImageInfo {
pub squashfs: PathBuf, pub squashfs: PathBuf,
pub manifest: ImageManifest, pub manifest: ImageManifest,
pub config: ImageConfiguration,
} }
impl ImageInfo { impl ImageInfo {
fn new(squashfs: PathBuf, manifest: ImageManifest) -> Result<ImageInfo> { fn new(
Ok(ImageInfo { squashfs, manifest }) squashfs: PathBuf,
manifest: ImageManifest,
config: ImageConfiguration,
) -> Result<ImageInfo> {
Ok(ImageInfo {
squashfs,
manifest,
config,
})
} }
} }
@ -70,6 +79,10 @@ impl ImageCompiler<'_> {
if let Some(cached) = self.cache.recall(&manifest_digest)? { if let Some(cached) = self.cache.recall(&manifest_digest)? {
return Ok(cached); return Ok(cached);
} }
let config_bytes = client.get_blob(&Digest::new(manifest.config().digest())?)?;
let config: ImageConfiguration = serde_json::from_slice(&config_bytes)?;
for layer in manifest.layers() { for layer in manifest.layers() {
debug!( debug!(
"ImageCompiler download start digest={} size={}", "ImageCompiler download start digest={} size={}",
@ -100,7 +113,7 @@ impl ImageCompiler<'_> {
layer.size() layer.size()
); );
self.squash(image_dir, squash_file)?; self.squash(image_dir, squash_file)?;
let info = ImageInfo::new(squash_file.clone(), manifest.clone())?; let info = ImageInfo::new(squash_file.clone(), manifest.clone(), config)?;
return self.cache.store(&manifest_digest, &info); return self.cache.store(&manifest_digest, &info);
} }
Err(Error::MissingLayer.into()) Err(Error::MissingLayer.into())