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 super::{json_pretty, resolve_env_id, resolve_env_id_pretty, EXIT_SUCCESS};
|
||||||
use karapace_core::Engine;
|
use karapace_core::Engine;
|
||||||
use karapace_store::StoreLayout;
|
use karapace_store::{LayerStore, StoreLayout};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn run(engine: &Engine, store_path: &Path, env_id: &str, json: bool) -> Result<u8, String> {
|
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())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
if json {
|
if json {
|
||||||
let entries: Vec<_> = snapshots
|
let mut entries = Vec::new();
|
||||||
.iter()
|
for s in &snapshots {
|
||||||
.map(|s| {
|
let restore_hash = LayerStore::compute_hash(s).map_err(|e| e.to_string())?;
|
||||||
serde_json::json!({
|
entries.push(serde_json::json!({
|
||||||
"hash": s.hash,
|
"hash": s.hash,
|
||||||
|
"restore_hash": restore_hash,
|
||||||
"tar_hash": s.tar_hash,
|
"tar_hash": s.tar_hash,
|
||||||
"parent": s.parent,
|
"parent": s.parent,
|
||||||
})
|
}));
|
||||||
})
|
}
|
||||||
.collect();
|
|
||||||
let payload = serde_json::json!({
|
let payload = serde_json::json!({
|
||||||
"env_id": resolved,
|
"env_id": resolved,
|
||||||
"snapshots": entries,
|
"snapshots": entries,
|
||||||
|
|
@ -36,7 +36,8 @@ pub fn run(engine: &Engine, store_path: &Path, env_id: &str, json: bool) -> Resu
|
||||||
} else {
|
} else {
|
||||||
println!("snapshots for {env_id}:");
|
println!("snapshots for {env_id}:");
|
||||||
for s in &snapshots {
|
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)
|
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
|
// A5: CLI Validation — list with JSON output
|
||||||
#[test]
|
#[test]
|
||||||
fn cli_list_json_output_stable() {
|
fn cli_list_json_output_stable() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue