mirror of
https://github.com/marcoallegretti/karapace.git
synced 2026-03-26 21:43:09 +00:00
cli: make snapshots output restorable
The snapshots command printed a snapshot layer internal ID that restore cannot use. Compute and display the stored layer manifest hash so it can be copy/pasted into restore. JSON output now includes restore_hash. Add an integration test covering commit -> snapshots -> restore.
This commit is contained in:
parent
b73fd9eaec
commit
7278d9923d
2 changed files with 92 additions and 12 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use super::{json_pretty, resolve_env_id, resolve_env_id_pretty, EXIT_SUCCESS};
|
||||
use karapace_core::Engine;
|
||||
use karapace_store::StoreLayout;
|
||||
use karapace_store::{LayerStore, StoreLayout};
|
||||
use std::path::Path;
|
||||
|
||||
pub fn run(engine: &Engine, store_path: &Path, env_id: &str, json: bool) -> Result<u8, String> {
|
||||
|
|
@ -16,16 +16,16 @@ pub fn run(engine: &Engine, store_path: &Path, env_id: &str, json: bool) -> Resu
|
|||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if json {
|
||||
let entries: Vec<_> = snapshots
|
||||
.iter()
|
||||
.map(|s| {
|
||||
serde_json::json!({
|
||||
"hash": s.hash,
|
||||
"tar_hash": s.tar_hash,
|
||||
"parent": s.parent,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let mut entries = Vec::new();
|
||||
for s in &snapshots {
|
||||
let restore_hash = LayerStore::compute_hash(s).map_err(|e| e.to_string())?;
|
||||
entries.push(serde_json::json!({
|
||||
"hash": s.hash,
|
||||
"restore_hash": restore_hash,
|
||||
"tar_hash": s.tar_hash,
|
||||
"parent": s.parent,
|
||||
}));
|
||||
}
|
||||
let payload = serde_json::json!({
|
||||
"env_id": resolved,
|
||||
"snapshots": entries,
|
||||
|
|
@ -36,7 +36,8 @@ pub fn run(engine: &Engine, store_path: &Path, env_id: &str, json: bool) -> Resu
|
|||
} else {
|
||||
println!("snapshots for {env_id}:");
|
||||
for s in &snapshots {
|
||||
println!(" {} (tar: {})", &s.hash[..12], &s.tar_hash[..12]);
|
||||
let restore_hash = LayerStore::compute_hash(s).map_err(|e| e.to_string())?;
|
||||
println!(" {} (tar: {})", restore_hash, &s.tar_hash[..12]);
|
||||
}
|
||||
}
|
||||
Ok(EXIT_SUCCESS)
|
||||
|
|
|
|||
|
|
@ -178,6 +178,85 @@ fn cli_build_offline_fails_fast_with_packages() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_snapshots_restore_hash_matches_commit() {
|
||||
let store = temp_store();
|
||||
let project = tempfile::tempdir().unwrap();
|
||||
let manifest = write_minimal_manifest(project.path(), "rolling");
|
||||
|
||||
let build_out = karapace_bin()
|
||||
.args([
|
||||
"--store",
|
||||
&store.path().to_string_lossy(),
|
||||
"--json",
|
||||
"build",
|
||||
&manifest.to_string_lossy(),
|
||||
"--name",
|
||||
"demo",
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(build_out.status.success());
|
||||
|
||||
let commit_out = karapace_bin()
|
||||
.args([
|
||||
"--store",
|
||||
&store.path().to_string_lossy(),
|
||||
"--json",
|
||||
"commit",
|
||||
"demo",
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
commit_out.status.success(),
|
||||
"commit must exit 0. stderr: {}",
|
||||
String::from_utf8_lossy(&commit_out.stderr)
|
||||
);
|
||||
let commit_stdout = String::from_utf8_lossy(&commit_out.stdout);
|
||||
let commit_json: serde_json::Value = serde_json::from_str(&commit_stdout)
|
||||
.unwrap_or_else(|e| panic!("commit --json must produce valid JSON: {e}\n{commit_stdout}"));
|
||||
let commit_hash = commit_json["snapshot_hash"].as_str().unwrap().to_owned();
|
||||
|
||||
let snaps_out = karapace_bin()
|
||||
.args([
|
||||
"--store",
|
||||
&store.path().to_string_lossy(),
|
||||
"--json",
|
||||
"snapshots",
|
||||
"demo",
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
snaps_out.status.success(),
|
||||
"snapshots must exit 0. stderr: {}",
|
||||
String::from_utf8_lossy(&snaps_out.stderr)
|
||||
);
|
||||
let snaps_stdout = String::from_utf8_lossy(&snaps_out.stdout);
|
||||
let snaps_json: serde_json::Value = serde_json::from_str(&snaps_stdout).unwrap_or_else(|e| {
|
||||
panic!("snapshots --json must produce valid JSON: {e}\nstdout: {snaps_stdout}")
|
||||
});
|
||||
let restore_hash = snaps_json["snapshots"][0]["restore_hash"].as_str().unwrap();
|
||||
assert_eq!(restore_hash, commit_hash);
|
||||
|
||||
let restore_out = karapace_bin()
|
||||
.args([
|
||||
"--store",
|
||||
&store.path().to_string_lossy(),
|
||||
"restore",
|
||||
"demo",
|
||||
restore_hash,
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
restore_out.status.success(),
|
||||
"restore must exit 0. stderr: {}",
|
||||
String::from_utf8_lossy(&restore_out.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
// A5: CLI Validation — list with JSON output
|
||||
#[test]
|
||||
fn cli_list_json_output_stable() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue