From e401a2cb2bb9826fb738c4173b258a6a34efc37b Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Thu, 18 Jan 2024 00:15:36 -0800 Subject: [PATCH] hypha: cache image config --- hypha/src/image/cache.rs | 52 +++++++++++++++++++++++++++------------- hypha/src/image/mod.rs | 21 ++++++++++++---- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/hypha/src/image/cache.rs b/hypha/src/image/cache.rs index 0a4702e..8f556ad 100644 --- a/hypha/src/image/cache.rs +++ b/hypha/src/image/cache.rs @@ -1,6 +1,6 @@ use crate::image::{ImageInfo, Result}; use log::debug; -use oci_spec::image::ImageManifest; +use oci_spec::image::{ImageConfiguration, ImageManifest}; use std::fs; use std::path::{Path, PathBuf}; @@ -17,35 +17,53 @@ impl ImageCache { pub fn recall(&self, digest: &str) -> Result> { let mut squashfs_path = self.cache_dir.clone(); + let mut config_path = self.cache_dir.clone(); let mut manifest_path = self.cache_dir.clone(); squashfs_path.push(format!("{}.squashfs", digest)); - manifest_path.push(format!("{}.json", digest)); - Ok(if squashfs_path.exists() && manifest_path.exists() { - let squashfs_metadata = fs::metadata(&squashfs_path)?; - let manifest_metadata = fs::metadata(&manifest_path)?; - if squashfs_metadata.is_file() && manifest_metadata.is_file() { - let manifest_text = fs::read_to_string(&manifest_path)?; - let manifest: ImageManifest = serde_json::from_str(manifest_text.as_str())?; - debug!("cache hit digest={}", digest); - Some(ImageInfo::new(squashfs_path.clone(), manifest)?) + manifest_path.push(format!("{}.manifest.json", digest)); + config_path.push(format!("{}.config.json", digest)); + Ok( + if squashfs_path.exists() && manifest_path.exists() && config_path.exists() { + let squashfs_metadata = fs::metadata(&squashfs_path)?; + let manifest_metadata = fs::metadata(&manifest_path)?; + let config_metadata = fs::metadata(&config_path)?; + if squashfs_metadata.is_file() + && 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 { + debug!("cache miss digest={}", digest); None - } - } else { - debug!("cache miss digest={}", digest); - None - }) + }, + ) } pub fn store(&self, digest: &str, info: &ImageInfo) -> Result { debug!("cache store digest={}", digest); let mut squashfs_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)); - 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)?; let manifest_text = serde_json::to_string_pretty(&info.manifest)?; 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(), + ) } } diff --git a/hypha/src/image/mod.rs b/hypha/src/image/mod.rs index 9dc581d..73ef13b 100644 --- a/hypha/src/image/mod.rs +++ b/hypha/src/image/mod.rs @@ -4,7 +4,7 @@ use crate::error::{HyphaError, Result}; use crate::image::cache::ImageCache; use backhand::{FilesystemWriter, NodeHeader}; use log::{debug, trace}; -use oci_spec::image::{ImageManifest, MediaType}; +use oci_spec::image::{ImageConfiguration, ImageManifest, MediaType}; use ocipkg::distribution::Client; use ocipkg::error::Error; use ocipkg::{Digest, ImageName}; @@ -19,11 +19,20 @@ use walkdir::WalkDir; pub struct ImageInfo { pub squashfs: PathBuf, pub manifest: ImageManifest, + pub config: ImageConfiguration, } impl ImageInfo { - fn new(squashfs: PathBuf, manifest: ImageManifest) -> Result { - Ok(ImageInfo { squashfs, manifest }) + fn new( + squashfs: PathBuf, + manifest: ImageManifest, + config: ImageConfiguration, + ) -> Result { + Ok(ImageInfo { + squashfs, + manifest, + config, + }) } } @@ -70,6 +79,10 @@ impl ImageCompiler<'_> { if let Some(cached) = self.cache.recall(&manifest_digest)? { 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() { debug!( "ImageCompiler download start digest={} size={}", @@ -100,7 +113,7 @@ impl ImageCompiler<'_> { layer.size() ); 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); } Err(Error::MissingLayer.into())