mirror of
https://github.com/marcoallegretti/karapace.git
synced 2026-03-26 21:43:09 +00:00
fix(schema): avoid panics in manifest canonicalization
Make NormalizedManifest::canonical_json and compute_env_id fallible and propagate serialization errors through core engine code.
This commit is contained in:
parent
c1e2650617
commit
a9c09a369e
3 changed files with 18 additions and 17 deletions
|
|
@ -112,10 +112,10 @@ impl Engine {
|
|||
|
||||
// Use preliminary identity from manifest (not resolved yet).
|
||||
// This is sufficient for the Defined state; build will re-resolve.
|
||||
let identity = compute_env_id(&normalized);
|
||||
let identity = compute_env_id(&normalized)?;
|
||||
|
||||
if !self.meta_store.exists(&identity.env_id) {
|
||||
let manifest_json = normalized.canonical_json();
|
||||
let manifest_json = normalized.canonical_json()?;
|
||||
let manifest_hash = self.obj_store.put(manifest_json.as_bytes())?;
|
||||
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
|
|
@ -225,7 +225,7 @@ impl Engine {
|
|||
// Phase 1: Resolve dependencies through the backend.
|
||||
// This downloads the base image, computes its content digest,
|
||||
// and queries the package manager for exact versions.
|
||||
let preliminary_id = compute_env_id(&normalized);
|
||||
let preliminary_id = compute_env_id(&normalized)?;
|
||||
let preliminary_spec = RuntimeSpec {
|
||||
env_id: preliminary_id.env_id.to_string(),
|
||||
root_path: self
|
||||
|
|
@ -272,7 +272,8 @@ impl Engine {
|
|||
);
|
||||
|
||||
// Phase 3: Build the environment, then capture real filesystem layers.
|
||||
let manifest_hash = self.obj_store.put(normalized.canonical_json().as_bytes())?;
|
||||
let manifest_json = normalized.canonical_json()?;
|
||||
let manifest_hash = self.obj_store.put(manifest_json.as_bytes())?;
|
||||
|
||||
let env_dir = self.layout.env_path(&identity.env_id);
|
||||
|
||||
|
|
@ -639,7 +640,7 @@ impl Engine {
|
|||
if old_env_ids.is_empty() {
|
||||
let manifest = parse_manifest_file(manifest_path)?;
|
||||
let normalized = manifest.normalize()?;
|
||||
let identity = compute_env_id(&normalized);
|
||||
let identity = compute_env_id(&normalized)?;
|
||||
if self.meta_store.exists(&identity.env_id) {
|
||||
old_env_ids.push(identity.env_id.to_string());
|
||||
}
|
||||
|
|
@ -953,7 +954,7 @@ impl Engine {
|
|||
) -> Result<(ManifestV1, NormalizedManifest, EnvIdentity), CoreError> {
|
||||
let manifest = parse_manifest_file(manifest_path)?;
|
||||
let normalized = manifest.normalize()?;
|
||||
let identity = compute_env_id(&normalized);
|
||||
let identity = compute_env_id(&normalized)?;
|
||||
Ok((manifest, normalized, identity))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ pub struct EnvIdentity {
|
|||
/// - Internal lookup during rebuild (to find old environments)
|
||||
///
|
||||
/// After `build`, the env_id stored in metadata comes from the lock file.
|
||||
pub fn compute_env_id(normalized: &NormalizedManifest) -> EnvIdentity {
|
||||
pub fn compute_env_id(normalized: &NormalizedManifest) -> Result<EnvIdentity, serde_json::Error> {
|
||||
let mut hasher = blake3::Hasher::new();
|
||||
|
||||
hasher.update(normalized.canonical_json().as_bytes());
|
||||
hasher.update(normalized.canonical_json()?.as_bytes());
|
||||
|
||||
let base_digest = blake3::hash(normalized.base_image.as_bytes())
|
||||
.to_hex()
|
||||
|
|
@ -71,10 +71,10 @@ pub fn compute_env_id(normalized: &NormalizedManifest) -> EnvIdentity {
|
|||
let hex = hasher.finalize().to_hex().to_string();
|
||||
let short = hex[..12].to_owned();
|
||||
|
||||
EnvIdentity {
|
||||
Ok(EnvIdentity {
|
||||
env_id: EnvId::new(hex),
|
||||
short_id: ShortId::new(short),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -110,7 +110,7 @@ packages = ["clang", "git"]
|
|||
.normalize()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(compute_env_id(&a), compute_env_id(&b));
|
||||
assert_eq!(compute_env_id(&a).unwrap(), compute_env_id(&b).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -141,7 +141,7 @@ packages = ["git", "cmake"]
|
|||
.normalize()
|
||||
.unwrap();
|
||||
|
||||
assert_ne!(compute_env_id(&a), compute_env_id(&b));
|
||||
assert_ne!(compute_env_id(&a).unwrap(), compute_env_id(&b).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -172,7 +172,7 @@ backend = "oci"
|
|||
.normalize()
|
||||
.unwrap();
|
||||
|
||||
assert_ne!(compute_env_id(&a), compute_env_id(&b));
|
||||
assert_ne!(compute_env_id(&a).unwrap(), compute_env_id(&b).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -188,7 +188,7 @@ image = "rolling"
|
|||
.normalize()
|
||||
.unwrap();
|
||||
|
||||
let id = compute_env_id(&n);
|
||||
let id = compute_env_id(&n).unwrap();
|
||||
assert_eq!(id.short_id.as_str().len(), 12);
|
||||
assert!(id.env_id.as_str().starts_with(id.short_id.as_str()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ impl ManifestV1 {
|
|||
}
|
||||
|
||||
impl NormalizedManifest {
|
||||
pub fn canonical_json(&self) -> String {
|
||||
serde_json::to_string(self).expect("normalized manifest serialization is infallible")
|
||||
pub fn canonical_json(&self) -> Result<String, serde_json::Error> {
|
||||
serde_json::to_string(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ packages = ["clang", "git"]
|
|||
.normalize()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(a.canonical_json(), b.canonical_json());
|
||||
assert_eq!(a.canonical_json().unwrap(), b.canonical_json().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue